@kelnishi/satmouse-client 0.17.1 → 0.18.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/dist/elements/index.cjs +81 -36
- package/dist/elements/index.cjs.map +1 -1
- package/dist/elements/index.d.cts +32 -1
- package/dist/elements/index.d.ts +32 -1
- package/dist/elements/index.js +79 -37
- package/dist/elements/index.js.map +1 -1
- package/package.json +1 -1
package/dist/elements/index.cjs
CHANGED
|
@@ -19,6 +19,44 @@ function onManager(fn) {
|
|
|
19
19
|
return () => listeners.delete(fn);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
// src/elements/locale.ts
|
|
23
|
+
var DEFAULT_LOCALE = {
|
|
24
|
+
// satmouse-status
|
|
25
|
+
connected: "Connected",
|
|
26
|
+
connecting: "Connecting...",
|
|
27
|
+
disconnected: "Disconnected",
|
|
28
|
+
notRunning: "Not running",
|
|
29
|
+
extensionRequired: "Extension required",
|
|
30
|
+
launchSatMouse: "Launch SatMouse",
|
|
31
|
+
downloadSatMouse: "Download SatMouse",
|
|
32
|
+
enableExtension: "Enable Extension",
|
|
33
|
+
// satmouse-devices
|
|
34
|
+
noDevices: "No devices",
|
|
35
|
+
flip: "Flip",
|
|
36
|
+
translateScale: "Trans",
|
|
37
|
+
rotateScale: "Rot",
|
|
38
|
+
wScale: "W",
|
|
39
|
+
buttonMappings: "Button Mappings",
|
|
40
|
+
remapKey: "Remap key",
|
|
41
|
+
pressAKey: "Press a key...",
|
|
42
|
+
remove: "Remove",
|
|
43
|
+
addButtonMapping: "+ Add Button Mapping",
|
|
44
|
+
pressDeviceButton: "Press a device button...",
|
|
45
|
+
restoreDefaults: "Restore Defaults",
|
|
46
|
+
// satmouse-debug
|
|
47
|
+
fps: "fps"
|
|
48
|
+
};
|
|
49
|
+
var current = { ...DEFAULT_LOCALE };
|
|
50
|
+
function setLocale(overrides) {
|
|
51
|
+
current = { ...current, ...overrides };
|
|
52
|
+
}
|
|
53
|
+
function getLocale() {
|
|
54
|
+
return current;
|
|
55
|
+
}
|
|
56
|
+
function t(key) {
|
|
57
|
+
return current[key];
|
|
58
|
+
}
|
|
59
|
+
|
|
22
60
|
// src/elements/satmouse-status.ts
|
|
23
61
|
var TEMPLATE = `
|
|
24
62
|
<style>
|
|
@@ -34,9 +72,9 @@ var TEMPLATE = `
|
|
|
34
72
|
|
|
35
73
|
</style>
|
|
36
74
|
<span class="dot"></span>
|
|
37
|
-
<span class="text"
|
|
75
|
+
<span class="text"></span>
|
|
38
76
|
<span class="protocol"></span>
|
|
39
|
-
<button class="launch"
|
|
77
|
+
<button class="launch"></button>
|
|
40
78
|
`;
|
|
41
79
|
var SatMouseStatus = class extends HTMLElement {
|
|
42
80
|
dot;
|
|
@@ -55,6 +93,8 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
55
93
|
this.text = shadow.querySelector(".text");
|
|
56
94
|
this.proto = shadow.querySelector(".protocol");
|
|
57
95
|
this.launch = shadow.querySelector(".launch");
|
|
96
|
+
this.text.textContent = t("disconnected");
|
|
97
|
+
this.launch.textContent = t("launchSatMouse");
|
|
58
98
|
this.launch.addEventListener("click", () => {
|
|
59
99
|
this.startLaunchFlow();
|
|
60
100
|
});
|
|
@@ -63,7 +103,7 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
63
103
|
this.unsub = onManager((mgr) => this.bind(mgr));
|
|
64
104
|
this.stopPoll();
|
|
65
105
|
this.launch.disabled = false;
|
|
66
|
-
this.launch.textContent = "
|
|
106
|
+
this.launch.textContent = t("launchSatMouse");
|
|
67
107
|
}
|
|
68
108
|
disconnectedCallback() {
|
|
69
109
|
this.stopPoll();
|
|
@@ -86,30 +126,30 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
86
126
|
if (state === "connected") {
|
|
87
127
|
this.stopPoll();
|
|
88
128
|
this.showDownload = false;
|
|
89
|
-
this.text.textContent = "
|
|
129
|
+
this.text.textContent = t("connected");
|
|
90
130
|
this.launch.style.display = "none";
|
|
91
131
|
} else if (state === "connecting") {
|
|
92
|
-
this.text.textContent = "
|
|
132
|
+
this.text.textContent = t("connecting");
|
|
93
133
|
this.launch.style.display = "none";
|
|
94
134
|
} else if (state === "failed") {
|
|
95
135
|
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
96
136
|
const hasExtension = !!globalThis.__satmouseExtensionAvailable;
|
|
97
137
|
if (isSafari && !hasExtension) {
|
|
98
|
-
this.text.textContent = "
|
|
138
|
+
this.text.textContent = t("extensionRequired");
|
|
99
139
|
this.launch.style.display = "inline-block";
|
|
100
140
|
this.launch.disabled = false;
|
|
101
|
-
this.launch.textContent = "
|
|
141
|
+
this.launch.textContent = t("enableExtension");
|
|
102
142
|
this.showDownload = false;
|
|
103
143
|
this.needsExtension = true;
|
|
104
144
|
} else {
|
|
105
|
-
this.text.textContent = "
|
|
145
|
+
this.text.textContent = t("notRunning");
|
|
106
146
|
this.launch.style.display = "inline-block";
|
|
107
147
|
this.launch.disabled = false;
|
|
108
|
-
this.launch.textContent = this.showDownload ? "
|
|
148
|
+
this.launch.textContent = this.showDownload ? t("downloadSatMouse") : t("launchSatMouse");
|
|
109
149
|
this.needsExtension = false;
|
|
110
150
|
}
|
|
111
151
|
} else {
|
|
112
|
-
this.text.textContent = "
|
|
152
|
+
this.text.textContent = t("disconnected");
|
|
113
153
|
this.launch.style.display = "none";
|
|
114
154
|
}
|
|
115
155
|
}
|
|
@@ -118,7 +158,7 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
118
158
|
startLaunchFlow() {
|
|
119
159
|
if (this.needsExtension) {
|
|
120
160
|
window.location.href = "satmouse://enable-extension";
|
|
121
|
-
this.launch.textContent = "
|
|
161
|
+
this.launch.textContent = t("connecting");
|
|
122
162
|
this.launch.disabled = true;
|
|
123
163
|
this.stopPoll();
|
|
124
164
|
this.pollTimer = setInterval(() => {
|
|
@@ -131,7 +171,7 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
131
171
|
setTimeout(() => {
|
|
132
172
|
this.stopPoll();
|
|
133
173
|
this.launch.disabled = false;
|
|
134
|
-
this.launch.textContent = "
|
|
174
|
+
this.launch.textContent = t("enableExtension");
|
|
135
175
|
}, 3e4);
|
|
136
176
|
return;
|
|
137
177
|
}
|
|
@@ -139,7 +179,7 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
139
179
|
window.location.href = "https://github.com/kelnishi/SatMouse/releases/latest";
|
|
140
180
|
return;
|
|
141
181
|
}
|
|
142
|
-
this.launch.textContent = "
|
|
182
|
+
this.launch.textContent = t("connecting");
|
|
143
183
|
this.launch.disabled = true;
|
|
144
184
|
this.manager?.retry();
|
|
145
185
|
window.location.href = "satmouse://launch";
|
|
@@ -156,7 +196,7 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
156
196
|
this.stopPoll();
|
|
157
197
|
this.showDownload = true;
|
|
158
198
|
this.launch.disabled = false;
|
|
159
|
-
this.launch.textContent = "
|
|
199
|
+
this.launch.textContent = t("downloadSatMouse");
|
|
160
200
|
return;
|
|
161
201
|
}
|
|
162
202
|
this.manager?.retry();
|
|
@@ -239,7 +279,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
239
279
|
disconnectedCallback() {
|
|
240
280
|
this.unsub?.();
|
|
241
281
|
this.unbind();
|
|
242
|
-
this.container.innerHTML = `<span class="empty"
|
|
282
|
+
this.container.innerHTML = `<span class="empty">${t("noDevices")}</span>`;
|
|
243
283
|
}
|
|
244
284
|
bind(mgr) {
|
|
245
285
|
this.unbind();
|
|
@@ -293,7 +333,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
293
333
|
const cb = document.createElement("input");
|
|
294
334
|
cb.type = "checkbox";
|
|
295
335
|
cb.checked = route.flip ?? false;
|
|
296
|
-
cb.title = "
|
|
336
|
+
cb.title = t("flip");
|
|
297
337
|
const routeIndex = i;
|
|
298
338
|
cb.addEventListener("change", () => {
|
|
299
339
|
this.updateRoute(device.id, routeIndex, deviceAxes, { flip: cb.checked });
|
|
@@ -318,9 +358,9 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
318
358
|
}
|
|
319
359
|
controls.appendChild(routeGroup);
|
|
320
360
|
for (const [label, key, globalKey] of [
|
|
321
|
-
["
|
|
322
|
-
["
|
|
323
|
-
["
|
|
361
|
+
[t("translateScale"), "translateScale", "translateScale"],
|
|
362
|
+
[t("rotateScale"), "rotateScale", "rotateScale"],
|
|
363
|
+
[t("wScale"), "wScale", "wScale"]
|
|
324
364
|
]) {
|
|
325
365
|
const row = document.createElement("div");
|
|
326
366
|
row.className = "slider-row";
|
|
@@ -339,7 +379,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
339
379
|
btnSection.className = "btn-section";
|
|
340
380
|
const btnLabel = document.createElement("div");
|
|
341
381
|
btnLabel.className = "btn-section-label";
|
|
342
|
-
btnLabel.textContent = "
|
|
382
|
+
btnLabel.textContent = t("buttonMappings");
|
|
343
383
|
btnSection.appendChild(btnLabel);
|
|
344
384
|
const buttonRoutes = cfg.buttonRoutes ?? [];
|
|
345
385
|
const labels = device.buttonLabels ?? [];
|
|
@@ -363,17 +403,17 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
363
403
|
const editBtn = document.createElement("button");
|
|
364
404
|
editBtn.className = "btn-remove";
|
|
365
405
|
editBtn.textContent = "\u270E";
|
|
366
|
-
editBtn.title = "
|
|
406
|
+
editBtn.title = t("remapKey");
|
|
367
407
|
const routeIdx = i;
|
|
368
408
|
editBtn.addEventListener("click", () => {
|
|
369
|
-
keySpan.textContent = "
|
|
409
|
+
keySpan.textContent = t("pressAKey");
|
|
370
410
|
keySpan.style.color = "#f39c12";
|
|
371
411
|
const onKey = (e) => {
|
|
372
412
|
e.preventDefault();
|
|
373
413
|
e.stopPropagation();
|
|
374
414
|
document.removeEventListener("keydown", onKey, true);
|
|
375
|
-
const
|
|
376
|
-
const updated =
|
|
415
|
+
const current2 = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];
|
|
416
|
+
const updated = current2.map(
|
|
377
417
|
(r, j) => j === routeIdx ? { ...r, key: e.key, code: e.code } : r
|
|
378
418
|
);
|
|
379
419
|
mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });
|
|
@@ -385,10 +425,10 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
385
425
|
const removeBtn = document.createElement("button");
|
|
386
426
|
removeBtn.className = "btn-remove";
|
|
387
427
|
removeBtn.textContent = "\xD7";
|
|
388
|
-
removeBtn.title = "
|
|
428
|
+
removeBtn.title = t("remove");
|
|
389
429
|
removeBtn.addEventListener("click", () => {
|
|
390
|
-
const
|
|
391
|
-
const updated =
|
|
430
|
+
const current2 = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];
|
|
431
|
+
const updated = current2.filter((_, j) => j !== routeIdx);
|
|
392
432
|
mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });
|
|
393
433
|
this.refreshControls(panel, device);
|
|
394
434
|
});
|
|
@@ -397,7 +437,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
397
437
|
}
|
|
398
438
|
const addBtn = document.createElement("button");
|
|
399
439
|
addBtn.className = "btn-add";
|
|
400
|
-
addBtn.textContent = "
|
|
440
|
+
addBtn.textContent = t("addButtonMapping");
|
|
401
441
|
addBtn.addEventListener("click", () => {
|
|
402
442
|
if (addBtn.classList.contains("listening")) return;
|
|
403
443
|
this.startButtonListen(addBtn, mgr, device, panel);
|
|
@@ -406,7 +446,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
406
446
|
controls.appendChild(btnSection);
|
|
407
447
|
const resetBtn = document.createElement("button");
|
|
408
448
|
resetBtn.className = "reset-btn";
|
|
409
|
-
resetBtn.textContent = "
|
|
449
|
+
resetBtn.textContent = t("restoreDefaults");
|
|
410
450
|
resetBtn.addEventListener("click", () => {
|
|
411
451
|
mgr.resetDeviceConfig(device.id);
|
|
412
452
|
this.refreshControls(panel, device);
|
|
@@ -437,12 +477,12 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
437
477
|
}
|
|
438
478
|
startButtonListen(btn, mgr, device, panel) {
|
|
439
479
|
btn.classList.add("listening");
|
|
440
|
-
btn.textContent = "
|
|
480
|
+
btn.textContent = t("pressDeviceButton");
|
|
441
481
|
const onButton = (event) => {
|
|
442
482
|
if (!event.pressed) return;
|
|
443
483
|
mgr.off("buttonEvent", onButton);
|
|
444
484
|
const capturedButton = event.button;
|
|
445
|
-
btn.textContent = `Btn ${capturedButton} \u2192
|
|
485
|
+
btn.textContent = `Btn ${capturedButton} \u2192 ${t("pressAKey")}`;
|
|
446
486
|
const onKey = (e) => {
|
|
447
487
|
e.preventDefault();
|
|
448
488
|
e.stopPropagation();
|
|
@@ -452,8 +492,8 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
452
492
|
key: e.key,
|
|
453
493
|
code: e.code
|
|
454
494
|
};
|
|
455
|
-
const
|
|
456
|
-
const updated =
|
|
495
|
+
const current2 = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];
|
|
496
|
+
const updated = current2.filter((r) => r.button !== capturedButton);
|
|
457
497
|
updated.push(route);
|
|
458
498
|
mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });
|
|
459
499
|
this.refreshControls(panel, device);
|
|
@@ -466,7 +506,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
466
506
|
mgr.off("buttonEvent", onButton);
|
|
467
507
|
document.removeEventListener("keydown", onCancel, true);
|
|
468
508
|
btn.classList.remove("listening");
|
|
469
|
-
btn.textContent = "
|
|
509
|
+
btn.textContent = t("addButtonMapping");
|
|
470
510
|
}
|
|
471
511
|
};
|
|
472
512
|
document.addEventListener("keydown", onCancel, true);
|
|
@@ -474,7 +514,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
474
514
|
removeDevice(device) {
|
|
475
515
|
this.shadowRoot.getElementById(`dev-${device.id}`)?.remove();
|
|
476
516
|
if (this.container.children.length === 0) {
|
|
477
|
-
this.container.innerHTML = `<span class="empty"
|
|
517
|
+
this.container.innerHTML = `<span class="empty">${t("noDevices")}</span>`;
|
|
478
518
|
}
|
|
479
519
|
}
|
|
480
520
|
};
|
|
@@ -489,7 +529,7 @@ var TEMPLATE2 = `
|
|
|
489
529
|
.value { color: #3498db; text-align: right; min-width: 50px; }
|
|
490
530
|
.meta { color: #7f8c8d; font-size: 11px; padding: 2px 0; }
|
|
491
531
|
</style>
|
|
492
|
-
<div class="meta"><span class="state"
|
|
532
|
+
<div class="meta"><span class="state"></span> \xB7 <span class="protocol"></span> \xB7 <span class="fps">0</span> <span class="fps-label"></span></div>
|
|
493
533
|
<div class="row"><span class="label">TX</span><span class="value" id="tx">0</span></div>
|
|
494
534
|
<div class="row"><span class="label">TY</span><span class="value" id="ty">0</span></div>
|
|
495
535
|
<div class="row"><span class="label">TZ</span><span class="value" id="tz">0</span></div>
|
|
@@ -526,6 +566,8 @@ var SatMouseDebug = class extends HTMLElement {
|
|
|
526
566
|
this.els.state = shadow.querySelector(".state");
|
|
527
567
|
this.els.protocol = shadow.querySelector(".protocol");
|
|
528
568
|
this.els.fps = shadow.querySelector(".fps");
|
|
569
|
+
this.els.state.textContent = t("disconnected");
|
|
570
|
+
shadow.querySelector(".fps-label").textContent = t("fps");
|
|
529
571
|
}
|
|
530
572
|
connectedCallback() {
|
|
531
573
|
this.unsub = onManager((mgr) => this.bind(mgr));
|
|
@@ -560,10 +602,13 @@ var SatMouseDebug = class extends HTMLElement {
|
|
|
560
602
|
};
|
|
561
603
|
customElements.define("satmouse-debug", SatMouseDebug);
|
|
562
604
|
|
|
605
|
+
exports.DEFAULT_LOCALE = DEFAULT_LOCALE;
|
|
563
606
|
exports.SatMouseDebug = SatMouseDebug;
|
|
564
607
|
exports.SatMouseDevices = SatMouseDevices;
|
|
565
608
|
exports.SatMouseStatus = SatMouseStatus;
|
|
609
|
+
exports.getLocale = getLocale;
|
|
566
610
|
exports.getManager = getManager;
|
|
567
611
|
exports.registerSatMouse = registerSatMouse;
|
|
612
|
+
exports.setLocale = setLocale;
|
|
568
613
|
//# sourceMappingURL=index.cjs.map
|
|
569
614
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -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\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\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.showDownload = false;\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 // Detect Safari without extension — suggest enabling it\n const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n const hasExtension = !!(globalThis as any).__satmouseExtensionAvailable;\n if (isSafari && !hasExtension) {\n this.text.textContent = \"Extension required\";\n this.launch.style.display = \"inline-block\";\n this.launch.disabled = false;\n this.launch.textContent = \"Enable Extension\";\n this.showDownload = false;\n this.needsExtension = true;\n } else {\n this.text.textContent = \"Not running\";\n this.launch.style.display = \"inline-block\";\n this.launch.disabled = false;\n this.launch.textContent = this.showDownload ? \"Download SatMouse\" : \"Launch SatMouse\";\n this.needsExtension = false;\n }\n } else {\n this.text.textContent = \"Disconnected\";\n this.launch.style.display = \"none\";\n }\n }\n\n private showDownload = false;\n private needsExtension = false;\n\n private startLaunchFlow(): void {\n if (this.needsExtension) {\n // Open Safari extension preferences via the bridge's URL scheme\n window.location.href = \"satmouse://enable-extension\";\n // Retry connection after user enables the extension\n this.launch.textContent = \"Connecting...\";\n this.launch.disabled = true;\n this.stopPoll();\n this.pollTimer = setInterval(() => {\n if (this.manager?.state === \"connected\") { this.stopPoll(); return; }\n this.manager?.retry();\n }, 2000);\n // Give up after 30s\n setTimeout(() => { this.stopPoll(); this.launch.disabled = false; this.launch.textContent = \"Enable Extension\"; }, 30000);\n return;\n }\n\n if (this.showDownload) {\n window.location.href = \"https://github.com/kelnishi/SatMouse/releases/latest\";\n return;\n }\n\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 this.showDownload = false;\n return;\n }\n if (attempts >= 5) {\n this.stopPoll();\n this.showDownload = true;\n this.launch.disabled = false;\n this.launch.textContent = \"Download SatMouse\";\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 type { ButtonRoute } from \"../utils/config.js\";\nimport type { ButtonEvent } from \"../core/types.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 .btn-section { display: flex; flex-direction: column; gap: 4px; }\n .btn-section-label { color: #7f8c8d; font-weight: 600; font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; }\n .btn-route { display: flex; gap: 6px; align-items: center; font-size: 11px; }\n .btn-route .btn-idx { color: #7f8c8d; font-family: monospace; min-width: 32px; }\n .btn-route .btn-arrow { color: #7f8c8d; }\n .btn-route .btn-key { color: #3498db; font-family: monospace; }\n .btn-route .btn-remove { cursor: pointer; color: #e74c3c; background: none; border: none;\n font-size: 11px; padding: 0 2px; font-family: inherit; }\n .btn-route .btn-remove:hover { color: #ff6b6b; }\n .btn-add { background: none; border: 1px dashed #1a4a8a; border-radius: 3px; color: #7f8c8d;\n font-size: 11px; padding: 4px 8px; cursor: pointer; font-family: inherit; }\n .btn-add:hover { color: #e0e0e0; border-color: #3498db; }\n .btn-add.listening { color: #f39c12; border-color: #f39c12; border-style: solid; cursor: default; }\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, 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 sliders\n for (const [label, key, globalKey] of [\n [\"Trans\", \"translateScale\", \"translateScale\"],\n [\"Rot\", \"rotateScale\", \"rotateScale\"],\n [\"W\", \"wScale\", \"wScale\"],\n ] as const) {\n const row = document.createElement(\"div\");\n row.className = \"slider-row\";\n const val = (cfg as any)[key] ?? (mgr.config as any)[globalKey];\n row.innerHTML = `<label>${label}</label>` +\n `<input type=\"range\" min=\"0\" max=\"100\" value=\"${Math.round(unmapSlider(val))}\">` +\n `<span>${val.toFixed(4)}</span>`;\n const sl = row.querySelector(\"input\")! as HTMLInputElement;\n const sp = row.querySelector(\"span\")!;\n sl.addEventListener(\"input\", () => {\n const v = mapSlider(+sl.value);\n sp.textContent = v.toFixed(4);\n mgr.updateDeviceConfig(device.id, { [key]: v });\n });\n controls.appendChild(row);\n }\n\n // Button mappings\n const btnSection = document.createElement(\"div\");\n btnSection.className = \"btn-section\";\n const btnLabel = document.createElement(\"div\");\n btnLabel.className = \"btn-section-label\";\n btnLabel.textContent = \"Button Mappings\";\n btnSection.appendChild(btnLabel);\n\n const buttonRoutes: ButtonRoute[] = cfg.buttonRoutes ?? [];\n const labels = device.buttonLabels ?? [];\n for (let i = 0; i < buttonRoutes.length; i++) {\n const route = buttonRoutes[i];\n const btnName = labels[route.button] ?? `Btn ${route.button}`;\n const row = document.createElement(\"div\");\n row.className = \"btn-route\";\n\n const idxSpan = document.createElement(\"span\");\n idxSpan.className = \"btn-idx\";\n idxSpan.textContent = btnName;\n row.appendChild(idxSpan);\n\n const arrow = document.createElement(\"span\");\n arrow.className = \"btn-arrow\";\n arrow.textContent = \"\\u2192\";\n row.appendChild(arrow);\n\n const keySpan = document.createElement(\"span\");\n keySpan.className = \"btn-key\";\n keySpan.textContent = route.key;\n row.appendChild(keySpan);\n\n // Edit — re-listen for a new key\n const editBtn = document.createElement(\"button\");\n editBtn.className = \"btn-remove\";\n editBtn.textContent = \"\\u270E\";\n editBtn.title = \"Remap key\";\n const routeIdx = i;\n editBtn.addEventListener(\"click\", () => {\n keySpan.textContent = \"Press a key...\";\n keySpan.style.color = \"#f39c12\";\n const onKey = (e: KeyboardEvent) => {\n e.preventDefault();\n e.stopPropagation();\n document.removeEventListener(\"keydown\", onKey, true);\n const current = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];\n const updated = current.map((r: ButtonRoute, j: number) =>\n j === routeIdx ? { ...r, key: e.key, code: e.code } : r\n );\n mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });\n this.refreshControls(panel, device);\n };\n document.addEventListener(\"keydown\", onKey, true);\n });\n row.appendChild(editBtn);\n\n // Delete\n const removeBtn = document.createElement(\"button\");\n removeBtn.className = \"btn-remove\";\n removeBtn.textContent = \"\\u00d7\";\n removeBtn.title = \"Remove\";\n removeBtn.addEventListener(\"click\", () => {\n const current = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];\n const updated = current.filter((_: ButtonRoute, j: number) => j !== routeIdx);\n mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });\n this.refreshControls(panel, device);\n });\n row.appendChild(removeBtn);\n btnSection.appendChild(row);\n }\n\n // Add mapping button with listen flow\n const addBtn = document.createElement(\"button\");\n addBtn.className = \"btn-add\";\n addBtn.textContent = \"+ Add Button Mapping\";\n addBtn.addEventListener(\"click\", () => {\n if (addBtn.classList.contains(\"listening\")) return;\n this.startButtonListen(addBtn, mgr, device, panel);\n });\n btnSection.appendChild(addBtn);\n controls.appendChild(btnSection);\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(device: DeviceInfo, deviceAxes: string[]): AxisRoute[] {\n const mgr = this.manager!;\n\n // 1. Exact device ID\n const devCfg = mgr.config.devices[device.id];\n if (devCfg?.routes && Array.isArray(devCfg.routes)) return devCfg.routes;\n\n // 2. Pattern match\n for (const [pattern, cfg] of Object.entries(mgr.config.devices)) {\n if (pattern.endsWith(\"*\") && device.id.startsWith(pattern.slice(0, -1))) {\n if (cfg.routes && Array.isArray(cfg.routes)) return cfg.routes;\n }\n }\n\n // 3. Device class defaults\n if (device.deviceClass && mgr.config.deviceClasses) {\n const classCfg = mgr.config.deviceClasses[device.deviceClass];\n if (classCfg?.routes && Array.isArray(classCfg.routes)) return classCfg.routes;\n }\n\n // 4. Build from device axes metadata\n return buildRoutes(deviceAxes);\n }\n\n private updateRoute(deviceId: string, index: number, deviceAxes: string[], patch: Partial<AxisRoute>): void {\n const device = Array.from(this.manager!.getDevicesWithConfig()).find(d => d.device.id === deviceId)?.device;\n const base = this.getRoutes(device ?? { id: deviceId } as DeviceInfo, deviceAxes);\n const updated = base.map((r, j) => j === index ? { ...r, ...patch } : { ...r });\n this.manager!.updateDeviceConfig(deviceId, { routes: updated });\n }\n\n private startButtonListen(\n btn: HTMLButtonElement,\n mgr: InputManager,\n device: DeviceInfo,\n panel: HTMLDetailsElement,\n ): void {\n btn.classList.add(\"listening\");\n btn.textContent = \"Press a device button...\";\n\n // Step 1: Listen for device button\n const onButton = (event: ButtonEvent) => {\n if (!event.pressed) return; // only on press, not release\n mgr.off(\"buttonEvent\", onButton);\n\n const capturedButton = event.button;\n btn.textContent = `Btn ${capturedButton} \\u2192 Press a key...`;\n\n // Step 2: Listen for keyboard key\n const onKey = (e: KeyboardEvent) => {\n e.preventDefault();\n e.stopPropagation();\n document.removeEventListener(\"keydown\", onKey, true);\n\n const route: ButtonRoute = {\n button: capturedButton,\n key: e.key,\n code: e.code,\n };\n\n const current = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];\n // Replace existing mapping for the same button, or add new\n const updated = current.filter((r: ButtonRoute) => r.button !== capturedButton);\n updated.push(route);\n mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });\n this.refreshControls(panel, device);\n };\n document.addEventListener(\"keydown\", onKey, true);\n };\n mgr.on(\"buttonEvent\", onButton);\n\n // Cancel on Escape (before a button is pressed)\n const onCancel = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n mgr.off(\"buttonEvent\", onButton);\n document.removeEventListener(\"keydown\", onCancel, true);\n btn.classList.remove(\"listening\");\n btn.textContent = \"+ Add Button Mapping\";\n }\n };\n document.addEventListener(\"keydown\", onCancel, true);\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"]}
|
|
1
|
+
{"version":3,"sources":["../../src/elements/registry.ts","../../src/elements/locale.ts","../../src/elements/satmouse-status.ts","../../src/elements/satmouse-devices.ts","../../src/elements/satmouse-debug.ts"],"names":["FULL_AXES","current","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","/** All localizable strings used by SatMouse Web Components. */\nexport interface SatMouseLocale {\n // satmouse-status\n connected: string;\n connecting: string;\n disconnected: string;\n notRunning: string;\n extensionRequired: string;\n launchSatMouse: string;\n downloadSatMouse: string;\n enableExtension: string;\n\n // satmouse-devices\n noDevices: string;\n flip: string;\n translateScale: string;\n rotateScale: string;\n wScale: string;\n buttonMappings: string;\n remapKey: string;\n pressAKey: string;\n remove: string;\n addButtonMapping: string;\n pressDeviceButton: string;\n restoreDefaults: string;\n\n // satmouse-debug\n fps: string;\n}\n\n/** Default English strings. Exported so implementors can iterate keys for translation tooling. */\nexport const DEFAULT_LOCALE: Readonly<SatMouseLocale> = {\n // satmouse-status\n connected: \"Connected\",\n connecting: \"Connecting...\",\n disconnected: \"Disconnected\",\n notRunning: \"Not running\",\n extensionRequired: \"Extension required\",\n launchSatMouse: \"Launch SatMouse\",\n downloadSatMouse: \"Download SatMouse\",\n enableExtension: \"Enable Extension\",\n\n // satmouse-devices\n noDevices: \"No devices\",\n flip: \"Flip\",\n translateScale: \"Trans\",\n rotateScale: \"Rot\",\n wScale: \"W\",\n buttonMappings: \"Button Mappings\",\n remapKey: \"Remap key\",\n pressAKey: \"Press a key...\",\n remove: \"Remove\",\n addButtonMapping: \"+ Add Button Mapping\",\n pressDeviceButton: \"Press a device button...\",\n restoreDefaults: \"Restore Defaults\",\n\n // satmouse-debug\n fps: \"fps\",\n};\n\nlet current: SatMouseLocale = { ...DEFAULT_LOCALE };\n\n/** Override some or all UI strings. Partial updates merge with the current locale. */\nexport function setLocale(overrides: Partial<SatMouseLocale>): void {\n current = { ...current, ...overrides };\n}\n\n/** Get the current locale strings. */\nexport function getLocale(): Readonly<SatMouseLocale> {\n return current;\n}\n\n/** Read a single string by key. Used internally by components. */\nexport function t(key: keyof SatMouseLocale): string {\n return current[key];\n}\n","import { onManager } from \"./registry.js\";\nimport { t } from \"./locale.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\n</style>\n<span class=\"dot\"></span>\n<span class=\"text\"></span>\n<span class=\"protocol\"></span>\n<button class=\"launch\"></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 this.text.textContent = t(\"disconnected\");\n this.launch.textContent = t(\"launchSatMouse\");\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 = t(\"launchSatMouse\");\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.showDownload = false;\n this.text.textContent = t(\"connected\");\n this.launch.style.display = \"none\";\n } else if (state === \"connecting\") {\n this.text.textContent = t(\"connecting\");\n this.launch.style.display = \"none\";\n } else if (state === \"failed\") {\n // Detect Safari without extension — suggest enabling it\n const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n const hasExtension = !!(globalThis as any).__satmouseExtensionAvailable;\n if (isSafari && !hasExtension) {\n this.text.textContent = t(\"extensionRequired\");\n this.launch.style.display = \"inline-block\";\n this.launch.disabled = false;\n this.launch.textContent = t(\"enableExtension\");\n this.showDownload = false;\n this.needsExtension = true;\n } else {\n this.text.textContent = t(\"notRunning\");\n this.launch.style.display = \"inline-block\";\n this.launch.disabled = false;\n this.launch.textContent = this.showDownload ? t(\"downloadSatMouse\") : t(\"launchSatMouse\");\n this.needsExtension = false;\n }\n } else {\n this.text.textContent = t(\"disconnected\");\n this.launch.style.display = \"none\";\n }\n }\n\n private showDownload = false;\n private needsExtension = false;\n\n private startLaunchFlow(): void {\n if (this.needsExtension) {\n // Open Safari extension preferences via the bridge's URL scheme\n window.location.href = \"satmouse://enable-extension\";\n // Retry connection after user enables the extension\n this.launch.textContent = t(\"connecting\");\n this.launch.disabled = true;\n this.stopPoll();\n this.pollTimer = setInterval(() => {\n if (this.manager?.state === \"connected\") { this.stopPoll(); return; }\n this.manager?.retry();\n }, 2000);\n // Give up after 30s\n setTimeout(() => { this.stopPoll(); this.launch.disabled = false; this.launch.textContent = t(\"enableExtension\"); }, 30000);\n return;\n }\n\n if (this.showDownload) {\n window.location.href = \"https://github.com/kelnishi/SatMouse/releases/latest\";\n return;\n }\n\n this.launch.textContent = t(\"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 this.showDownload = false;\n return;\n }\n if (attempts >= 5) {\n this.stopPoll();\n this.showDownload = true;\n this.launch.disabled = false;\n this.launch.textContent = t(\"downloadSatMouse\");\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 { t } from \"./locale.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 type { ButtonRoute } from \"../utils/config.js\";\nimport type { ButtonEvent } from \"../core/types.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 .btn-section { display: flex; flex-direction: column; gap: 4px; }\n .btn-section-label { color: #7f8c8d; font-weight: 600; font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; }\n .btn-route { display: flex; gap: 6px; align-items: center; font-size: 11px; }\n .btn-route .btn-idx { color: #7f8c8d; font-family: monospace; min-width: 32px; }\n .btn-route .btn-arrow { color: #7f8c8d; }\n .btn-route .btn-key { color: #3498db; font-family: monospace; }\n .btn-route .btn-remove { cursor: pointer; color: #e74c3c; background: none; border: none;\n font-size: 11px; padding: 0 2px; font-family: inherit; }\n .btn-route .btn-remove:hover { color: #ff6b6b; }\n .btn-add { background: none; border: 1px dashed #1a4a8a; border-radius: 3px; color: #7f8c8d;\n font-size: 11px; padding: 4px 8px; cursor: pointer; font-family: inherit; }\n .btn-add:hover { color: #e0e0e0; border-color: #3498db; }\n .btn-add.listening { color: #f39c12; border-color: #f39c12; border-style: solid; cursor: default; }\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\">${t(\"noDevices\")}</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, 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 = t(\"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 sliders\n for (const [label, key, globalKey] of [\n [t(\"translateScale\"), \"translateScale\", \"translateScale\"],\n [t(\"rotateScale\"), \"rotateScale\", \"rotateScale\"],\n [t(\"wScale\"), \"wScale\", \"wScale\"],\n ] as const) {\n const row = document.createElement(\"div\");\n row.className = \"slider-row\";\n const val = (cfg as any)[key] ?? (mgr.config as any)[globalKey];\n row.innerHTML = `<label>${label}</label>` +\n `<input type=\"range\" min=\"0\" max=\"100\" value=\"${Math.round(unmapSlider(val))}\">` +\n `<span>${val.toFixed(4)}</span>`;\n const sl = row.querySelector(\"input\")! as HTMLInputElement;\n const sp = row.querySelector(\"span\")!;\n sl.addEventListener(\"input\", () => {\n const v = mapSlider(+sl.value);\n sp.textContent = v.toFixed(4);\n mgr.updateDeviceConfig(device.id, { [key]: v });\n });\n controls.appendChild(row);\n }\n\n // Button mappings\n const btnSection = document.createElement(\"div\");\n btnSection.className = \"btn-section\";\n const btnLabel = document.createElement(\"div\");\n btnLabel.className = \"btn-section-label\";\n btnLabel.textContent = t(\"buttonMappings\");\n btnSection.appendChild(btnLabel);\n\n const buttonRoutes: ButtonRoute[] = cfg.buttonRoutes ?? [];\n const labels = device.buttonLabels ?? [];\n for (let i = 0; i < buttonRoutes.length; i++) {\n const route = buttonRoutes[i];\n const btnName = labels[route.button] ?? `Btn ${route.button}`;\n const row = document.createElement(\"div\");\n row.className = \"btn-route\";\n\n const idxSpan = document.createElement(\"span\");\n idxSpan.className = \"btn-idx\";\n idxSpan.textContent = btnName;\n row.appendChild(idxSpan);\n\n const arrow = document.createElement(\"span\");\n arrow.className = \"btn-arrow\";\n arrow.textContent = \"\\u2192\";\n row.appendChild(arrow);\n\n const keySpan = document.createElement(\"span\");\n keySpan.className = \"btn-key\";\n keySpan.textContent = route.key;\n row.appendChild(keySpan);\n\n // Edit — re-listen for a new key\n const editBtn = document.createElement(\"button\");\n editBtn.className = \"btn-remove\";\n editBtn.textContent = \"\\u270E\";\n editBtn.title = t(\"remapKey\");\n const routeIdx = i;\n editBtn.addEventListener(\"click\", () => {\n keySpan.textContent = t(\"pressAKey\");\n keySpan.style.color = \"#f39c12\";\n const onKey = (e: KeyboardEvent) => {\n e.preventDefault();\n e.stopPropagation();\n document.removeEventListener(\"keydown\", onKey, true);\n const current = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];\n const updated = current.map((r: ButtonRoute, j: number) =>\n j === routeIdx ? { ...r, key: e.key, code: e.code } : r\n );\n mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });\n this.refreshControls(panel, device);\n };\n document.addEventListener(\"keydown\", onKey, true);\n });\n row.appendChild(editBtn);\n\n // Delete\n const removeBtn = document.createElement(\"button\");\n removeBtn.className = \"btn-remove\";\n removeBtn.textContent = \"\\u00d7\";\n removeBtn.title = t(\"remove\");\n removeBtn.addEventListener(\"click\", () => {\n const current = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];\n const updated = current.filter((_: ButtonRoute, j: number) => j !== routeIdx);\n mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });\n this.refreshControls(panel, device);\n });\n row.appendChild(removeBtn);\n btnSection.appendChild(row);\n }\n\n // Add mapping button with listen flow\n const addBtn = document.createElement(\"button\");\n addBtn.className = \"btn-add\";\n addBtn.textContent = t(\"addButtonMapping\");\n addBtn.addEventListener(\"click\", () => {\n if (addBtn.classList.contains(\"listening\")) return;\n this.startButtonListen(addBtn, mgr, device, panel);\n });\n btnSection.appendChild(addBtn);\n controls.appendChild(btnSection);\n\n // Reset button\n const resetBtn = document.createElement(\"button\");\n resetBtn.className = \"reset-btn\";\n resetBtn.textContent = t(\"restoreDefaults\");\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(device: DeviceInfo, deviceAxes: string[]): AxisRoute[] {\n const mgr = this.manager!;\n\n // 1. Exact device ID\n const devCfg = mgr.config.devices[device.id];\n if (devCfg?.routes && Array.isArray(devCfg.routes)) return devCfg.routes;\n\n // 2. Pattern match\n for (const [pattern, cfg] of Object.entries(mgr.config.devices)) {\n if (pattern.endsWith(\"*\") && device.id.startsWith(pattern.slice(0, -1))) {\n if (cfg.routes && Array.isArray(cfg.routes)) return cfg.routes;\n }\n }\n\n // 3. Device class defaults\n if (device.deviceClass && mgr.config.deviceClasses) {\n const classCfg = mgr.config.deviceClasses[device.deviceClass];\n if (classCfg?.routes && Array.isArray(classCfg.routes)) return classCfg.routes;\n }\n\n // 4. Build from device axes metadata\n return buildRoutes(deviceAxes);\n }\n\n private updateRoute(deviceId: string, index: number, deviceAxes: string[], patch: Partial<AxisRoute>): void {\n const device = Array.from(this.manager!.getDevicesWithConfig()).find(d => d.device.id === deviceId)?.device;\n const base = this.getRoutes(device ?? { id: deviceId } as DeviceInfo, deviceAxes);\n const updated = base.map((r, j) => j === index ? { ...r, ...patch } : { ...r });\n this.manager!.updateDeviceConfig(deviceId, { routes: updated });\n }\n\n private startButtonListen(\n btn: HTMLButtonElement,\n mgr: InputManager,\n device: DeviceInfo,\n panel: HTMLDetailsElement,\n ): void {\n btn.classList.add(\"listening\");\n btn.textContent = t(\"pressDeviceButton\");\n\n // Step 1: Listen for device button\n const onButton = (event: ButtonEvent) => {\n if (!event.pressed) return; // only on press, not release\n mgr.off(\"buttonEvent\", onButton);\n\n const capturedButton = event.button;\n btn.textContent = `Btn ${capturedButton} \\u2192 ${t(\"pressAKey\")}`;\n\n // Step 2: Listen for keyboard key\n const onKey = (e: KeyboardEvent) => {\n e.preventDefault();\n e.stopPropagation();\n document.removeEventListener(\"keydown\", onKey, true);\n\n const route: ButtonRoute = {\n button: capturedButton,\n key: e.key,\n code: e.code,\n };\n\n const current = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];\n // Replace existing mapping for the same button, or add new\n const updated = current.filter((r: ButtonRoute) => r.button !== capturedButton);\n updated.push(route);\n mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });\n this.refreshControls(panel, device);\n };\n document.addEventListener(\"keydown\", onKey, true);\n };\n mgr.on(\"buttonEvent\", onButton);\n\n // Cancel on Escape (before a button is pressed)\n const onCancel = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n mgr.off(\"buttonEvent\", onButton);\n document.removeEventListener(\"keydown\", onCancel, true);\n btn.classList.remove(\"listening\");\n btn.textContent = t(\"addButtonMapping\");\n }\n };\n document.addEventListener(\"keydown\", onCancel, true);\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\">${t(\"noDevices\")}</span>`;\n }\n }\n}\n\ncustomElements.define(\"satmouse-devices\", SatMouseDevices);\n","import { onManager } from \"./registry.js\";\nimport { t } from \"./locale.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\"></span> · <span class=\"protocol\"></span> · <span class=\"fps\">0</span> <span class=\"fps-label\"></span></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 this.els.state.textContent = t(\"disconnected\");\n shadow.querySelector(\".fps-label\")!.textContent = t(\"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"]}
|
|
@@ -59,4 +59,35 @@ declare class SatMouseDebug extends HTMLElement {
|
|
|
59
59
|
declare function registerSatMouse(manager: InputManager): void;
|
|
60
60
|
declare function getManager(): InputManager | null;
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
/** All localizable strings used by SatMouse Web Components. */
|
|
63
|
+
interface SatMouseLocale {
|
|
64
|
+
connected: string;
|
|
65
|
+
connecting: string;
|
|
66
|
+
disconnected: string;
|
|
67
|
+
notRunning: string;
|
|
68
|
+
extensionRequired: string;
|
|
69
|
+
launchSatMouse: string;
|
|
70
|
+
downloadSatMouse: string;
|
|
71
|
+
enableExtension: string;
|
|
72
|
+
noDevices: string;
|
|
73
|
+
flip: string;
|
|
74
|
+
translateScale: string;
|
|
75
|
+
rotateScale: string;
|
|
76
|
+
wScale: string;
|
|
77
|
+
buttonMappings: string;
|
|
78
|
+
remapKey: string;
|
|
79
|
+
pressAKey: string;
|
|
80
|
+
remove: string;
|
|
81
|
+
addButtonMapping: string;
|
|
82
|
+
pressDeviceButton: string;
|
|
83
|
+
restoreDefaults: string;
|
|
84
|
+
fps: string;
|
|
85
|
+
}
|
|
86
|
+
/** Default English strings. Exported so implementors can iterate keys for translation tooling. */
|
|
87
|
+
declare const DEFAULT_LOCALE: Readonly<SatMouseLocale>;
|
|
88
|
+
/** Override some or all UI strings. Partial updates merge with the current locale. */
|
|
89
|
+
declare function setLocale(overrides: Partial<SatMouseLocale>): void;
|
|
90
|
+
/** Get the current locale strings. */
|
|
91
|
+
declare function getLocale(): Readonly<SatMouseLocale>;
|
|
92
|
+
|
|
93
|
+
export { DEFAULT_LOCALE, SatMouseDebug, SatMouseDevices, type SatMouseLocale, SatMouseStatus, getLocale, getManager, registerSatMouse, setLocale };
|
package/dist/elements/index.d.ts
CHANGED
|
@@ -59,4 +59,35 @@ declare class SatMouseDebug extends HTMLElement {
|
|
|
59
59
|
declare function registerSatMouse(manager: InputManager): void;
|
|
60
60
|
declare function getManager(): InputManager | null;
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
/** All localizable strings used by SatMouse Web Components. */
|
|
63
|
+
interface SatMouseLocale {
|
|
64
|
+
connected: string;
|
|
65
|
+
connecting: string;
|
|
66
|
+
disconnected: string;
|
|
67
|
+
notRunning: string;
|
|
68
|
+
extensionRequired: string;
|
|
69
|
+
launchSatMouse: string;
|
|
70
|
+
downloadSatMouse: string;
|
|
71
|
+
enableExtension: string;
|
|
72
|
+
noDevices: string;
|
|
73
|
+
flip: string;
|
|
74
|
+
translateScale: string;
|
|
75
|
+
rotateScale: string;
|
|
76
|
+
wScale: string;
|
|
77
|
+
buttonMappings: string;
|
|
78
|
+
remapKey: string;
|
|
79
|
+
pressAKey: string;
|
|
80
|
+
remove: string;
|
|
81
|
+
addButtonMapping: string;
|
|
82
|
+
pressDeviceButton: string;
|
|
83
|
+
restoreDefaults: string;
|
|
84
|
+
fps: string;
|
|
85
|
+
}
|
|
86
|
+
/** Default English strings. Exported so implementors can iterate keys for translation tooling. */
|
|
87
|
+
declare const DEFAULT_LOCALE: Readonly<SatMouseLocale>;
|
|
88
|
+
/** Override some or all UI strings. Partial updates merge with the current locale. */
|
|
89
|
+
declare function setLocale(overrides: Partial<SatMouseLocale>): void;
|
|
90
|
+
/** Get the current locale strings. */
|
|
91
|
+
declare function getLocale(): Readonly<SatMouseLocale>;
|
|
92
|
+
|
|
93
|
+
export { DEFAULT_LOCALE, SatMouseDebug, SatMouseDevices, type SatMouseLocale, SatMouseStatus, getLocale, getManager, registerSatMouse, setLocale };
|
package/dist/elements/index.js
CHANGED
|
@@ -17,6 +17,44 @@ function onManager(fn) {
|
|
|
17
17
|
return () => listeners.delete(fn);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
// src/elements/locale.ts
|
|
21
|
+
var DEFAULT_LOCALE = {
|
|
22
|
+
// satmouse-status
|
|
23
|
+
connected: "Connected",
|
|
24
|
+
connecting: "Connecting...",
|
|
25
|
+
disconnected: "Disconnected",
|
|
26
|
+
notRunning: "Not running",
|
|
27
|
+
extensionRequired: "Extension required",
|
|
28
|
+
launchSatMouse: "Launch SatMouse",
|
|
29
|
+
downloadSatMouse: "Download SatMouse",
|
|
30
|
+
enableExtension: "Enable Extension",
|
|
31
|
+
// satmouse-devices
|
|
32
|
+
noDevices: "No devices",
|
|
33
|
+
flip: "Flip",
|
|
34
|
+
translateScale: "Trans",
|
|
35
|
+
rotateScale: "Rot",
|
|
36
|
+
wScale: "W",
|
|
37
|
+
buttonMappings: "Button Mappings",
|
|
38
|
+
remapKey: "Remap key",
|
|
39
|
+
pressAKey: "Press a key...",
|
|
40
|
+
remove: "Remove",
|
|
41
|
+
addButtonMapping: "+ Add Button Mapping",
|
|
42
|
+
pressDeviceButton: "Press a device button...",
|
|
43
|
+
restoreDefaults: "Restore Defaults",
|
|
44
|
+
// satmouse-debug
|
|
45
|
+
fps: "fps"
|
|
46
|
+
};
|
|
47
|
+
var current = { ...DEFAULT_LOCALE };
|
|
48
|
+
function setLocale(overrides) {
|
|
49
|
+
current = { ...current, ...overrides };
|
|
50
|
+
}
|
|
51
|
+
function getLocale() {
|
|
52
|
+
return current;
|
|
53
|
+
}
|
|
54
|
+
function t(key) {
|
|
55
|
+
return current[key];
|
|
56
|
+
}
|
|
57
|
+
|
|
20
58
|
// src/elements/satmouse-status.ts
|
|
21
59
|
var TEMPLATE = `
|
|
22
60
|
<style>
|
|
@@ -32,9 +70,9 @@ var TEMPLATE = `
|
|
|
32
70
|
|
|
33
71
|
</style>
|
|
34
72
|
<span class="dot"></span>
|
|
35
|
-
<span class="text"
|
|
73
|
+
<span class="text"></span>
|
|
36
74
|
<span class="protocol"></span>
|
|
37
|
-
<button class="launch"
|
|
75
|
+
<button class="launch"></button>
|
|
38
76
|
`;
|
|
39
77
|
var SatMouseStatus = class extends HTMLElement {
|
|
40
78
|
dot;
|
|
@@ -53,6 +91,8 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
53
91
|
this.text = shadow.querySelector(".text");
|
|
54
92
|
this.proto = shadow.querySelector(".protocol");
|
|
55
93
|
this.launch = shadow.querySelector(".launch");
|
|
94
|
+
this.text.textContent = t("disconnected");
|
|
95
|
+
this.launch.textContent = t("launchSatMouse");
|
|
56
96
|
this.launch.addEventListener("click", () => {
|
|
57
97
|
this.startLaunchFlow();
|
|
58
98
|
});
|
|
@@ -61,7 +101,7 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
61
101
|
this.unsub = onManager((mgr) => this.bind(mgr));
|
|
62
102
|
this.stopPoll();
|
|
63
103
|
this.launch.disabled = false;
|
|
64
|
-
this.launch.textContent = "
|
|
104
|
+
this.launch.textContent = t("launchSatMouse");
|
|
65
105
|
}
|
|
66
106
|
disconnectedCallback() {
|
|
67
107
|
this.stopPoll();
|
|
@@ -84,30 +124,30 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
84
124
|
if (state === "connected") {
|
|
85
125
|
this.stopPoll();
|
|
86
126
|
this.showDownload = false;
|
|
87
|
-
this.text.textContent = "
|
|
127
|
+
this.text.textContent = t("connected");
|
|
88
128
|
this.launch.style.display = "none";
|
|
89
129
|
} else if (state === "connecting") {
|
|
90
|
-
this.text.textContent = "
|
|
130
|
+
this.text.textContent = t("connecting");
|
|
91
131
|
this.launch.style.display = "none";
|
|
92
132
|
} else if (state === "failed") {
|
|
93
133
|
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
94
134
|
const hasExtension = !!globalThis.__satmouseExtensionAvailable;
|
|
95
135
|
if (isSafari && !hasExtension) {
|
|
96
|
-
this.text.textContent = "
|
|
136
|
+
this.text.textContent = t("extensionRequired");
|
|
97
137
|
this.launch.style.display = "inline-block";
|
|
98
138
|
this.launch.disabled = false;
|
|
99
|
-
this.launch.textContent = "
|
|
139
|
+
this.launch.textContent = t("enableExtension");
|
|
100
140
|
this.showDownload = false;
|
|
101
141
|
this.needsExtension = true;
|
|
102
142
|
} else {
|
|
103
|
-
this.text.textContent = "
|
|
143
|
+
this.text.textContent = t("notRunning");
|
|
104
144
|
this.launch.style.display = "inline-block";
|
|
105
145
|
this.launch.disabled = false;
|
|
106
|
-
this.launch.textContent = this.showDownload ? "
|
|
146
|
+
this.launch.textContent = this.showDownload ? t("downloadSatMouse") : t("launchSatMouse");
|
|
107
147
|
this.needsExtension = false;
|
|
108
148
|
}
|
|
109
149
|
} else {
|
|
110
|
-
this.text.textContent = "
|
|
150
|
+
this.text.textContent = t("disconnected");
|
|
111
151
|
this.launch.style.display = "none";
|
|
112
152
|
}
|
|
113
153
|
}
|
|
@@ -116,7 +156,7 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
116
156
|
startLaunchFlow() {
|
|
117
157
|
if (this.needsExtension) {
|
|
118
158
|
window.location.href = "satmouse://enable-extension";
|
|
119
|
-
this.launch.textContent = "
|
|
159
|
+
this.launch.textContent = t("connecting");
|
|
120
160
|
this.launch.disabled = true;
|
|
121
161
|
this.stopPoll();
|
|
122
162
|
this.pollTimer = setInterval(() => {
|
|
@@ -129,7 +169,7 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
129
169
|
setTimeout(() => {
|
|
130
170
|
this.stopPoll();
|
|
131
171
|
this.launch.disabled = false;
|
|
132
|
-
this.launch.textContent = "
|
|
172
|
+
this.launch.textContent = t("enableExtension");
|
|
133
173
|
}, 3e4);
|
|
134
174
|
return;
|
|
135
175
|
}
|
|
@@ -137,7 +177,7 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
137
177
|
window.location.href = "https://github.com/kelnishi/SatMouse/releases/latest";
|
|
138
178
|
return;
|
|
139
179
|
}
|
|
140
|
-
this.launch.textContent = "
|
|
180
|
+
this.launch.textContent = t("connecting");
|
|
141
181
|
this.launch.disabled = true;
|
|
142
182
|
this.manager?.retry();
|
|
143
183
|
window.location.href = "satmouse://launch";
|
|
@@ -154,7 +194,7 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
154
194
|
this.stopPoll();
|
|
155
195
|
this.showDownload = true;
|
|
156
196
|
this.launch.disabled = false;
|
|
157
|
-
this.launch.textContent = "
|
|
197
|
+
this.launch.textContent = t("downloadSatMouse");
|
|
158
198
|
return;
|
|
159
199
|
}
|
|
160
200
|
this.manager?.retry();
|
|
@@ -237,7 +277,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
237
277
|
disconnectedCallback() {
|
|
238
278
|
this.unsub?.();
|
|
239
279
|
this.unbind();
|
|
240
|
-
this.container.innerHTML = `<span class="empty"
|
|
280
|
+
this.container.innerHTML = `<span class="empty">${t("noDevices")}</span>`;
|
|
241
281
|
}
|
|
242
282
|
bind(mgr) {
|
|
243
283
|
this.unbind();
|
|
@@ -291,7 +331,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
291
331
|
const cb = document.createElement("input");
|
|
292
332
|
cb.type = "checkbox";
|
|
293
333
|
cb.checked = route.flip ?? false;
|
|
294
|
-
cb.title = "
|
|
334
|
+
cb.title = t("flip");
|
|
295
335
|
const routeIndex = i;
|
|
296
336
|
cb.addEventListener("change", () => {
|
|
297
337
|
this.updateRoute(device.id, routeIndex, deviceAxes, { flip: cb.checked });
|
|
@@ -316,9 +356,9 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
316
356
|
}
|
|
317
357
|
controls.appendChild(routeGroup);
|
|
318
358
|
for (const [label, key, globalKey] of [
|
|
319
|
-
["
|
|
320
|
-
["
|
|
321
|
-
["
|
|
359
|
+
[t("translateScale"), "translateScale", "translateScale"],
|
|
360
|
+
[t("rotateScale"), "rotateScale", "rotateScale"],
|
|
361
|
+
[t("wScale"), "wScale", "wScale"]
|
|
322
362
|
]) {
|
|
323
363
|
const row = document.createElement("div");
|
|
324
364
|
row.className = "slider-row";
|
|
@@ -337,7 +377,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
337
377
|
btnSection.className = "btn-section";
|
|
338
378
|
const btnLabel = document.createElement("div");
|
|
339
379
|
btnLabel.className = "btn-section-label";
|
|
340
|
-
btnLabel.textContent = "
|
|
380
|
+
btnLabel.textContent = t("buttonMappings");
|
|
341
381
|
btnSection.appendChild(btnLabel);
|
|
342
382
|
const buttonRoutes = cfg.buttonRoutes ?? [];
|
|
343
383
|
const labels = device.buttonLabels ?? [];
|
|
@@ -361,17 +401,17 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
361
401
|
const editBtn = document.createElement("button");
|
|
362
402
|
editBtn.className = "btn-remove";
|
|
363
403
|
editBtn.textContent = "\u270E";
|
|
364
|
-
editBtn.title = "
|
|
404
|
+
editBtn.title = t("remapKey");
|
|
365
405
|
const routeIdx = i;
|
|
366
406
|
editBtn.addEventListener("click", () => {
|
|
367
|
-
keySpan.textContent = "
|
|
407
|
+
keySpan.textContent = t("pressAKey");
|
|
368
408
|
keySpan.style.color = "#f39c12";
|
|
369
409
|
const onKey = (e) => {
|
|
370
410
|
e.preventDefault();
|
|
371
411
|
e.stopPropagation();
|
|
372
412
|
document.removeEventListener("keydown", onKey, true);
|
|
373
|
-
const
|
|
374
|
-
const updated =
|
|
413
|
+
const current2 = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];
|
|
414
|
+
const updated = current2.map(
|
|
375
415
|
(r, j) => j === routeIdx ? { ...r, key: e.key, code: e.code } : r
|
|
376
416
|
);
|
|
377
417
|
mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });
|
|
@@ -383,10 +423,10 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
383
423
|
const removeBtn = document.createElement("button");
|
|
384
424
|
removeBtn.className = "btn-remove";
|
|
385
425
|
removeBtn.textContent = "\xD7";
|
|
386
|
-
removeBtn.title = "
|
|
426
|
+
removeBtn.title = t("remove");
|
|
387
427
|
removeBtn.addEventListener("click", () => {
|
|
388
|
-
const
|
|
389
|
-
const updated =
|
|
428
|
+
const current2 = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];
|
|
429
|
+
const updated = current2.filter((_, j) => j !== routeIdx);
|
|
390
430
|
mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });
|
|
391
431
|
this.refreshControls(panel, device);
|
|
392
432
|
});
|
|
@@ -395,7 +435,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
395
435
|
}
|
|
396
436
|
const addBtn = document.createElement("button");
|
|
397
437
|
addBtn.className = "btn-add";
|
|
398
|
-
addBtn.textContent = "
|
|
438
|
+
addBtn.textContent = t("addButtonMapping");
|
|
399
439
|
addBtn.addEventListener("click", () => {
|
|
400
440
|
if (addBtn.classList.contains("listening")) return;
|
|
401
441
|
this.startButtonListen(addBtn, mgr, device, panel);
|
|
@@ -404,7 +444,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
404
444
|
controls.appendChild(btnSection);
|
|
405
445
|
const resetBtn = document.createElement("button");
|
|
406
446
|
resetBtn.className = "reset-btn";
|
|
407
|
-
resetBtn.textContent = "
|
|
447
|
+
resetBtn.textContent = t("restoreDefaults");
|
|
408
448
|
resetBtn.addEventListener("click", () => {
|
|
409
449
|
mgr.resetDeviceConfig(device.id);
|
|
410
450
|
this.refreshControls(panel, device);
|
|
@@ -435,12 +475,12 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
435
475
|
}
|
|
436
476
|
startButtonListen(btn, mgr, device, panel) {
|
|
437
477
|
btn.classList.add("listening");
|
|
438
|
-
btn.textContent = "
|
|
478
|
+
btn.textContent = t("pressDeviceButton");
|
|
439
479
|
const onButton = (event) => {
|
|
440
480
|
if (!event.pressed) return;
|
|
441
481
|
mgr.off("buttonEvent", onButton);
|
|
442
482
|
const capturedButton = event.button;
|
|
443
|
-
btn.textContent = `Btn ${capturedButton} \u2192
|
|
483
|
+
btn.textContent = `Btn ${capturedButton} \u2192 ${t("pressAKey")}`;
|
|
444
484
|
const onKey = (e) => {
|
|
445
485
|
e.preventDefault();
|
|
446
486
|
e.stopPropagation();
|
|
@@ -450,8 +490,8 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
450
490
|
key: e.key,
|
|
451
491
|
code: e.code
|
|
452
492
|
};
|
|
453
|
-
const
|
|
454
|
-
const updated =
|
|
493
|
+
const current2 = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];
|
|
494
|
+
const updated = current2.filter((r) => r.button !== capturedButton);
|
|
455
495
|
updated.push(route);
|
|
456
496
|
mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });
|
|
457
497
|
this.refreshControls(panel, device);
|
|
@@ -464,7 +504,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
464
504
|
mgr.off("buttonEvent", onButton);
|
|
465
505
|
document.removeEventListener("keydown", onCancel, true);
|
|
466
506
|
btn.classList.remove("listening");
|
|
467
|
-
btn.textContent = "
|
|
507
|
+
btn.textContent = t("addButtonMapping");
|
|
468
508
|
}
|
|
469
509
|
};
|
|
470
510
|
document.addEventListener("keydown", onCancel, true);
|
|
@@ -472,7 +512,7 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
472
512
|
removeDevice(device) {
|
|
473
513
|
this.shadowRoot.getElementById(`dev-${device.id}`)?.remove();
|
|
474
514
|
if (this.container.children.length === 0) {
|
|
475
|
-
this.container.innerHTML = `<span class="empty"
|
|
515
|
+
this.container.innerHTML = `<span class="empty">${t("noDevices")}</span>`;
|
|
476
516
|
}
|
|
477
517
|
}
|
|
478
518
|
};
|
|
@@ -487,7 +527,7 @@ var TEMPLATE2 = `
|
|
|
487
527
|
.value { color: #3498db; text-align: right; min-width: 50px; }
|
|
488
528
|
.meta { color: #7f8c8d; font-size: 11px; padding: 2px 0; }
|
|
489
529
|
</style>
|
|
490
|
-
<div class="meta"><span class="state"
|
|
530
|
+
<div class="meta"><span class="state"></span> \xB7 <span class="protocol"></span> \xB7 <span class="fps">0</span> <span class="fps-label"></span></div>
|
|
491
531
|
<div class="row"><span class="label">TX</span><span class="value" id="tx">0</span></div>
|
|
492
532
|
<div class="row"><span class="label">TY</span><span class="value" id="ty">0</span></div>
|
|
493
533
|
<div class="row"><span class="label">TZ</span><span class="value" id="tz">0</span></div>
|
|
@@ -524,6 +564,8 @@ var SatMouseDebug = class extends HTMLElement {
|
|
|
524
564
|
this.els.state = shadow.querySelector(".state");
|
|
525
565
|
this.els.protocol = shadow.querySelector(".protocol");
|
|
526
566
|
this.els.fps = shadow.querySelector(".fps");
|
|
567
|
+
this.els.state.textContent = t("disconnected");
|
|
568
|
+
shadow.querySelector(".fps-label").textContent = t("fps");
|
|
527
569
|
}
|
|
528
570
|
connectedCallback() {
|
|
529
571
|
this.unsub = onManager((mgr) => this.bind(mgr));
|
|
@@ -558,6 +600,6 @@ var SatMouseDebug = class extends HTMLElement {
|
|
|
558
600
|
};
|
|
559
601
|
customElements.define("satmouse-debug", SatMouseDebug);
|
|
560
602
|
|
|
561
|
-
export { SatMouseDebug, SatMouseDevices, SatMouseStatus, getManager, registerSatMouse };
|
|
603
|
+
export { DEFAULT_LOCALE, SatMouseDebug, SatMouseDevices, SatMouseStatus, getLocale, getManager, registerSatMouse, setLocale };
|
|
562
604
|
//# sourceMappingURL=index.js.map
|
|
563
605
|
//# sourceMappingURL=index.js.map
|
|
@@ -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":["TEMPLATE"],"mappings":"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","file":"index.js","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\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.showDownload = false;\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 // Detect Safari without extension — suggest enabling it\n const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n const hasExtension = !!(globalThis as any).__satmouseExtensionAvailable;\n if (isSafari && !hasExtension) {\n this.text.textContent = \"Extension required\";\n this.launch.style.display = \"inline-block\";\n this.launch.disabled = false;\n this.launch.textContent = \"Enable Extension\";\n this.showDownload = false;\n this.needsExtension = true;\n } else {\n this.text.textContent = \"Not running\";\n this.launch.style.display = \"inline-block\";\n this.launch.disabled = false;\n this.launch.textContent = this.showDownload ? \"Download SatMouse\" : \"Launch SatMouse\";\n this.needsExtension = false;\n }\n } else {\n this.text.textContent = \"Disconnected\";\n this.launch.style.display = \"none\";\n }\n }\n\n private showDownload = false;\n private needsExtension = false;\n\n private startLaunchFlow(): void {\n if (this.needsExtension) {\n // Open Safari extension preferences via the bridge's URL scheme\n window.location.href = \"satmouse://enable-extension\";\n // Retry connection after user enables the extension\n this.launch.textContent = \"Connecting...\";\n this.launch.disabled = true;\n this.stopPoll();\n this.pollTimer = setInterval(() => {\n if (this.manager?.state === \"connected\") { this.stopPoll(); return; }\n this.manager?.retry();\n }, 2000);\n // Give up after 30s\n setTimeout(() => { this.stopPoll(); this.launch.disabled = false; this.launch.textContent = \"Enable Extension\"; }, 30000);\n return;\n }\n\n if (this.showDownload) {\n window.location.href = \"https://github.com/kelnishi/SatMouse/releases/latest\";\n return;\n }\n\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 this.showDownload = false;\n return;\n }\n if (attempts >= 5) {\n this.stopPoll();\n this.showDownload = true;\n this.launch.disabled = false;\n this.launch.textContent = \"Download SatMouse\";\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 type { ButtonRoute } from \"../utils/config.js\";\nimport type { ButtonEvent } from \"../core/types.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 .btn-section { display: flex; flex-direction: column; gap: 4px; }\n .btn-section-label { color: #7f8c8d; font-weight: 600; font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; }\n .btn-route { display: flex; gap: 6px; align-items: center; font-size: 11px; }\n .btn-route .btn-idx { color: #7f8c8d; font-family: monospace; min-width: 32px; }\n .btn-route .btn-arrow { color: #7f8c8d; }\n .btn-route .btn-key { color: #3498db; font-family: monospace; }\n .btn-route .btn-remove { cursor: pointer; color: #e74c3c; background: none; border: none;\n font-size: 11px; padding: 0 2px; font-family: inherit; }\n .btn-route .btn-remove:hover { color: #ff6b6b; }\n .btn-add { background: none; border: 1px dashed #1a4a8a; border-radius: 3px; color: #7f8c8d;\n font-size: 11px; padding: 4px 8px; cursor: pointer; font-family: inherit; }\n .btn-add:hover { color: #e0e0e0; border-color: #3498db; }\n .btn-add.listening { color: #f39c12; border-color: #f39c12; border-style: solid; cursor: default; }\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, 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 sliders\n for (const [label, key, globalKey] of [\n [\"Trans\", \"translateScale\", \"translateScale\"],\n [\"Rot\", \"rotateScale\", \"rotateScale\"],\n [\"W\", \"wScale\", \"wScale\"],\n ] as const) {\n const row = document.createElement(\"div\");\n row.className = \"slider-row\";\n const val = (cfg as any)[key] ?? (mgr.config as any)[globalKey];\n row.innerHTML = `<label>${label}</label>` +\n `<input type=\"range\" min=\"0\" max=\"100\" value=\"${Math.round(unmapSlider(val))}\">` +\n `<span>${val.toFixed(4)}</span>`;\n const sl = row.querySelector(\"input\")! as HTMLInputElement;\n const sp = row.querySelector(\"span\")!;\n sl.addEventListener(\"input\", () => {\n const v = mapSlider(+sl.value);\n sp.textContent = v.toFixed(4);\n mgr.updateDeviceConfig(device.id, { [key]: v });\n });\n controls.appendChild(row);\n }\n\n // Button mappings\n const btnSection = document.createElement(\"div\");\n btnSection.className = \"btn-section\";\n const btnLabel = document.createElement(\"div\");\n btnLabel.className = \"btn-section-label\";\n btnLabel.textContent = \"Button Mappings\";\n btnSection.appendChild(btnLabel);\n\n const buttonRoutes: ButtonRoute[] = cfg.buttonRoutes ?? [];\n const labels = device.buttonLabels ?? [];\n for (let i = 0; i < buttonRoutes.length; i++) {\n const route = buttonRoutes[i];\n const btnName = labels[route.button] ?? `Btn ${route.button}`;\n const row = document.createElement(\"div\");\n row.className = \"btn-route\";\n\n const idxSpan = document.createElement(\"span\");\n idxSpan.className = \"btn-idx\";\n idxSpan.textContent = btnName;\n row.appendChild(idxSpan);\n\n const arrow = document.createElement(\"span\");\n arrow.className = \"btn-arrow\";\n arrow.textContent = \"\\u2192\";\n row.appendChild(arrow);\n\n const keySpan = document.createElement(\"span\");\n keySpan.className = \"btn-key\";\n keySpan.textContent = route.key;\n row.appendChild(keySpan);\n\n // Edit — re-listen for a new key\n const editBtn = document.createElement(\"button\");\n editBtn.className = \"btn-remove\";\n editBtn.textContent = \"\\u270E\";\n editBtn.title = \"Remap key\";\n const routeIdx = i;\n editBtn.addEventListener(\"click\", () => {\n keySpan.textContent = \"Press a key...\";\n keySpan.style.color = \"#f39c12\";\n const onKey = (e: KeyboardEvent) => {\n e.preventDefault();\n e.stopPropagation();\n document.removeEventListener(\"keydown\", onKey, true);\n const current = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];\n const updated = current.map((r: ButtonRoute, j: number) =>\n j === routeIdx ? { ...r, key: e.key, code: e.code } : r\n );\n mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });\n this.refreshControls(panel, device);\n };\n document.addEventListener(\"keydown\", onKey, true);\n });\n row.appendChild(editBtn);\n\n // Delete\n const removeBtn = document.createElement(\"button\");\n removeBtn.className = \"btn-remove\";\n removeBtn.textContent = \"\\u00d7\";\n removeBtn.title = \"Remove\";\n removeBtn.addEventListener(\"click\", () => {\n const current = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];\n const updated = current.filter((_: ButtonRoute, j: number) => j !== routeIdx);\n mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });\n this.refreshControls(panel, device);\n });\n row.appendChild(removeBtn);\n btnSection.appendChild(row);\n }\n\n // Add mapping button with listen flow\n const addBtn = document.createElement(\"button\");\n addBtn.className = \"btn-add\";\n addBtn.textContent = \"+ Add Button Mapping\";\n addBtn.addEventListener(\"click\", () => {\n if (addBtn.classList.contains(\"listening\")) return;\n this.startButtonListen(addBtn, mgr, device, panel);\n });\n btnSection.appendChild(addBtn);\n controls.appendChild(btnSection);\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(device: DeviceInfo, deviceAxes: string[]): AxisRoute[] {\n const mgr = this.manager!;\n\n // 1. Exact device ID\n const devCfg = mgr.config.devices[device.id];\n if (devCfg?.routes && Array.isArray(devCfg.routes)) return devCfg.routes;\n\n // 2. Pattern match\n for (const [pattern, cfg] of Object.entries(mgr.config.devices)) {\n if (pattern.endsWith(\"*\") && device.id.startsWith(pattern.slice(0, -1))) {\n if (cfg.routes && Array.isArray(cfg.routes)) return cfg.routes;\n }\n }\n\n // 3. Device class defaults\n if (device.deviceClass && mgr.config.deviceClasses) {\n const classCfg = mgr.config.deviceClasses[device.deviceClass];\n if (classCfg?.routes && Array.isArray(classCfg.routes)) return classCfg.routes;\n }\n\n // 4. Build from device axes metadata\n return buildRoutes(deviceAxes);\n }\n\n private updateRoute(deviceId: string, index: number, deviceAxes: string[], patch: Partial<AxisRoute>): void {\n const device = Array.from(this.manager!.getDevicesWithConfig()).find(d => d.device.id === deviceId)?.device;\n const base = this.getRoutes(device ?? { id: deviceId } as DeviceInfo, deviceAxes);\n const updated = base.map((r, j) => j === index ? { ...r, ...patch } : { ...r });\n this.manager!.updateDeviceConfig(deviceId, { routes: updated });\n }\n\n private startButtonListen(\n btn: HTMLButtonElement,\n mgr: InputManager,\n device: DeviceInfo,\n panel: HTMLDetailsElement,\n ): void {\n btn.classList.add(\"listening\");\n btn.textContent = \"Press a device button...\";\n\n // Step 1: Listen for device button\n const onButton = (event: ButtonEvent) => {\n if (!event.pressed) return; // only on press, not release\n mgr.off(\"buttonEvent\", onButton);\n\n const capturedButton = event.button;\n btn.textContent = `Btn ${capturedButton} \\u2192 Press a key...`;\n\n // Step 2: Listen for keyboard key\n const onKey = (e: KeyboardEvent) => {\n e.preventDefault();\n e.stopPropagation();\n document.removeEventListener(\"keydown\", onKey, true);\n\n const route: ButtonRoute = {\n button: capturedButton,\n key: e.key,\n code: e.code,\n };\n\n const current = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];\n // Replace existing mapping for the same button, or add new\n const updated = current.filter((r: ButtonRoute) => r.button !== capturedButton);\n updated.push(route);\n mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });\n this.refreshControls(panel, device);\n };\n document.addEventListener(\"keydown\", onKey, true);\n };\n mgr.on(\"buttonEvent\", onButton);\n\n // Cancel on Escape (before a button is pressed)\n const onCancel = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n mgr.off(\"buttonEvent\", onButton);\n document.removeEventListener(\"keydown\", onCancel, true);\n btn.classList.remove(\"listening\");\n btn.textContent = \"+ Add Button Mapping\";\n }\n };\n document.addEventListener(\"keydown\", onCancel, true);\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"]}
|
|
1
|
+
{"version":3,"sources":["../../src/elements/registry.ts","../../src/elements/locale.ts","../../src/elements/satmouse-status.ts","../../src/elements/satmouse-devices.ts","../../src/elements/satmouse-debug.ts"],"names":["current","TEMPLATE"],"mappings":";;;AAWA,IAAI,aAAA,GAAqC,IAAA;AACzC,IAAM,SAAA,uBAAgB,GAAA,EAA+B;AAE9C,SAAS,iBAAiB,OAAA,EAA6B;AAC5D,EAAA,aAAA,GAAgB,OAAA;AAChB,EAAA,KAAA,MAAW,EAAA,IAAM,SAAA,EAAW,EAAA,CAAG,OAAO,CAAA;AACtC,EAAA,SAAA,CAAU,KAAA,EAAM;AAClB;AAEO,SAAS,UAAA,GAAkC;AAChD,EAAA,OAAO,aAAA;AACT;AASO,SAAS,UAAU,EAAA,EAA2C;AACnE,EAAA,IAAI,aAAA,KAAkB,aAAa,CAAA;AAAA,OAC9B,SAAA,CAAU,IAAI,EAAE,CAAA;AACrB,EAAA,OAAO,MAAM,SAAA,CAAU,MAAA,CAAO,EAAE,CAAA;AAClC;;;ACJO,IAAM,cAAA,GAA2C;AAAA;AAAA,EAEtD,SAAA,EAAW,WAAA;AAAA,EACX,UAAA,EAAY,eAAA;AAAA,EACZ,YAAA,EAAc,cAAA;AAAA,EACd,UAAA,EAAY,aAAA;AAAA,EACZ,iBAAA,EAAmB,oBAAA;AAAA,EACnB,cAAA,EAAgB,iBAAA;AAAA,EAChB,gBAAA,EAAkB,mBAAA;AAAA,EAClB,eAAA,EAAiB,kBAAA;AAAA;AAAA,EAGjB,SAAA,EAAW,YAAA;AAAA,EACX,IAAA,EAAM,MAAA;AAAA,EACN,cAAA,EAAgB,OAAA;AAAA,EAChB,WAAA,EAAa,KAAA;AAAA,EACb,MAAA,EAAQ,GAAA;AAAA,EACR,cAAA,EAAgB,iBAAA;AAAA,EAChB,QAAA,EAAU,WAAA;AAAA,EACV,SAAA,EAAW,gBAAA;AAAA,EACX,MAAA,EAAQ,QAAA;AAAA,EACR,gBAAA,EAAkB,sBAAA;AAAA,EAClB,iBAAA,EAAmB,0BAAA;AAAA,EACnB,eAAA,EAAiB,kBAAA;AAAA;AAAA,EAGjB,GAAA,EAAK;AACP;AAEA,IAAI,OAAA,GAA0B,EAAE,GAAG,cAAA,EAAe;AAG3C,SAAS,UAAU,SAAA,EAA0C;AAClE,EAAA,OAAA,GAAU,EAAE,GAAG,OAAA,EAAS,GAAG,SAAA,EAAU;AACvC;AAGO,SAAS,SAAA,GAAsC;AACpD,EAAA,OAAO,OAAA;AACT;AAGO,SAAS,EAAE,GAAA,EAAmC;AACnD,EAAA,OAAO,QAAQ,GAAG,CAAA;AACpB;;;ACtEA,IAAM,QAAA,GAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAmBV,IAAM,cAAA,GAAN,cAA6B,WAAA,CAAY;AAAA,EACtC,GAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA,GAA+B,IAAA;AAAA,EAC/B,KAAA,GAA6B,IAAA;AAAA,EAC7B,SAAA,GAAmD,IAAA;AAAA,EAEnD,eAAe,CAAC,KAAA,EAAwB,aAAgC,IAAA,CAAK,MAAA,CAAO,OAAO,QAAQ,CAAA;AAAA,EAE3G,WAAA,GAAc;AACZ,IAAA,KAAA,EAAM;AACN,IAAA,MAAM,SAAS,IAAA,CAAK,YAAA,CAAa,EAAE,IAAA,EAAM,QAAQ,CAAA;AACjD,IAAA,MAAA,CAAO,SAAA,GAAY,QAAA;AACnB,IAAA,IAAA,CAAK,GAAA,GAAM,MAAA,CAAO,aAAA,CAAc,MAAM,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,MAAA,CAAO,aAAA,CAAc,OAAO,CAAA;AACxC,IAAA,IAAA,CAAK,KAAA,GAAQ,MAAA,CAAO,aAAA,CAAc,WAAW,CAAA;AAC7C,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA,CAAO,aAAA,CAAc,SAAS,CAAA;AAC5C,IAAA,IAAA,CAAK,IAAA,CAAK,WAAA,GAAc,CAAA,CAAE,cAAc,CAAA;AACxC,IAAA,IAAA,CAAK,MAAA,CAAO,WAAA,GAAc,CAAA,CAAE,gBAAgB,CAAA;AAE5C,IAAA,IAAA,CAAK,MAAA,CAAO,gBAAA,CAAiB,OAAA,EAAS,MAAM;AAC1C,MAAA,IAAA,CAAK,eAAA,EAAgB;AAAA,IACvB,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,iBAAA,GAAoB;AAClB,IAAA,IAAA,CAAK,QAAQ,SAAA,CAAU,CAAC,QAAQ,IAAA,CAAK,IAAA,CAAK,GAAG,CAAC,CAAA;AAE9C,IAAA,IAAA,CAAK,QAAA,EAAS;AACd,IAAA,IAAA,CAAK,OAAO,QAAA,GAAW,KAAA;AACvB,IAAA,IAAA,CAAK,MAAA,CAAO,WAAA,GAAc,CAAA,CAAE,gBAAgB,CAAA;AAAA,EAC9C;AAAA,EAEA,oBAAA,GAAuB;AACrB,IAAA,IAAA,CAAK,QAAA,EAAS;AACd,IAAA,IAAA,CAAK,KAAA,IAAQ;AACb,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EACd;AAAA,EAEQ,KAAK,GAAA,EAAyB;AACpC,IAAA,IAAA,CAAK,MAAA,EAAO;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,GAAA;AACf,IAAA,GAAA,CAAI,EAAA,CAAG,aAAA,EAAe,IAAA,CAAK,YAAY,CAAA;AACvC,IAAA,IAAA,CAAK,MAAA,CAAO,GAAA,CAAI,KAAA,EAAO,GAAA,CAAI,QAAQ,CAAA;AAAA,EACrC;AAAA,EAEQ,MAAA,GAAe;AACrB,IAAA,IAAA,CAAK,OAAA,EAAS,GAAA,CAAI,aAAA,EAAe,IAAA,CAAK,YAAY,CAAA;AAClD,IAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAAA,EACjB;AAAA,EAEQ,MAAA,CAAO,OAAwB,QAAA,EAAmC;AACxE,IAAA,IAAA,CAAK,GAAA,CAAI,QAAQ,KAAA,GAAQ,KAAA;AACzB,IAAA,IAAA,CAAK,KAAA,CAAM,WAAA,GAAc,QAAA,KAAa,MAAA,GAAS,QAAA,GAAW,EAAA;AAE1D,IAAA,IAAI,UAAU,WAAA,EAAa;AACzB,MAAA,IAAA,CAAK,QAAA,EAAS;AACd,MAAA,IAAA,CAAK,YAAA,GAAe,KAAA;AACpB,MAAA,IAAA,CAAK,IAAA,CAAK,WAAA,GAAc,CAAA,CAAE,WAAW,CAAA;AACrC,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,OAAA,GAAU,MAAA;AAAA,IAC9B,CAAA,MAAA,IAAW,UAAU,YAAA,EAAc;AACjC,MAAA,IAAA,CAAK,IAAA,CAAK,WAAA,GAAc,CAAA,CAAE,YAAY,CAAA;AACtC,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,OAAA,GAAU,MAAA;AAAA,IAC9B,CAAA,MAAA,IAAW,UAAU,QAAA,EAAU;AAE7B,MAAA,MAAM,QAAA,GAAW,gCAAA,CAAiC,IAAA,CAAK,SAAA,CAAU,SAAS,CAAA;AAC1E,MAAA,MAAM,YAAA,GAAe,CAAC,CAAE,UAAA,CAAmB,4BAAA;AAC3C,MAAA,IAAI,QAAA,IAAY,CAAC,YAAA,EAAc;AAC7B,QAAA,IAAA,CAAK,IAAA,CAAK,WAAA,GAAc,CAAA,CAAE,mBAAmB,CAAA;AAC7C,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,OAAA,GAAU,cAAA;AAC5B,QAAA,IAAA,CAAK,OAAO,QAAA,GAAW,KAAA;AACvB,QAAA,IAAA,CAAK,MAAA,CAAO,WAAA,GAAc,CAAA,CAAE,iBAAiB,CAAA;AAC7C,QAAA,IAAA,CAAK,YAAA,GAAe,KAAA;AACpB,QAAA,IAAA,CAAK,cAAA,GAAiB,IAAA;AAAA,MACxB,CAAA,MAAO;AACL,QAAA,IAAA,CAAK,IAAA,CAAK,WAAA,GAAc,CAAA,CAAE,YAAY,CAAA;AACtC,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,OAAA,GAAU,cAAA;AAC5B,QAAA,IAAA,CAAK,OAAO,QAAA,GAAW,KAAA;AACvB,QAAA,IAAA,CAAK,MAAA,CAAO,cAAc,IAAA,CAAK,YAAA,GAAe,EAAE,kBAAkB,CAAA,GAAI,EAAE,gBAAgB,CAAA;AACxF,QAAA,IAAA,CAAK,cAAA,GAAiB,KAAA;AAAA,MACxB;AAAA,IACF,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,IAAA,CAAK,WAAA,GAAc,CAAA,CAAE,cAAc,CAAA;AACxC,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,OAAA,GAAU,MAAA;AAAA,IAC9B;AAAA,EACF;AAAA,EAEQ,YAAA,GAAe,KAAA;AAAA,EACf,cAAA,GAAiB,KAAA;AAAA,EAEjB,eAAA,GAAwB;AAC9B,IAAA,IAAI,KAAK,cAAA,EAAgB;AAEvB,MAAA,MAAA,CAAO,SAAS,IAAA,GAAO,6BAAA;AAEvB,MAAA,IAAA,CAAK,MAAA,CAAO,WAAA,GAAc,CAAA,CAAE,YAAY,CAAA;AACxC,MAAA,IAAA,CAAK,OAAO,QAAA,GAAW,IAAA;AACvB,MAAA,IAAA,CAAK,QAAA,EAAS;AACd,MAAA,IAAA,CAAK,SAAA,GAAY,YAAY,MAAM;AACjC,QAAA,IAAI,IAAA,CAAK,OAAA,EAAS,KAAA,KAAU,WAAA,EAAa;AAAE,UAAA,IAAA,CAAK,QAAA,EAAS;AAAG,UAAA;AAAA,QAAQ;AACpE,QAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AAAA,MACtB,GAAG,GAAI,CAAA;AAEP,MAAA,UAAA,CAAW,MAAM;AAAE,QAAA,IAAA,CAAK,QAAA,EAAS;AAAG,QAAA,IAAA,CAAK,OAAO,QAAA,GAAW,KAAA;AAAO,QAAA,IAAA,CAAK,MAAA,CAAO,WAAA,GAAc,CAAA,CAAE,iBAAiB,CAAA;AAAA,MAAG,GAAG,GAAK,CAAA;AAC1H,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,KAAK,YAAA,EAAc;AACrB,MAAA,MAAA,CAAO,SAAS,IAAA,GAAO,sDAAA;AACvB,MAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,MAAA,CAAO,WAAA,GAAc,CAAA,CAAE,YAAY,CAAA;AACxC,IAAA,IAAA,CAAK,OAAO,QAAA,GAAW,IAAA;AAEvB,IAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AACpB,IAAA,MAAA,CAAO,SAAS,IAAA,GAAO,mBAAA;AAEvB,IAAA,IAAI,QAAA,GAAW,CAAA;AACf,IAAA,IAAA,CAAK,QAAA,EAAS;AACd,IAAA,IAAA,CAAK,SAAA,GAAY,YAAY,MAAM;AACjC,MAAA,QAAA,EAAA;AACA,MAAA,IAAI,IAAA,CAAK,OAAA,EAAS,KAAA,KAAU,WAAA,EAAa;AACvC,QAAA,IAAA,CAAK,QAAA,EAAS;AACd,QAAA,IAAA,CAAK,YAAA,GAAe,KAAA;AACpB,QAAA;AAAA,MACF;AACA,MAAA,IAAI,YAAY,CAAA,EAAG;AACjB,QAAA,IAAA,CAAK,QAAA,EAAS;AACd,QAAA,IAAA,CAAK,YAAA,GAAe,IAAA;AACpB,QAAA,IAAA,CAAK,OAAO,QAAA,GAAW,KAAA;AACvB,QAAA,IAAA,CAAK,MAAA,CAAO,WAAA,GAAc,CAAA,CAAE,kBAAkB,CAAA;AAC9C,QAAA;AAAA,MACF;AACA,MAAA,IAAA,CAAK,SAAS,KAAA,EAAM;AAAA,IACtB,GAAG,IAAI,CAAA;AAAA,EACT;AAAA,EAEQ,QAAA,GAAiB;AACvB,IAAA,IAAI,KAAK,SAAA,EAAW;AAClB,MAAA,aAAA,CAAc,KAAK,SAAS,CAAA;AAC5B,MAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AAAA,IACnB;AAAA,EACF;AACF;AAEA,cAAA,CAAe,MAAA,CAAO,mBAAmB,cAAc,CAAA;;;ACnKvD,IAAM,MAAA,GAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAqCf,SAAS,UAAU,CAAA,EAAmB;AAAE,EAAA,OAAO,IAAA,GAAS,IAAA,CAAK,GAAA,CAAI,GAAA,EAAK,IAAI,GAAG,CAAA;AAAG;AAChF,SAAS,YAAY,CAAA,EAAmB;AAAE,EAAA,OAAQ,GAAA,GAAM,KAAK,GAAA,CAAI,CAAA,GAAI,IAAM,CAAA,GAAK,IAAA,CAAK,IAAI,GAAG,CAAA;AAAG;AAExF,IAAM,eAAA,GAAN,cAA8B,WAAA,CAAY;AAAA,EACvC,OAAA,GAA+B,IAAA;AAAA,EAC/B,SAAA;AAAA,EAER,WAAA,GAAc;AACZ,IAAA,KAAA,EAAM;AACN,IAAA,MAAM,SAAS,IAAA,CAAK,YAAA,CAAa,EAAE,IAAA,EAAM,QAAQ,CAAA;AACjD,IAAA,MAAA,CAAO,YAAY,MAAA,GAAS,CAAA,kEAAA,CAAA;AAC5B,IAAA,IAAA,CAAK,SAAA,GAAY,MAAA,CAAO,aAAA,CAAc,YAAY,CAAA;AAAA,EACpD;AAAA,EAEQ,KAAA,GAA6B,IAAA;AAAA,EAE7B,mBAAA,GAAsB,CAAC,KAAA,EAAqC,MAAA,KAAuB;AACzF,IAAA,IAAI,KAAA,KAAU,WAAA,EAAa,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA;AAAA,SAC3C,IAAA,CAAK,aAAa,MAAM,CAAA;AAAA,EAC/B,CAAA;AAAA,EAEQ,YAAA,GAAe,CAAC,KAAA,KAAkB;AACxC,IAAA,IAAI,UAAU,WAAA,EAAa;AACzB,MAAA,IAAA,CAAK,OAAA,EAAS,eAAA,EAAgB,CAAE,IAAA,CAAK,CAAC,OAAA,KAAY,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAA,KAAM,IAAA,CAAK,SAAA,CAAU,CAAC,CAAC,CAAC,CAAA;AAAA,IAC7F;AAAA,EACF,CAAA;AAAA,EAEA,iBAAA,GAAoB;AAClB,IAAA,IAAA,CAAK,QAAQ,SAAA,CAAU,CAAC,QAAQ,IAAA,CAAK,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,EAChD;AAAA,EAEA,oBAAA,GAAuB;AACrB,IAAA,IAAA,CAAK,KAAA,IAAQ;AACb,IAAA,IAAA,CAAK,MAAA,EAAO;AACZ,IAAA,IAAA,CAAK,SAAA,CAAU,SAAA,GAAY,CAAA,oBAAA,EAAuB,CAAA,CAAE,WAAW,CAAC,CAAA,OAAA,CAAA;AAAA,EAClE;AAAA,EAEQ,KAAK,GAAA,EAAyB;AACpC,IAAA,IAAA,CAAK,MAAA,EAAO;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,GAAA;AACf,IAAA,GAAA,CAAI,EAAA,CAAG,cAAA,EAAgB,IAAA,CAAK,mBAAmB,CAAA;AAC/C,IAAA,GAAA,CAAI,EAAA,CAAG,aAAA,EAAe,IAAA,CAAK,YAAY,CAAA;AACvC,IAAA,IAAI,GAAA,CAAI,UAAU,WAAA,EAAa;AAC7B,MAAA,GAAA,CAAI,eAAA,EAAgB,CAAE,IAAA,CAAK,CAAC,OAAA,KAAY,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAA,KAAM,IAAA,CAAK,SAAA,CAAU,CAAC,CAAC,CAAC,CAAA;AAAA,IACnF;AAAA,EACF;AAAA,EAEQ,MAAA,GAAe;AACrB,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,cAAA,EAAgB,IAAA,CAAK,mBAAmB,CAAA;AACzD,MAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,aAAA,EAAe,IAAA,CAAK,YAAY,CAAA;AACjD,MAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAAA,IACjB;AAAA,EACF;AAAA,EAEQ,UAAU,MAAA,EAA0B;AAC1C,IAAA,MAAM,WAAW,IAAA,CAAK,UAAA,CAAY,eAAe,CAAA,IAAA,EAAO,MAAA,CAAO,EAAE,CAAA,CAAE,CAAA;AACnE,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,IAAA,CAAK,eAAA,CAAgB,UAAgC,MAAM,CAAA;AAC3D,MAAA;AAAA,IACF;AACA,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,SAAA,CAAU,aAAA,CAAc,QAAQ,CAAA;AACnD,IAAA,IAAI,KAAA,QAAa,MAAA,EAAO;AAExB,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,aAAA,CAAc,SAAS,CAAA;AAC9C,IAAA,KAAA,CAAM,SAAA,GAAY,OAAA;AAClB,IAAA,KAAA,CAAM,EAAA,GAAK,CAAA,IAAA,EAAO,MAAA,CAAO,EAAE,CAAA,CAAA;AAC3B,IAAA,KAAA,CAAM,IAAA,GAAO,IAAA;AAEb,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,SAAS,CAAA;AAChD,IAAA,OAAA,CAAQ,SAAA,GAAY,GAAG,MAAA,CAAO,KAAA,IAAS,OAAO,IAAI,CAAA,mBAAA,EAAsB,MAAA,CAAO,cAAA,IAAkB,EAAE,CAAA,OAAA,CAAA;AACnG,IAAA,KAAA,CAAM,YAAY,OAAO,CAAA;AAEzB,IAAA,IAAA,CAAK,eAAA,CAAgB,OAAO,MAAM,CAAA;AAClC,IAAA,IAAA,CAAK,SAAA,CAAU,YAAY,KAAK,CAAA;AAAA,EAClC;AAAA,EAEQ,eAAA,CAAgB,OAA2B,MAAA,EAA0B;AAC3E,IAAA,MAAM,GAAA,GAAM,KAAA,CAAM,aAAA,CAAc,WAAW,CAAA;AAC3C,IAAA,IAAI,GAAA,MAAS,MAAA,EAAO;AAEpB,IAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,MAAA,CAAO,EAAE,CAAA;AAEzC,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC7C,IAAA,QAAA,CAAS,SAAA,GAAY,UAAA;AAGrB,IAAA,MAAM,UAAA,GAAa,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC/C,IAAA,UAAA,CAAW,SAAA,GAAY,aAAA;AACvB,IAAA,MAAM,UAAA,GAAa,OAAO,IAAA,IAAQ,CAAC,MAAM,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,IAAA,EAAM,IAAI,CAAA;AACrE,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,SAAA,CAAU,MAAA,EAAQ,UAAU,CAAA;AAEhD,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,UAAA,CAAW,QAAQ,CAAA,EAAA,EAAK;AAC1C,MAAA,MAAM,QAAQ,MAAA,CAAO,CAAC,CAAA,IAAK,EAAE,QAAQ,UAAA,CAAW,CAAC,CAAA,EAAgB,MAAA,EAAQ,WAAW,CAAC,CAAA,CAAE,OAAA,CAAQ,OAAA,EAAS,EAAE,CAAA,EAAe;AACzH,MAAA,MAAM,GAAA,GAAM,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AACxC,MAAA,GAAA,CAAI,SAAA,GAAY,WAAA;AAGhB,MAAA,MAAM,EAAA,GAAK,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA;AACzC,MAAA,EAAA,CAAG,IAAA,GAAO,UAAA;AACV,MAAA,EAAA,CAAG,OAAA,GAAU,MAAM,IAAA,IAAQ,KAAA;AAC3B,MAAA,EAAA,CAAG,KAAA,GAAQ,EAAE,MAAM,CAAA;AACnB,MAAA,MAAM,UAAA,GAAa,CAAA;AACnB,MAAA,EAAA,CAAG,gBAAA,CAAiB,UAAU,MAAM;AAClC,QAAA,IAAA,CAAK,WAAA,CAAY,OAAO,EAAA,EAAI,UAAA,EAAY,YAAY,EAAE,IAAA,EAAM,EAAA,CAAG,OAAA,EAAS,CAAA;AAAA,MAC1E,CAAC,CAAA;AACD,MAAA,GAAA,CAAI,YAAY,EAAE,CAAA;AAGlB,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA;AAC5C,MAAA,KAAA,CAAM,WAAA,GAAc,OAAO,UAAA,GAAa,CAAC,KAAK,UAAA,CAAW,CAAC,EAAE,WAAA,EAAY;AACxE,MAAA,GAAA,CAAI,YAAY,KAAK,CAAA;AAGrB,MAAA,MAAM,GAAA,GAAM,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC3C,MAAA,KAAA,MAAW,UAAU,SAAA,EAAW;AAC9B,QAAA,MAAM,GAAA,GAAM,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC3C,QAAA,GAAA,CAAI,KAAA,GAAQ,MAAA;AACZ,QAAA,GAAA,CAAI,WAAA,GAAc,OAAO,WAAA,EAAY;AACrC,QAAA,IAAI,MAAA,KAAW,KAAA,CAAM,MAAA,EAAQ,GAAA,CAAI,QAAA,GAAW,IAAA;AAC5C,QAAA,GAAA,CAAI,YAAY,GAAG,CAAA;AAAA,MACrB;AACA,MAAA,GAAA,CAAI,gBAAA,CAAiB,UAAU,MAAM;AACnC,QAAA,IAAA,CAAK,WAAA,CAAY,OAAO,EAAA,EAAI,UAAA,EAAY,YAAY,EAAE,MAAA,EAAQ,GAAA,CAAI,KAAA,EAAoB,CAAA;AAAA,MACxF,CAAC,CAAA;AACD,MAAA,GAAA,CAAI,YAAY,GAAG,CAAA;AAEnB,MAAA,UAAA,CAAW,YAAY,GAAG,CAAA;AAAA,IAC5B;AACA,IAAA,QAAA,CAAS,YAAY,UAAU,CAAA;AAG/B,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,GAAA,EAAK,SAAS,CAAA,IAAK;AAAA,MACpC,CAAC,CAAA,CAAE,gBAAgB,CAAA,EAAG,kBAAkB,gBAAgB,CAAA;AAAA,MACxD,CAAC,CAAA,CAAE,aAAa,CAAA,EAAG,eAAe,aAAa,CAAA;AAAA,MAC/C,CAAC,CAAA,CAAE,QAAQ,CAAA,EAAG,UAAU,QAAQ;AAAA,KAClC,EAAY;AACV,MAAA,MAAM,GAAA,GAAM,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AACxC,MAAA,GAAA,CAAI,SAAA,GAAY,YAAA;AAChB,MAAA,MAAM,MAAO,GAAA,CAAY,GAAG,CAAA,IAAM,GAAA,CAAI,OAAe,SAAS,CAAA;AAC9D,MAAA,GAAA,CAAI,SAAA,GAAY,CAAA,OAAA,EAAU,KAAK,CAAA,qDAAA,EACmB,KAAK,KAAA,CAAM,WAAA,CAAY,GAAG,CAAC,CAAC,CAAA,QAAA,EACnE,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,OAAA,CAAA;AACzB,MAAA,MAAM,EAAA,GAAK,GAAA,CAAI,aAAA,CAAc,OAAO,CAAA;AACpC,MAAA,MAAM,EAAA,GAAK,GAAA,CAAI,aAAA,CAAc,MAAM,CAAA;AACnC,MAAA,EAAA,CAAG,gBAAA,CAAiB,SAAS,MAAM;AACjC,QAAA,MAAM,CAAA,GAAI,SAAA,CAAU,CAAC,EAAA,CAAG,KAAK,CAAA;AAC7B,QAAA,EAAA,CAAG,WAAA,GAAc,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAC5B,QAAA,GAAA,CAAI,kBAAA,CAAmB,OAAO,EAAA,EAAI,EAAE,CAAC,GAAG,GAAG,GAAG,CAAA;AAAA,MAChD,CAAC,CAAA;AACD,MAAA,QAAA,CAAS,YAAY,GAAG,CAAA;AAAA,IAC1B;AAGA,IAAA,MAAM,UAAA,GAAa,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC/C,IAAA,UAAA,CAAW,SAAA,GAAY,aAAA;AACvB,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC7C,IAAA,QAAA,CAAS,SAAA,GAAY,mBAAA;AACrB,IAAA,QAAA,CAAS,WAAA,GAAc,EAAE,gBAAgB,CAAA;AACzC,IAAA,UAAA,CAAW,YAAY,QAAQ,CAAA;AAE/B,IAAA,MAAM,YAAA,GAA8B,GAAA,CAAI,YAAA,IAAgB,EAAC;AACzD,IAAA,MAAM,MAAA,GAAS,MAAA,CAAO,YAAA,IAAgB,EAAC;AACvC,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,YAAA,CAAa,QAAQ,CAAA,EAAA,EAAK;AAC5C,MAAA,MAAM,KAAA,GAAQ,aAAa,CAAC,CAAA;AAC5B,MAAA,MAAM,UAAU,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,IAAK,CAAA,IAAA,EAAO,MAAM,MAAM,CAAA,CAAA;AAC3D,MAAA,MAAM,GAAA,GAAM,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AACxC,MAAA,GAAA,CAAI,SAAA,GAAY,WAAA;AAEhB,MAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA;AAC7C,MAAA,OAAA,CAAQ,SAAA,GAAY,SAAA;AACpB,MAAA,OAAA,CAAQ,WAAA,GAAc,OAAA;AACtB,MAAA,GAAA,CAAI,YAAY,OAAO,CAAA;AAEvB,MAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA;AAC3C,MAAA,KAAA,CAAM,SAAA,GAAY,WAAA;AAClB,MAAA,KAAA,CAAM,WAAA,GAAc,QAAA;AACpB,MAAA,GAAA,CAAI,YAAY,KAAK,CAAA;AAErB,MAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA;AAC7C,MAAA,OAAA,CAAQ,SAAA,GAAY,SAAA;AACpB,MAAA,OAAA,CAAQ,cAAc,KAAA,CAAM,GAAA;AAC5B,MAAA,GAAA,CAAI,YAAY,OAAO,CAAA;AAGvB,MAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC/C,MAAA,OAAA,CAAQ,SAAA,GAAY,YAAA;AACpB,MAAA,OAAA,CAAQ,WAAA,GAAc,QAAA;AACtB,MAAA,OAAA,CAAQ,KAAA,GAAQ,EAAE,UAAU,CAAA;AAC5B,MAAA,MAAM,QAAA,GAAW,CAAA;AACjB,MAAA,OAAA,CAAQ,gBAAA,CAAiB,SAAS,MAAM;AACtC,QAAA,OAAA,CAAQ,WAAA,GAAc,EAAE,WAAW,CAAA;AACnC,QAAA,OAAA,CAAQ,MAAM,KAAA,GAAQ,SAAA;AACtB,QAAA,MAAM,KAAA,GAAQ,CAAC,CAAA,KAAqB;AAClC,UAAA,CAAA,CAAE,cAAA,EAAe;AACjB,UAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,UAAA,QAAA,CAAS,mBAAA,CAAoB,SAAA,EAAW,KAAA,EAAO,IAAI,CAAA;AACnD,UAAA,MAAMA,WAAU,GAAA,CAAI,eAAA,CAAgB,OAAO,EAAE,CAAA,CAAE,gBAAgB,EAAC;AAChE,UAAA,MAAM,UAAUA,QAAAA,CAAQ,GAAA;AAAA,YAAI,CAAC,CAAA,EAAgB,CAAA,KAC3C,CAAA,KAAM,WAAW,EAAE,GAAG,CAAA,EAAG,GAAA,EAAK,CAAA,CAAE,GAAA,EAAK,IAAA,EAAM,CAAA,CAAE,MAAK,GAAI;AAAA,WACxD;AACA,UAAA,GAAA,CAAI,mBAAmB,MAAA,CAAO,EAAA,EAAI,EAAE,YAAA,EAAc,SAAS,CAAA;AAC3D,UAAA,IAAA,CAAK,eAAA,CAAgB,OAAO,MAAM,CAAA;AAAA,QACpC,CAAA;AACA,QAAA,QAAA,CAAS,gBAAA,CAAiB,SAAA,EAAW,KAAA,EAAO,IAAI,CAAA;AAAA,MAClD,CAAC,CAAA;AACD,MAAA,GAAA,CAAI,YAAY,OAAO,CAAA;AAGvB,MAAA,MAAM,SAAA,GAAY,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AACjD,MAAA,SAAA,CAAU,SAAA,GAAY,YAAA;AACtB,MAAA,SAAA,CAAU,WAAA,GAAc,MAAA;AACxB,MAAA,SAAA,CAAU,KAAA,GAAQ,EAAE,QAAQ,CAAA;AAC5B,MAAA,SAAA,CAAU,gBAAA,CAAiB,SAAS,MAAM;AACxC,QAAA,MAAMA,WAAU,GAAA,CAAI,eAAA,CAAgB,OAAO,EAAE,CAAA,CAAE,gBAAgB,EAAC;AAChE,QAAA,MAAM,UAAUA,QAAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,EAAgB,CAAA,KAAc,MAAM,QAAQ,CAAA;AAC5E,QAAA,GAAA,CAAI,mBAAmB,MAAA,CAAO,EAAA,EAAI,EAAE,YAAA,EAAc,SAAS,CAAA;AAC3D,QAAA,IAAA,CAAK,eAAA,CAAgB,OAAO,MAAM,CAAA;AAAA,MACpC,CAAC,CAAA;AACD,MAAA,GAAA,CAAI,YAAY,SAAS,CAAA;AACzB,MAAA,UAAA,CAAW,YAAY,GAAG,CAAA;AAAA,IAC5B;AAGA,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC9C,IAAA,MAAA,CAAO,SAAA,GAAY,SAAA;AACnB,IAAA,MAAA,CAAO,WAAA,GAAc,EAAE,kBAAkB,CAAA;AACzC,IAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,MAAM;AACrC,MAAA,IAAI,MAAA,CAAO,SAAA,CAAU,QAAA,CAAS,WAAW,CAAA,EAAG;AAC5C,MAAA,IAAA,CAAK,iBAAA,CAAkB,MAAA,EAAQ,GAAA,EAAK,MAAA,EAAQ,KAAK,CAAA;AAAA,IACnD,CAAC,CAAA;AACD,IAAA,UAAA,CAAW,YAAY,MAAM,CAAA;AAC7B,IAAA,QAAA,CAAS,YAAY,UAAU,CAAA;AAG/B,IAAA,MAAM,QAAA,GAAW,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAChD,IAAA,QAAA,CAAS,SAAA,GAAY,WAAA;AACrB,IAAA,QAAA,CAAS,WAAA,GAAc,EAAE,iBAAiB,CAAA;AAC1C,IAAA,QAAA,CAAS,gBAAA,CAAiB,SAAS,MAAM;AACvC,MAAA,GAAA,CAAI,iBAAA,CAAkB,OAAO,EAAE,CAAA;AAC/B,MAAA,IAAA,CAAK,eAAA,CAAgB,OAAO,MAAM,CAAA;AAAA,IACpC,CAAC,CAAA;AACD,IAAA,QAAA,CAAS,YAAY,QAAQ,CAAA;AAE7B,IAAA,KAAA,CAAM,YAAY,QAAQ,CAAA;AAAA,EAC5B;AAAA,EAEQ,SAAA,CAAU,QAAoB,UAAA,EAAmC;AACvE,IAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AAGjB,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,MAAA,CAAO,OAAA,CAAQ,OAAO,EAAE,CAAA;AAC3C,IAAA,IAAI,MAAA,EAAQ,UAAU,KAAA,CAAM,OAAA,CAAQ,OAAO,MAAM,CAAA,SAAU,MAAA,CAAO,MAAA;AAGlE,IAAA,KAAA,MAAW,CAAC,SAAS,GAAG,CAAA,IAAK,OAAO,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,OAAO,CAAA,EAAG;AAC/D,MAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,IAAK,MAAA,CAAO,EAAA,CAAG,UAAA,CAAW,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA,EAAG;AACvE,QAAA,IAAI,GAAA,CAAI,UAAU,KAAA,CAAM,OAAA,CAAQ,IAAI,MAAM,CAAA,SAAU,GAAA,CAAI,MAAA;AAAA,MAC1D;AAAA,IACF;AAGA,IAAA,IAAI,MAAA,CAAO,WAAA,IAAe,GAAA,CAAI,MAAA,CAAO,aAAA,EAAe;AAClD,MAAA,MAAM,QAAA,GAAW,GAAA,CAAI,MAAA,CAAO,aAAA,CAAc,OAAO,WAAW,CAAA;AAC5D,MAAA,IAAI,QAAA,EAAU,UAAU,KAAA,CAAM,OAAA,CAAQ,SAAS,MAAM,CAAA,SAAU,QAAA,CAAS,MAAA;AAAA,IAC1E;AAGA,IAAA,OAAO,YAAY,UAAU,CAAA;AAAA,EAC/B;AAAA,EAEQ,WAAA,CAAY,QAAA,EAAkB,KAAA,EAAe,UAAA,EAAsB,KAAA,EAAiC;AAC1G,IAAA,MAAM,MAAA,GAAS,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,QAAS,oBAAA,EAAsB,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,KAAK,CAAA,CAAE,MAAA,CAAO,EAAA,KAAO,QAAQ,CAAA,EAAG,MAAA;AACrG,IAAA,MAAM,IAAA,GAAO,KAAK,SAAA,CAAU,MAAA,IAAU,EAAE,EAAA,EAAI,QAAA,IAA0B,UAAU,CAAA;AAChF,IAAA,MAAM,UAAU,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,EAAG,MAAM,CAAA,KAAM,KAAA,GAAQ,EAAE,GAAG,GAAG,GAAG,KAAA,KAAU,EAAE,GAAG,GAAG,CAAA;AAC9E,IAAA,IAAA,CAAK,QAAS,kBAAA,CAAmB,QAAA,EAAU,EAAE,MAAA,EAAQ,SAAS,CAAA;AAAA,EAChE;AAAA,EAEQ,iBAAA,CACN,GAAA,EACA,GAAA,EACA,MAAA,EACA,KAAA,EACM;AACN,IAAA,GAAA,CAAI,SAAA,CAAU,IAAI,WAAW,CAAA;AAC7B,IAAA,GAAA,CAAI,WAAA,GAAc,EAAE,mBAAmB,CAAA;AAGvC,IAAA,MAAM,QAAA,GAAW,CAAC,KAAA,KAAuB;AACvC,MAAA,IAAI,CAAC,MAAM,OAAA,EAAS;AACpB,MAAA,GAAA,CAAI,GAAA,CAAI,eAAe,QAAQ,CAAA;AAE/B,MAAA,MAAM,iBAAiB,KAAA,CAAM,MAAA;AAC7B,MAAA,GAAA,CAAI,cAAc,CAAA,IAAA,EAAO,cAAc,CAAA,QAAA,EAAW,CAAA,CAAE,WAAW,CAAC,CAAA,CAAA;AAGhE,MAAA,MAAM,KAAA,GAAQ,CAAC,CAAA,KAAqB;AAClC,QAAA,CAAA,CAAE,cAAA,EAAe;AACjB,QAAA,CAAA,CAAE,eAAA,EAAgB;AAClB,QAAA,QAAA,CAAS,mBAAA,CAAoB,SAAA,EAAW,KAAA,EAAO,IAAI,CAAA;AAEnD,QAAA,MAAM,KAAA,GAAqB;AAAA,UACzB,MAAA,EAAQ,cAAA;AAAA,UACR,KAAK,CAAA,CAAE,GAAA;AAAA,UACP,MAAM,CAAA,CAAE;AAAA,SACV;AAEA,QAAA,MAAMA,WAAU,GAAA,CAAI,eAAA,CAAgB,OAAO,EAAE,CAAA,CAAE,gBAAgB,EAAC;AAEhE,QAAA,MAAM,UAAUA,QAAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAmB,CAAA,CAAE,WAAW,cAAc,CAAA;AAC9E,QAAA,OAAA,CAAQ,KAAK,KAAK,CAAA;AAClB,QAAA,GAAA,CAAI,mBAAmB,MAAA,CAAO,EAAA,EAAI,EAAE,YAAA,EAAc,SAAS,CAAA;AAC3D,QAAA,IAAA,CAAK,eAAA,CAAgB,OAAO,MAAM,CAAA;AAAA,MACpC,CAAA;AACA,MAAA,QAAA,CAAS,gBAAA,CAAiB,SAAA,EAAW,KAAA,EAAO,IAAI,CAAA;AAAA,IAClD,CAAA;AACA,IAAA,GAAA,CAAI,EAAA,CAAG,eAAe,QAAQ,CAAA;AAG9B,IAAA,MAAM,QAAA,GAAW,CAAC,CAAA,KAAqB;AACrC,MAAA,IAAI,CAAA,CAAE,QAAQ,QAAA,EAAU;AACtB,QAAA,GAAA,CAAI,GAAA,CAAI,eAAe,QAAQ,CAAA;AAC/B,QAAA,QAAA,CAAS,mBAAA,CAAoB,SAAA,EAAW,QAAA,EAAU,IAAI,CAAA;AACtD,QAAA,GAAA,CAAI,SAAA,CAAU,OAAO,WAAW,CAAA;AAChC,QAAA,GAAA,CAAI,WAAA,GAAc,EAAE,kBAAkB,CAAA;AAAA,MACxC;AAAA,IACF,CAAA;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,SAAA,EAAW,QAAA,EAAU,IAAI,CAAA;AAAA,EACrD;AAAA,EAEQ,aAAa,MAAA,EAA0B;AAC7C,IAAA,IAAA,CAAK,WAAY,cAAA,CAAe,CAAA,IAAA,EAAO,OAAO,EAAE,CAAA,CAAE,GAAG,MAAA,EAAO;AAC5D,IAAA,IAAI,IAAA,CAAK,SAAA,CAAU,QAAA,CAAS,MAAA,KAAW,CAAA,EAAG;AACxC,MAAA,IAAA,CAAK,SAAA,CAAU,SAAA,GAAY,CAAA,oBAAA,EAAuB,CAAA,CAAE,WAAW,CAAC,CAAA,OAAA,CAAA;AAAA,IAClE;AAAA,EACF;AACF;AAEA,cAAA,CAAe,MAAA,CAAO,oBAAoB,eAAe,CAAA;;;AC5XzD,IAAMC,SAAAA,GAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAiBV,IAAM,aAAA,GAAN,cAA4B,WAAA,CAAY;AAAA,EACrC,MAAmC,EAAC;AAAA,EACpC,UAAA,GAAa,CAAA;AAAA,EACb,WAAA,GAAqD,IAAA;AAAA,EACrD,OAAA,GAA+B,IAAA;AAAA,EAC/B,KAAA,GAA6B,IAAA;AAAA,EAE7B,cAAA,GAAiB,CAAC,IAAA,KAAsB;AAC9C,IAAA,IAAA,CAAK,UAAA,EAAA;AACL,IAAA,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,GAAc,MAAA,CAAO,KAAK,KAAA,CAAM,IAAA,CAAK,WAAA,CAAY,CAAC,CAAC,CAAA;AAC/D,IAAA,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,GAAc,MAAA,CAAO,KAAK,KAAA,CAAM,IAAA,CAAK,WAAA,CAAY,CAAC,CAAC,CAAA;AAC/D,IAAA,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,GAAc,MAAA,CAAO,KAAK,KAAA,CAAM,IAAA,CAAK,WAAA,CAAY,CAAC,CAAC,CAAA;AAC/D,IAAA,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,GAAc,MAAA,CAAO,KAAK,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,CAAC,CAAC,CAAA;AAC5D,IAAA,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,GAAc,MAAA,CAAO,KAAK,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,CAAC,CAAC,CAAA;AAC5D,IAAA,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,GAAc,MAAA,CAAO,KAAK,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,CAAC,CAAC,CAAA;AAAA,EAC9D,CAAA;AAAA,EAEQ,YAAA,GAAe,CAAC,KAAA,EAAwB,QAAA,KAAgC;AAC9E,IAAA,IAAA,CAAK,GAAA,CAAI,MAAM,WAAA,GAAc,KAAA;AAC7B,IAAA,IAAA,CAAK,GAAA,CAAI,QAAA,CAAS,WAAA,GAAc,QAAA,KAAa,SAAS,QAAA,GAAW,EAAA;AAAA,EACnE,CAAA;AAAA,EAEA,WAAA,GAAc;AACZ,IAAA,KAAA,EAAM;AACN,IAAA,MAAM,SAAS,IAAA,CAAK,YAAA,CAAa,EAAE,IAAA,EAAM,QAAQ,CAAA;AACjD,IAAA,MAAA,CAAO,SAAA,GAAYA,SAAAA;AACnB,IAAA,KAAA,MAAW,EAAA,IAAM,CAAC,IAAA,EAAM,IAAA,EAAM,MAAM,IAAA,EAAM,IAAA,EAAM,IAAI,CAAA,EAAG;AACrD,MAAA,IAAA,CAAK,GAAA,CAAI,EAAE,CAAA,GAAI,MAAA,CAAO,eAAe,EAAE,CAAA;AAAA,IACzC;AACA,IAAA,IAAA,CAAK,GAAA,CAAI,KAAA,GAAQ,MAAA,CAAO,aAAA,CAAc,QAAQ,CAAA;AAC9C,IAAA,IAAA,CAAK,GAAA,CAAI,QAAA,GAAW,MAAA,CAAO,aAAA,CAAc,WAAW,CAAA;AACpD,IAAA,IAAA,CAAK,GAAA,CAAI,GAAA,GAAM,MAAA,CAAO,aAAA,CAAc,MAAM,CAAA;AAC1C,IAAA,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,WAAA,GAAc,CAAA,CAAE,cAAc,CAAA;AAC7C,IAAA,MAAA,CAAO,aAAA,CAAc,YAAY,CAAA,CAAG,WAAA,GAAc,EAAE,KAAK,CAAA;AAAA,EAC3D;AAAA,EAEA,iBAAA,GAAoB;AAClB,IAAA,IAAA,CAAK,QAAQ,SAAA,CAAU,CAAC,QAAQ,IAAA,CAAK,IAAA,CAAK,GAAG,CAAC,CAAA;AAC9C,IAAA,IAAA,CAAK,WAAA,GAAc,YAAY,MAAM;AACnC,MAAA,IAAA,CAAK,GAAA,CAAI,GAAA,CAAI,WAAA,GAAc,MAAA,CAAO,KAAK,UAAU,CAAA;AACjD,MAAA,IAAA,CAAK,UAAA,GAAa,CAAA;AAAA,IACpB,GAAG,GAAI,CAAA;AAAA,EACT;AAAA,EAEA,oBAAA,GAAuB;AACrB,IAAA,IAAA,CAAK,KAAA,IAAQ;AACb,IAAA,IAAA,CAAK,MAAA,EAAO;AACZ,IAAA,IAAI,KAAK,WAAA,EAAa;AACpB,MAAA,aAAA,CAAc,KAAK,WAAW,CAAA;AAC9B,MAAA,IAAA,CAAK,WAAA,GAAc,IAAA;AAAA,IACrB;AAAA,EACF;AAAA,EAEQ,KAAK,GAAA,EAAyB;AACpC,IAAA,IAAA,CAAK,MAAA,EAAO;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,GAAA;AACf,IAAA,GAAA,CAAI,EAAA,CAAG,gBAAA,EAAkB,IAAA,CAAK,cAAc,CAAA;AAC5C,IAAA,GAAA,CAAI,EAAA,CAAG,aAAA,EAAe,IAAA,CAAK,YAAY,CAAA;AACvC,IAAA,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,WAAA,GAAc,GAAA,CAAI,KAAA;AACjC,IAAA,IAAA,CAAK,IAAI,QAAA,CAAS,WAAA,GAAc,IAAI,QAAA,KAAa,MAAA,GAAS,IAAI,QAAA,GAAW,EAAA;AAAA,EAC3E;AAAA,EAEQ,MAAA,GAAe;AACrB,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,gBAAA,EAAkB,IAAA,CAAK,cAAc,CAAA;AACtD,MAAA,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,aAAA,EAAe,IAAA,CAAK,YAAY,CAAA;AACjD,MAAA,IAAA,CAAK,OAAA,GAAU,IAAA;AAAA,IACjB;AAAA,EACF;AACF;AAEA,cAAA,CAAe,MAAA,CAAO,kBAAkB,aAAa,CAAA","file":"index.js","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","/** All localizable strings used by SatMouse Web Components. */\nexport interface SatMouseLocale {\n // satmouse-status\n connected: string;\n connecting: string;\n disconnected: string;\n notRunning: string;\n extensionRequired: string;\n launchSatMouse: string;\n downloadSatMouse: string;\n enableExtension: string;\n\n // satmouse-devices\n noDevices: string;\n flip: string;\n translateScale: string;\n rotateScale: string;\n wScale: string;\n buttonMappings: string;\n remapKey: string;\n pressAKey: string;\n remove: string;\n addButtonMapping: string;\n pressDeviceButton: string;\n restoreDefaults: string;\n\n // satmouse-debug\n fps: string;\n}\n\n/** Default English strings. Exported so implementors can iterate keys for translation tooling. */\nexport const DEFAULT_LOCALE: Readonly<SatMouseLocale> = {\n // satmouse-status\n connected: \"Connected\",\n connecting: \"Connecting...\",\n disconnected: \"Disconnected\",\n notRunning: \"Not running\",\n extensionRequired: \"Extension required\",\n launchSatMouse: \"Launch SatMouse\",\n downloadSatMouse: \"Download SatMouse\",\n enableExtension: \"Enable Extension\",\n\n // satmouse-devices\n noDevices: \"No devices\",\n flip: \"Flip\",\n translateScale: \"Trans\",\n rotateScale: \"Rot\",\n wScale: \"W\",\n buttonMappings: \"Button Mappings\",\n remapKey: \"Remap key\",\n pressAKey: \"Press a key...\",\n remove: \"Remove\",\n addButtonMapping: \"+ Add Button Mapping\",\n pressDeviceButton: \"Press a device button...\",\n restoreDefaults: \"Restore Defaults\",\n\n // satmouse-debug\n fps: \"fps\",\n};\n\nlet current: SatMouseLocale = { ...DEFAULT_LOCALE };\n\n/** Override some or all UI strings. Partial updates merge with the current locale. */\nexport function setLocale(overrides: Partial<SatMouseLocale>): void {\n current = { ...current, ...overrides };\n}\n\n/** Get the current locale strings. */\nexport function getLocale(): Readonly<SatMouseLocale> {\n return current;\n}\n\n/** Read a single string by key. Used internally by components. */\nexport function t(key: keyof SatMouseLocale): string {\n return current[key];\n}\n","import { onManager } from \"./registry.js\";\nimport { t } from \"./locale.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\n</style>\n<span class=\"dot\"></span>\n<span class=\"text\"></span>\n<span class=\"protocol\"></span>\n<button class=\"launch\"></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 this.text.textContent = t(\"disconnected\");\n this.launch.textContent = t(\"launchSatMouse\");\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 = t(\"launchSatMouse\");\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.showDownload = false;\n this.text.textContent = t(\"connected\");\n this.launch.style.display = \"none\";\n } else if (state === \"connecting\") {\n this.text.textContent = t(\"connecting\");\n this.launch.style.display = \"none\";\n } else if (state === \"failed\") {\n // Detect Safari without extension — suggest enabling it\n const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n const hasExtension = !!(globalThis as any).__satmouseExtensionAvailable;\n if (isSafari && !hasExtension) {\n this.text.textContent = t(\"extensionRequired\");\n this.launch.style.display = \"inline-block\";\n this.launch.disabled = false;\n this.launch.textContent = t(\"enableExtension\");\n this.showDownload = false;\n this.needsExtension = true;\n } else {\n this.text.textContent = t(\"notRunning\");\n this.launch.style.display = \"inline-block\";\n this.launch.disabled = false;\n this.launch.textContent = this.showDownload ? t(\"downloadSatMouse\") : t(\"launchSatMouse\");\n this.needsExtension = false;\n }\n } else {\n this.text.textContent = t(\"disconnected\");\n this.launch.style.display = \"none\";\n }\n }\n\n private showDownload = false;\n private needsExtension = false;\n\n private startLaunchFlow(): void {\n if (this.needsExtension) {\n // Open Safari extension preferences via the bridge's URL scheme\n window.location.href = \"satmouse://enable-extension\";\n // Retry connection after user enables the extension\n this.launch.textContent = t(\"connecting\");\n this.launch.disabled = true;\n this.stopPoll();\n this.pollTimer = setInterval(() => {\n if (this.manager?.state === \"connected\") { this.stopPoll(); return; }\n this.manager?.retry();\n }, 2000);\n // Give up after 30s\n setTimeout(() => { this.stopPoll(); this.launch.disabled = false; this.launch.textContent = t(\"enableExtension\"); }, 30000);\n return;\n }\n\n if (this.showDownload) {\n window.location.href = \"https://github.com/kelnishi/SatMouse/releases/latest\";\n return;\n }\n\n this.launch.textContent = t(\"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 this.showDownload = false;\n return;\n }\n if (attempts >= 5) {\n this.stopPoll();\n this.showDownload = true;\n this.launch.disabled = false;\n this.launch.textContent = t(\"downloadSatMouse\");\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 { t } from \"./locale.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 type { ButtonRoute } from \"../utils/config.js\";\nimport type { ButtonEvent } from \"../core/types.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 .btn-section { display: flex; flex-direction: column; gap: 4px; }\n .btn-section-label { color: #7f8c8d; font-weight: 600; font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; }\n .btn-route { display: flex; gap: 6px; align-items: center; font-size: 11px; }\n .btn-route .btn-idx { color: #7f8c8d; font-family: monospace; min-width: 32px; }\n .btn-route .btn-arrow { color: #7f8c8d; }\n .btn-route .btn-key { color: #3498db; font-family: monospace; }\n .btn-route .btn-remove { cursor: pointer; color: #e74c3c; background: none; border: none;\n font-size: 11px; padding: 0 2px; font-family: inherit; }\n .btn-route .btn-remove:hover { color: #ff6b6b; }\n .btn-add { background: none; border: 1px dashed #1a4a8a; border-radius: 3px; color: #7f8c8d;\n font-size: 11px; padding: 4px 8px; cursor: pointer; font-family: inherit; }\n .btn-add:hover { color: #e0e0e0; border-color: #3498db; }\n .btn-add.listening { color: #f39c12; border-color: #f39c12; border-style: solid; cursor: default; }\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\">${t(\"noDevices\")}</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, 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 = t(\"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 sliders\n for (const [label, key, globalKey] of [\n [t(\"translateScale\"), \"translateScale\", \"translateScale\"],\n [t(\"rotateScale\"), \"rotateScale\", \"rotateScale\"],\n [t(\"wScale\"), \"wScale\", \"wScale\"],\n ] as const) {\n const row = document.createElement(\"div\");\n row.className = \"slider-row\";\n const val = (cfg as any)[key] ?? (mgr.config as any)[globalKey];\n row.innerHTML = `<label>${label}</label>` +\n `<input type=\"range\" min=\"0\" max=\"100\" value=\"${Math.round(unmapSlider(val))}\">` +\n `<span>${val.toFixed(4)}</span>`;\n const sl = row.querySelector(\"input\")! as HTMLInputElement;\n const sp = row.querySelector(\"span\")!;\n sl.addEventListener(\"input\", () => {\n const v = mapSlider(+sl.value);\n sp.textContent = v.toFixed(4);\n mgr.updateDeviceConfig(device.id, { [key]: v });\n });\n controls.appendChild(row);\n }\n\n // Button mappings\n const btnSection = document.createElement(\"div\");\n btnSection.className = \"btn-section\";\n const btnLabel = document.createElement(\"div\");\n btnLabel.className = \"btn-section-label\";\n btnLabel.textContent = t(\"buttonMappings\");\n btnSection.appendChild(btnLabel);\n\n const buttonRoutes: ButtonRoute[] = cfg.buttonRoutes ?? [];\n const labels = device.buttonLabels ?? [];\n for (let i = 0; i < buttonRoutes.length; i++) {\n const route = buttonRoutes[i];\n const btnName = labels[route.button] ?? `Btn ${route.button}`;\n const row = document.createElement(\"div\");\n row.className = \"btn-route\";\n\n const idxSpan = document.createElement(\"span\");\n idxSpan.className = \"btn-idx\";\n idxSpan.textContent = btnName;\n row.appendChild(idxSpan);\n\n const arrow = document.createElement(\"span\");\n arrow.className = \"btn-arrow\";\n arrow.textContent = \"\\u2192\";\n row.appendChild(arrow);\n\n const keySpan = document.createElement(\"span\");\n keySpan.className = \"btn-key\";\n keySpan.textContent = route.key;\n row.appendChild(keySpan);\n\n // Edit — re-listen for a new key\n const editBtn = document.createElement(\"button\");\n editBtn.className = \"btn-remove\";\n editBtn.textContent = \"\\u270E\";\n editBtn.title = t(\"remapKey\");\n const routeIdx = i;\n editBtn.addEventListener(\"click\", () => {\n keySpan.textContent = t(\"pressAKey\");\n keySpan.style.color = \"#f39c12\";\n const onKey = (e: KeyboardEvent) => {\n e.preventDefault();\n e.stopPropagation();\n document.removeEventListener(\"keydown\", onKey, true);\n const current = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];\n const updated = current.map((r: ButtonRoute, j: number) =>\n j === routeIdx ? { ...r, key: e.key, code: e.code } : r\n );\n mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });\n this.refreshControls(panel, device);\n };\n document.addEventListener(\"keydown\", onKey, true);\n });\n row.appendChild(editBtn);\n\n // Delete\n const removeBtn = document.createElement(\"button\");\n removeBtn.className = \"btn-remove\";\n removeBtn.textContent = \"\\u00d7\";\n removeBtn.title = t(\"remove\");\n removeBtn.addEventListener(\"click\", () => {\n const current = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];\n const updated = current.filter((_: ButtonRoute, j: number) => j !== routeIdx);\n mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });\n this.refreshControls(panel, device);\n });\n row.appendChild(removeBtn);\n btnSection.appendChild(row);\n }\n\n // Add mapping button with listen flow\n const addBtn = document.createElement(\"button\");\n addBtn.className = \"btn-add\";\n addBtn.textContent = t(\"addButtonMapping\");\n addBtn.addEventListener(\"click\", () => {\n if (addBtn.classList.contains(\"listening\")) return;\n this.startButtonListen(addBtn, mgr, device, panel);\n });\n btnSection.appendChild(addBtn);\n controls.appendChild(btnSection);\n\n // Reset button\n const resetBtn = document.createElement(\"button\");\n resetBtn.className = \"reset-btn\";\n resetBtn.textContent = t(\"restoreDefaults\");\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(device: DeviceInfo, deviceAxes: string[]): AxisRoute[] {\n const mgr = this.manager!;\n\n // 1. Exact device ID\n const devCfg = mgr.config.devices[device.id];\n if (devCfg?.routes && Array.isArray(devCfg.routes)) return devCfg.routes;\n\n // 2. Pattern match\n for (const [pattern, cfg] of Object.entries(mgr.config.devices)) {\n if (pattern.endsWith(\"*\") && device.id.startsWith(pattern.slice(0, -1))) {\n if (cfg.routes && Array.isArray(cfg.routes)) return cfg.routes;\n }\n }\n\n // 3. Device class defaults\n if (device.deviceClass && mgr.config.deviceClasses) {\n const classCfg = mgr.config.deviceClasses[device.deviceClass];\n if (classCfg?.routes && Array.isArray(classCfg.routes)) return classCfg.routes;\n }\n\n // 4. Build from device axes metadata\n return buildRoutes(deviceAxes);\n }\n\n private updateRoute(deviceId: string, index: number, deviceAxes: string[], patch: Partial<AxisRoute>): void {\n const device = Array.from(this.manager!.getDevicesWithConfig()).find(d => d.device.id === deviceId)?.device;\n const base = this.getRoutes(device ?? { id: deviceId } as DeviceInfo, deviceAxes);\n const updated = base.map((r, j) => j === index ? { ...r, ...patch } : { ...r });\n this.manager!.updateDeviceConfig(deviceId, { routes: updated });\n }\n\n private startButtonListen(\n btn: HTMLButtonElement,\n mgr: InputManager,\n device: DeviceInfo,\n panel: HTMLDetailsElement,\n ): void {\n btn.classList.add(\"listening\");\n btn.textContent = t(\"pressDeviceButton\");\n\n // Step 1: Listen for device button\n const onButton = (event: ButtonEvent) => {\n if (!event.pressed) return; // only on press, not release\n mgr.off(\"buttonEvent\", onButton);\n\n const capturedButton = event.button;\n btn.textContent = `Btn ${capturedButton} \\u2192 ${t(\"pressAKey\")}`;\n\n // Step 2: Listen for keyboard key\n const onKey = (e: KeyboardEvent) => {\n e.preventDefault();\n e.stopPropagation();\n document.removeEventListener(\"keydown\", onKey, true);\n\n const route: ButtonRoute = {\n button: capturedButton,\n key: e.key,\n code: e.code,\n };\n\n const current = mgr.getDeviceConfig(device.id).buttonRoutes ?? [];\n // Replace existing mapping for the same button, or add new\n const updated = current.filter((r: ButtonRoute) => r.button !== capturedButton);\n updated.push(route);\n mgr.updateDeviceConfig(device.id, { buttonRoutes: updated });\n this.refreshControls(panel, device);\n };\n document.addEventListener(\"keydown\", onKey, true);\n };\n mgr.on(\"buttonEvent\", onButton);\n\n // Cancel on Escape (before a button is pressed)\n const onCancel = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n mgr.off(\"buttonEvent\", onButton);\n document.removeEventListener(\"keydown\", onCancel, true);\n btn.classList.remove(\"listening\");\n btn.textContent = t(\"addButtonMapping\");\n }\n };\n document.addEventListener(\"keydown\", onCancel, true);\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\">${t(\"noDevices\")}</span>`;\n }\n }\n}\n\ncustomElements.define(\"satmouse-devices\", SatMouseDevices);\n","import { onManager } from \"./registry.js\";\nimport { t } from \"./locale.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\"></span> · <span class=\"protocol\"></span> · <span class=\"fps\">0</span> <span class=\"fps-label\"></span></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 this.els.state.textContent = t(\"disconnected\");\n shadow.querySelector(\".fps-label\")!.textContent = t(\"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"]}
|