@kelnishi/satmouse-client 0.9.14 → 0.10.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/chunk-JTG5GEIB.cjs +65 -0
- package/dist/chunk-JTG5GEIB.cjs.map +1 -0
- package/dist/chunk-RNM322RZ.js +60 -0
- package/dist/chunk-RNM322RZ.js.map +1 -0
- package/dist/{connection-5KQFvHoJ.d.cts → connection-DQxI5qib.d.cts} +6 -0
- package/dist/{connection-5KQFvHoJ.d.ts → connection-DQxI5qib.d.ts} +6 -0
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/elements/index.cjs +84 -67
- package/dist/elements/index.cjs.map +1 -1
- package/dist/elements/index.d.cts +4 -1
- package/dist/elements/index.d.ts +4 -1
- package/dist/elements/index.js +84 -67
- package/dist/elements/index.js.map +1 -1
- package/dist/react/index.cjs +130 -236
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +35 -95
- package/dist/react/index.d.ts +35 -95
- package/dist/react/index.js +130 -236
- package/dist/react/index.js.map +1 -1
- package/dist/utils/index.cjs +102 -173
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +42 -115
- package/dist/utils/index.d.ts +42 -115
- package/dist/utils/index.js +96 -161
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-I47ZOX3M.js +0 -64
- package/dist/chunk-I47ZOX3M.js.map +0 -1
- package/dist/chunk-LDSDVYCV.cjs +0 -69
- package/dist/chunk-LDSDVYCV.cjs.map +0 -1
package/dist/elements/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FULL_AXES, buildRoutes } from '../chunk-RNM322RZ.js';
|
|
2
2
|
|
|
3
3
|
// src/elements/registry.ts
|
|
4
4
|
var globalManager = null;
|
|
@@ -92,7 +92,6 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
92
92
|
customElements.define("satmouse-status", SatMouseStatus);
|
|
93
93
|
|
|
94
94
|
// src/elements/satmouse-devices.ts
|
|
95
|
-
var AXES = ["tx", "ty", "tz", "rx", "ry", "rz"];
|
|
96
95
|
var STYLES = `
|
|
97
96
|
<style>
|
|
98
97
|
:host { display: block; font-family: inherit; font-size: 12px; }
|
|
@@ -104,16 +103,16 @@ var STYLES = `
|
|
|
104
103
|
.slider-row label { color: #7f8c8d; font-weight: 600; width: 38px; flex-shrink: 0; }
|
|
105
104
|
.slider-row input[type="range"] { flex: 1; min-width: 0; height: 4px; accent-color: #3498db; }
|
|
106
105
|
.slider-row span { color: #7f8c8d; font-family: monospace; font-size: 10px; min-width: 44px; text-align: right; }
|
|
107
|
-
.
|
|
108
|
-
.
|
|
109
|
-
.
|
|
110
|
-
.
|
|
111
|
-
|
|
112
|
-
.
|
|
113
|
-
.remap-row label { color: #7f8c8d; width: 24px; flex-shrink: 0; }
|
|
114
|
-
.remap-row select { background: #16213e; color: #e0e0e0; border: 1px solid #1a4a8a; border-radius: 3px;
|
|
115
|
-
font-size: 11px; padding: 1px 4px; flex: 1; min-width: 0; }
|
|
106
|
+
.route-group { display: flex; flex-wrap: wrap; gap: 4px 12px; }
|
|
107
|
+
.route-row { display: flex; gap: 4px; align-items: center; }
|
|
108
|
+
.route-row label { color: #7f8c8d; white-space: nowrap; }
|
|
109
|
+
.route-row select { background: #16213e; color: #e0e0e0; border: 1px solid #1a4a8a; border-radius: 3px;
|
|
110
|
+
font-size: 11px; padding: 1px 4px; }
|
|
111
|
+
.route-row input[type="checkbox"] { accent-color: #e74c3c; margin: 0; }
|
|
116
112
|
.empty { color: #7f8c8d; font-style: italic; }
|
|
113
|
+
.reset-btn { background: none; border: 1px solid #1a4a8a; border-radius: 3px; color: #7f8c8d;
|
|
114
|
+
font-size: 11px; padding: 3px 8px; cursor: pointer; margin-top: 4px; }
|
|
115
|
+
.reset-btn:hover { color: #e0e0e0; border-color: #e74c3c; }
|
|
117
116
|
</style>
|
|
118
117
|
`;
|
|
119
118
|
function mapSlider(v) {
|
|
@@ -146,11 +145,13 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
146
145
|
});
|
|
147
146
|
}
|
|
148
147
|
addDevice(device) {
|
|
149
|
-
|
|
148
|
+
const existing = this.shadowRoot.getElementById(`dev-${device.id}`);
|
|
149
|
+
if (existing) {
|
|
150
|
+
this.refreshControls(existing, device);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
150
153
|
const empty = this.container.querySelector(".empty");
|
|
151
154
|
if (empty) empty.remove();
|
|
152
|
-
const mgr = this.manager;
|
|
153
|
-
const cfg = mgr.getDeviceConfig(device.id);
|
|
154
155
|
const panel = document.createElement("details");
|
|
155
156
|
panel.className = "panel";
|
|
156
157
|
panel.id = `dev-${device.id}`;
|
|
@@ -158,72 +159,88 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
158
159
|
const summary = document.createElement("summary");
|
|
159
160
|
summary.innerHTML = `${device.model ?? device.name}<span class="type">${device.connectionType ?? ""}</span>`;
|
|
160
161
|
panel.appendChild(summary);
|
|
162
|
+
this.refreshControls(panel, device);
|
|
163
|
+
this.container.appendChild(panel);
|
|
164
|
+
}
|
|
165
|
+
refreshControls(panel, device) {
|
|
166
|
+
const old = panel.querySelector(".controls");
|
|
167
|
+
if (old) old.remove();
|
|
168
|
+
const mgr = this.manager;
|
|
169
|
+
const cfg = mgr.getDeviceConfig(device.id);
|
|
161
170
|
const controls = document.createElement("div");
|
|
162
171
|
controls.className = "controls";
|
|
163
|
-
|
|
172
|
+
const routeGroup = document.createElement("div");
|
|
173
|
+
routeGroup.className = "route-group";
|
|
174
|
+
const deviceAxes = device.axes ?? ["tx", "ty", "tz", "rx", "ry", "rz"];
|
|
175
|
+
const routes = this.getRoutes(device.id, deviceAxes);
|
|
176
|
+
for (let i = 0; i < deviceAxes.length; i++) {
|
|
177
|
+
const route = routes[i] ?? { source: deviceAxes[i], target: deviceAxes[i].replace(/[+-]$/, "") };
|
|
164
178
|
const row = document.createElement("div");
|
|
165
|
-
row.className = "
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
mgr.updateDeviceConfig(device.id, {
|
|
174
|
-
sensitivity: { ...mgr.getDeviceConfig(device.id).sensitivity, [type]: v }
|
|
175
|
-
});
|
|
179
|
+
row.className = "route-row";
|
|
180
|
+
const cb = document.createElement("input");
|
|
181
|
+
cb.type = "checkbox";
|
|
182
|
+
cb.checked = route.flip ?? false;
|
|
183
|
+
cb.title = "Flip";
|
|
184
|
+
const routeIndex = i;
|
|
185
|
+
cb.addEventListener("change", () => {
|
|
186
|
+
this.updateRoute(device.id, routeIndex, deviceAxes, { flip: cb.checked });
|
|
176
187
|
});
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
for (const group of [["tx", "ty", "tz"], ["rx", "ry", "rz"]]) {
|
|
182
|
-
const row = document.createElement("div");
|
|
183
|
-
row.className = "flip-row";
|
|
184
|
-
for (const axis of group) {
|
|
185
|
-
const label = document.createElement("label");
|
|
186
|
-
const cb = document.createElement("input");
|
|
187
|
-
cb.type = "checkbox";
|
|
188
|
-
cb.checked = cfg.flip?.[axis] ?? mgr.config.flip[axis];
|
|
189
|
-
cb.addEventListener("change", () => {
|
|
190
|
-
mgr.updateDeviceConfig(device.id, {
|
|
191
|
-
flip: { ...mgr.getDeviceConfig(device.id).flip, [axis]: cb.checked }
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
label.appendChild(cb);
|
|
195
|
-
label.appendChild(document.createTextNode(axis.toUpperCase()));
|
|
196
|
-
row.appendChild(label);
|
|
197
|
-
}
|
|
198
|
-
flipGroup.appendChild(row);
|
|
199
|
-
}
|
|
200
|
-
controls.appendChild(flipGroup);
|
|
201
|
-
const remapGroup = document.createElement("div");
|
|
202
|
-
remapGroup.className = "remap-group";
|
|
203
|
-
const actionMap = cfg.actionMap ?? mgr.config.actionMap;
|
|
204
|
-
for (const action of AXES) {
|
|
205
|
-
const row = document.createElement("div");
|
|
206
|
-
row.className = "remap-row";
|
|
207
|
-
row.innerHTML = `<label>${action.toUpperCase()}</label>`;
|
|
188
|
+
row.appendChild(cb);
|
|
189
|
+
const label = document.createElement("label");
|
|
190
|
+
label.textContent = device.axisLabels?.[i] ?? deviceAxes[i].toUpperCase();
|
|
191
|
+
row.appendChild(label);
|
|
208
192
|
const sel = document.createElement("select");
|
|
209
|
-
for (const
|
|
193
|
+
for (const target of FULL_AXES) {
|
|
210
194
|
const opt = document.createElement("option");
|
|
211
|
-
opt.value =
|
|
212
|
-
opt.textContent =
|
|
213
|
-
if (
|
|
195
|
+
opt.value = target;
|
|
196
|
+
opt.textContent = target.toUpperCase();
|
|
197
|
+
if (target === route.target) opt.selected = true;
|
|
214
198
|
sel.appendChild(opt);
|
|
215
199
|
}
|
|
216
200
|
sel.addEventListener("change", () => {
|
|
217
|
-
|
|
218
|
-
current[action] = { ...current[action], source: sel.value };
|
|
219
|
-
mgr.updateDeviceConfig(device.id, { actionMap: current });
|
|
201
|
+
this.updateRoute(device.id, routeIndex, deviceAxes, { target: sel.value });
|
|
220
202
|
});
|
|
221
203
|
row.appendChild(sel);
|
|
222
|
-
|
|
204
|
+
routeGroup.appendChild(row);
|
|
223
205
|
}
|
|
224
|
-
controls.appendChild(
|
|
206
|
+
controls.appendChild(routeGroup);
|
|
207
|
+
const sensRow = document.createElement("div");
|
|
208
|
+
sensRow.className = "slider-row";
|
|
209
|
+
const currentScale = cfg.scale ?? mgr.config.scale;
|
|
210
|
+
sensRow.innerHTML = `<label>Scale</label><input type="range" min="0" max="100" value="${Math.round(unmapSlider(currentScale))}"><span>${currentScale.toFixed(4)}</span>`;
|
|
211
|
+
const slider = sensRow.querySelector("input");
|
|
212
|
+
const span = sensRow.querySelector("span");
|
|
213
|
+
slider.addEventListener("input", () => {
|
|
214
|
+
const v = mapSlider(+slider.value);
|
|
215
|
+
span.textContent = v.toFixed(4);
|
|
216
|
+
mgr.updateDeviceConfig(device.id, { scale: v });
|
|
217
|
+
});
|
|
218
|
+
controls.appendChild(sensRow);
|
|
219
|
+
const resetBtn = document.createElement("button");
|
|
220
|
+
resetBtn.className = "reset-btn";
|
|
221
|
+
resetBtn.textContent = "Restore Defaults";
|
|
222
|
+
resetBtn.addEventListener("click", () => {
|
|
223
|
+
mgr.resetDeviceConfig(device.id);
|
|
224
|
+
this.refreshControls(panel, device);
|
|
225
|
+
});
|
|
226
|
+
controls.appendChild(resetBtn);
|
|
225
227
|
panel.appendChild(controls);
|
|
226
|
-
|
|
228
|
+
}
|
|
229
|
+
getRoutes(deviceId, deviceAxes) {
|
|
230
|
+
const mgr = this.manager;
|
|
231
|
+
const devCfg = mgr.config.devices[deviceId];
|
|
232
|
+
if (devCfg?.routes && Array.isArray(devCfg.routes)) return devCfg.routes;
|
|
233
|
+
for (const [pattern, cfg] of Object.entries(mgr.config.devices)) {
|
|
234
|
+
if (pattern.endsWith("*") && deviceId.startsWith(pattern.slice(0, -1))) {
|
|
235
|
+
if (cfg.routes && Array.isArray(cfg.routes)) return cfg.routes;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return buildRoutes(deviceAxes);
|
|
239
|
+
}
|
|
240
|
+
updateRoute(deviceId, index, deviceAxes, patch) {
|
|
241
|
+
const base = this.getRoutes(deviceId, deviceAxes);
|
|
242
|
+
const updated = base.map((r, j) => j === index ? { ...r, ...patch } : { ...r });
|
|
243
|
+
this.manager.updateDeviceConfig(deviceId, { routes: updated });
|
|
227
244
|
}
|
|
228
245
|
removeDevice(device) {
|
|
229
246
|
this.shadowRoot.getElementById(`dev-${device.id}`)?.remove();
|
|
@@ -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":";;;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;AAEO,SAAS,eAAe,EAAA,EAAqC;AAClE,EAAA,IAAI,aAAA,KAAkB,aAAa,CAAA;AAAA,OAC9B,SAAA,CAAU,IAAI,EAAE,CAAA;AACvB;;;ACvBA,IAAM,QAAA,GAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAkBV,IAAM,cAAA,GAAN,cAA6B,WAAA,CAAY;AAAA,EACtC,GAAA;AAAA,EACA,IAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA,EACA,eAAA,GAAwD,IAAA;AAAA,EAEhE,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;AAE5C,IAAA,IAAA,CAAK,MAAA,CAAO,gBAAA,CAAiB,OAAA,EAAS,MAAM;AAE1C,MAAA,MAAA,CAAO,SAAS,IAAA,GAAO,mBAAA;AAEvB,MAAA,UAAA,CAAW,MAAM;AACf,QAAA,IAAI,CAAC,SAAS,MAAA,EAAQ;AACpB,UAAA,IAAI,OAAA,CAAQ,mEAAmE,CAAA,EAAG;AAChF,YAAA,MAAA,CAAO,IAAA,CAAK,sDAAA,EAAwD,QAAA,EAAU,UAAU,CAAA;AAAA,UAC1F;AAAA,QACF;AAAA,MACF,GAAG,GAAI,CAAA;AAAA,IACT,CAAC,CAAA;AAAA,EACH;AAAA,EAEA,iBAAA,GAAoB;AAElB,IAAA,IAAA,CAAK,eAAA,GAAkB,WAAW,MAAM;AAAE,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,OAAA,GAAU,cAAA;AAAA,IAAgB,GAAG,GAAI,CAAA;AAC7F,IAAA,cAAA,CAAe,CAAC,OAAA,KAAY,IAAA,CAAK,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,EAChD;AAAA,EAEQ,KAAK,OAAA,EAA6B;AACxC,IAAA,OAAA,CAAQ,EAAA,CAAG,aAAA,EAAe,CAAC,KAAA,EAAwB,QAAA,KAAgC;AACjF,MAAA,IAAA,CAAK,GAAA,CAAI,QAAQ,KAAA,GAAQ,KAAA;AACzB,MAAA,IAAA,CAAK,KAAA,CAAM,WAAA,GAAc,QAAA,KAAa,MAAA,GAAS,QAAA,GAAW,EAAA;AAE1D,MAAA,IAAI,KAAK,eAAA,EAAiB;AAAE,QAAA,YAAA,CAAa,KAAK,eAAe,CAAA;AAAG,QAAA,IAAA,CAAK,eAAA,GAAkB,IAAA;AAAA,MAAM;AAE7F,MAAA,IAAI,UAAU,WAAA,EAAa;AACzB,QAAA,IAAA,CAAK,KAAK,WAAA,GAAc,WAAA;AACxB,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,OAAA,GAAU,MAAA;AAAA,MAC9B,CAAA,MAAA,IAAW,UAAU,YAAA,EAAc;AACjC,QAAA,IAAA,CAAK,KAAK,WAAA,GAAc,eAAA;AACxB,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,OAAA,GAAU,MAAA;AAAA,MAC9B,CAAA,MAAA,IAAW,UAAU,QAAA,EAAU;AAC7B,QAAA,IAAA,CAAK,KAAK,WAAA,GAAc,aAAA;AACxB,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,OAAA,GAAU,cAAA;AAAA,MAC9B,CAAA,MAAO;AACL,QAAA,IAAA,CAAK,KAAK,WAAA,GAAc,cAAA;AACxB,QAAA,IAAA,CAAK,MAAA,CAAO,MAAM,OAAA,GAAU,MAAA;AAAA,MAC9B;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AACF;AAEA,cAAA,CAAe,MAAA,CAAO,mBAAmB,cAAc,CAAA;;;AC5EvD,IAAM,OAAoB,CAAC,IAAA,EAAM,MAAM,IAAA,EAAM,IAAA,EAAM,MAAM,IAAI,CAAA;AAE7D,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,CAAA;AAwBf,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,EAEA,iBAAA,GAAoB;AAClB,IAAA,cAAA,CAAe,CAAC,OAAA,KAAY;AAC1B,MAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,MAAA,OAAA,CAAQ,EAAA,CAAG,cAAA,EAAgB,CAAC,KAAA,EAAO,MAAA,KAAW;AAC5C,QAAA,IAAI,KAAA,KAAU,WAAA,EAAa,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA;AAAA,aAC3C,IAAA,CAAK,aAAa,MAAM,CAAA;AAAA,MAC/B,CAAC,CAAA;AACD,MAAA,OAAA,CAAQ,EAAA,CAAG,aAAA,EAAe,CAAC,KAAA,KAAU;AACnC,QAAA,IAAI,UAAU,WAAA,EAAa;AACzB,UAAA,OAAA,CAAQ,eAAA,EAAgB,CAAE,IAAA,CAAK,CAAC,OAAA,KAAY,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAA,KAAM,IAAA,CAAK,SAAA,CAAU,CAAC,CAAC,CAAC,CAAA;AAAA,QACvF;AAAA,MACF,CAAC,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACH;AAAA,EAEQ,UAAU,MAAA,EAA0B;AAC1C,IAAA,IAAI,KAAK,UAAA,CAAY,cAAA,CAAe,OAAO,MAAA,CAAO,EAAE,EAAE,CAAA,EAAG;AACzD,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,SAAA,CAAU,aAAA,CAAc,QAAQ,CAAA;AACnD,IAAA,IAAI,KAAA,QAAa,MAAA,EAAO;AAExB,IAAA,MAAM,MAAM,IAAA,CAAK,OAAA;AACjB,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,MAAA,CAAO,EAAE,CAAA;AAEzC,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,MAAM,QAAA,GAAW,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC7C,IAAA,QAAA,CAAS,SAAA,GAAY,UAAA;AAGrB,IAAA,KAAA,MAAW,IAAA,IAAQ,CAAC,aAAA,EAAe,UAAU,CAAA,EAAY;AACvD,MAAA,MAAM,GAAA,GAAM,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AACxC,MAAA,GAAA,CAAI,SAAA,GAAY,YAAA;AAChB,MAAA,MAAM,GAAA,GAAM,IAAI,WAAA,GAAc,IAAI,KAAK,GAAA,CAAI,MAAA,CAAO,YAAY,IAAI,CAAA;AAClE,MAAA,GAAA,CAAI,YAAY,CAAA,OAAA,EAAU,IAAA,KAAS,aAAA,GAAgB,OAAA,GAAU,KAAK,CAAA,qDAAA,EAChB,IAAA,CAAK,KAAA,CAAM,WAAA,CAAY,GAAG,CAAC,CAAC,WACnE,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,OAAA,CAAA;AACzB,MAAA,MAAM,MAAA,GAAS,GAAA,CAAI,aAAA,CAAc,OAAO,CAAA;AACxC,MAAA,MAAM,IAAA,GAAO,GAAA,CAAI,aAAA,CAAc,MAAM,CAAA;AACrC,MAAA,MAAA,CAAO,gBAAA,CAAiB,SAAS,MAAM;AACrC,QAAA,MAAM,CAAA,GAAI,SAAA,CAAU,CAAC,MAAA,CAAO,KAAK,CAAA;AACjC,QAAA,IAAA,CAAK,WAAA,GAAc,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAC9B,QAAA,GAAA,CAAI,kBAAA,CAAmB,OAAO,EAAA,EAAI;AAAA,UAChC,WAAA,EAAa,EAAE,GAAG,GAAA,CAAI,eAAA,CAAgB,MAAA,CAAO,EAAE,CAAA,CAAE,WAAA,EAAa,CAAC,IAAI,GAAG,CAAA;AAAE,SACzE,CAAA;AAAA,MACH,CAAC,CAAA;AACD,MAAA,QAAA,CAAS,YAAY,GAAG,CAAA;AAAA,IAC1B;AAGA,IAAA,MAAM,SAAA,GAAY,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC9C,IAAA,SAAA,CAAU,SAAA,GAAY,YAAA;AACtB,IAAA,KAAA,MAAW,KAAA,IAAS,CAAC,CAAC,IAAA,EAAM,IAAA,EAAM,IAAI,CAAA,EAAG,CAAC,IAAA,EAAM,IAAA,EAAM,IAAI,CAAC,CAAA,EAAoB;AAC7E,MAAA,MAAM,GAAA,GAAM,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AACxC,MAAA,GAAA,CAAI,SAAA,GAAY,UAAA;AAChB,MAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,QAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA;AAC5C,QAAA,MAAM,EAAA,GAAK,QAAA,CAAS,aAAA,CAAc,OAAO,CAAA;AACzC,QAAA,EAAA,CAAG,IAAA,GAAO,UAAA;AACV,QAAA,EAAA,CAAG,OAAA,GAAU,IAAI,IAAA,GAAO,IAAI,KAAK,GAAA,CAAI,MAAA,CAAO,KAAK,IAAI,CAAA;AACrD,QAAA,EAAA,CAAG,gBAAA,CAAiB,UAAU,MAAM;AAClC,UAAA,GAAA,CAAI,kBAAA,CAAmB,OAAO,EAAA,EAAI;AAAA,YAChC,IAAA,EAAM,EAAE,GAAG,GAAA,CAAI,eAAA,CAAgB,MAAA,CAAO,EAAE,CAAA,CAAE,IAAA,EAAM,CAAC,IAAI,GAAG,GAAG,OAAA;AAAQ,WACpE,CAAA;AAAA,QACH,CAAC,CAAA;AACD,QAAA,KAAA,CAAM,YAAY,EAAE,CAAA;AACpB,QAAA,KAAA,CAAM,YAAY,QAAA,CAAS,cAAA,CAAe,IAAA,CAAK,WAAA,EAAa,CAAC,CAAA;AAC7D,QAAA,GAAA,CAAI,YAAY,KAAK,CAAA;AAAA,MACvB;AACA,MAAA,SAAA,CAAU,YAAY,GAAG,CAAA;AAAA,IAC3B;AACA,IAAA,QAAA,CAAS,YAAY,SAAS,CAAA;AAG9B,IAAA,MAAM,UAAA,GAAa,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC/C,IAAA,UAAA,CAAW,SAAA,GAAY,aAAA;AACvB,IAAA,MAAM,SAAA,GAAY,GAAA,CAAI,SAAA,IAAa,GAAA,CAAI,MAAA,CAAO,SAAA;AAC9C,IAAA,KAAA,MAAW,UAAU,IAAA,EAAM;AACzB,MAAA,MAAM,GAAA,GAAM,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AACxC,MAAA,GAAA,CAAI,SAAA,GAAY,WAAA;AAChB,MAAA,GAAA,CAAI,SAAA,GAAY,CAAA,OAAA,EAAU,MAAA,CAAO,WAAA,EAAa,CAAA,QAAA,CAAA;AAC9C,MAAA,MAAM,GAAA,GAAM,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC3C,MAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,QAAA,MAAM,GAAA,GAAM,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AAC3C,QAAA,GAAA,CAAI,KAAA,GAAQ,GAAA;AACZ,QAAA,GAAA,CAAI,WAAA,GAAc,IAAI,WAAA,EAAY;AAClC,QAAA,IAAI,UAAU,MAAM,CAAA,EAAG,MAAA,KAAW,GAAA,MAAS,QAAA,GAAW,IAAA;AACtD,QAAA,GAAA,CAAI,YAAY,GAAG,CAAA;AAAA,MACrB;AACA,MAAA,GAAA,CAAI,gBAAA,CAAiB,UAAU,MAAM;AACnC,QAAA,MAAM,OAAA,GAAU,IAAI,eAAA,CAAgB,MAAA,CAAO,EAAE,CAAA,CAAE,SAAA,IAAa,EAAE,GAAG,kBAAA,EAAmB;AACpF,QAAA,OAAA,CAAQ,MAAM,IAAI,EAAE,GAAG,QAAQ,MAAM,CAAA,EAAG,MAAA,EAAQ,GAAA,CAAI,KAAA,EAAmB;AACvE,QAAA,GAAA,CAAI,mBAAmB,MAAA,CAAO,EAAA,EAAI,EAAE,SAAA,EAAW,SAAS,CAAA;AAAA,MAC1D,CAAC,CAAA;AACD,MAAA,GAAA,CAAI,YAAY,GAAG,CAAA;AACnB,MAAA,UAAA,CAAW,YAAY,GAAG,CAAA;AAAA,IAC5B;AACA,IAAA,QAAA,CAAS,YAAY,UAAU,CAAA;AAE/B,IAAA,KAAA,CAAM,YAAY,QAAQ,CAAA;AAC1B,IAAA,IAAA,CAAK,SAAA,CAAU,YAAY,KAAK,CAAA;AAAA,EAClC;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,UAAU,SAAA,GAAY,CAAA,qCAAA,CAAA;AAAA,IAC7B;AAAA,EACF;AACF;AAEA,cAAA,CAAe,MAAA,CAAO,oBAAoB,eAAe,CAAA;;;AC/JzD,IAAMA,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,EAErB,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;AAAA,EAC5C;AAAA,EAEA,iBAAA,GAAoB;AAClB,IAAA,cAAA,CAAe,CAAC,OAAA,KAAY,IAAA,CAAK,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,EAChD;AAAA,EAEQ,KAAK,OAAA,EAA6B;AACxC,IAAA,OAAA,CAAQ,EAAA,CAAG,gBAAA,EAAkB,CAAC,IAAA,KAAsB;AAClD,MAAA,IAAA,CAAK,UAAA,EAAA;AACL,MAAA,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,GAAc,MAAA,CAAO,KAAK,KAAA,CAAM,IAAA,CAAK,WAAA,CAAY,CAAC,CAAC,CAAA;AAC/D,MAAA,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,GAAc,MAAA,CAAO,KAAK,KAAA,CAAM,IAAA,CAAK,WAAA,CAAY,CAAC,CAAC,CAAA;AAC/D,MAAA,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,GAAc,MAAA,CAAO,KAAK,KAAA,CAAM,IAAA,CAAK,WAAA,CAAY,CAAC,CAAC,CAAA;AAC/D,MAAA,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,GAAc,MAAA,CAAO,KAAK,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,CAAC,CAAC,CAAA;AAC5D,MAAA,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,GAAc,MAAA,CAAO,KAAK,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,CAAC,CAAC,CAAA;AAC5D,MAAA,IAAA,CAAK,GAAA,CAAI,GAAG,WAAA,GAAc,MAAA,CAAO,KAAK,KAAA,CAAM,IAAA,CAAK,QAAA,CAAS,CAAC,CAAC,CAAA;AAAA,IAC9D,CAAC,CAAA;AAED,IAAA,OAAA,CAAQ,EAAA,CAAG,aAAA,EAAe,CAAC,KAAA,EAAwB,QAAA,KAAgC;AACjF,MAAA,IAAA,CAAK,GAAA,CAAI,MAAM,WAAA,GAAc,KAAA;AAC7B,MAAA,IAAA,CAAK,GAAA,CAAI,QAAA,CAAS,WAAA,GAAc,QAAA,KAAa,SAAS,QAAA,GAAW,EAAA;AAAA,IACnE,CAAC,CAAA;AAED,IAAA,WAAA,CAAY,MAAM;AAChB,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;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","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { ConnectionState, TransportProtocol } from \"../core/types.js\";\n\nconst TEMPLATE = `\n<style>\n :host { display: inline-flex; align-items: center; gap: 8px; font-family: inherit; font-size: 13px; }\n .dot { width: 8px; height: 8px; border-radius: 50%; background: #e74c3c; transition: background 0.3s; }\n .dot[data-state=\"connected\"] { background: #2ecc71; }\n .dot[data-state=\"connecting\"] { background: #f39c12; }\n .dot[data-state=\"failed\"] { background: #e74c3c; }\n .protocol { color: #7f8c8d; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; }\n .launch { padding: 4px 12px; background: #2980b9; color: #fff; border-radius: 4px; font-size: 11px;\n text-decoration: none; cursor: pointer; border: none; font-family: inherit; display: none; }\n .launch:hover { background: #3498db; }\n</style>\n<span class=\"dot\"></span>\n<span class=\"text\">Disconnected</span>\n<span class=\"protocol\"></span>\n<button class=\"launch\">Launch SatMouse</button>\n`;\n\nexport class SatMouseStatus extends HTMLElement {\n private dot!: HTMLElement;\n private text!: HTMLElement;\n private proto!: HTMLElement;\n private launch!: HTMLButtonElement;\n private disconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = TEMPLATE;\n this.dot = shadow.querySelector(\".dot\")!;\n this.text = shadow.querySelector(\".text\")!;\n this.proto = shadow.querySelector(\".protocol\")!;\n this.launch = shadow.querySelector(\".launch\")!;\n\n this.launch.addEventListener(\"click\", () => {\n // Try the URL scheme — if installed, the OS opens the app\n window.location.href = \"satmouse://launch\";\n // If we're still here after 1s, the scheme wasn't handled\n setTimeout(() => {\n if (!document.hidden) {\n if (confirm(\"SatMouse doesn't appear to be installed. Go to the download page?\")) {\n window.open(\"https://github.com/kelnishi/SatMouse/releases/latest\", \"_blank\", \"noopener\");\n }\n }\n }, 1000);\n });\n }\n\n connectedCallback() {\n // Show launch button if still disconnected after 3s (covers cold page load)\n this.disconnectTimer = setTimeout(() => { this.launch.style.display = \"inline-block\"; }, 3000);\n onManagerReady((manager) => this.bind(manager));\n }\n\n private bind(manager: InputManager): void {\n manager.on(\"stateChange\", (state: ConnectionState, protocol: TransportProtocol) => {\n this.dot.dataset.state = state;\n this.proto.textContent = protocol !== \"none\" ? protocol : \"\";\n\n if (this.disconnectTimer) { clearTimeout(this.disconnectTimer); this.disconnectTimer = null; }\n\n if (state === \"connected\") {\n this.text.textContent = \"Connected\";\n this.launch.style.display = \"none\";\n } else if (state === \"connecting\") {\n this.text.textContent = \"Connecting...\";\n this.launch.style.display = \"none\";\n } else if (state === \"failed\") {\n this.text.textContent = \"Not running\";\n this.launch.style.display = \"inline-block\";\n } else {\n this.text.textContent = \"Disconnected\";\n this.launch.style.display = \"none\";\n }\n });\n }\n}\n\ncustomElements.define(\"satmouse-status\", SatMouseStatus);\n","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { DeviceInfo } from \"../core/types.js\";\nimport type { InputAxis } from \"../utils/action-map.js\";\nimport { DEFAULT_ACTION_MAP } from \"../utils/action-map.js\";\n\nconst AXES: InputAxis[] = [\"tx\", \"ty\", \"tz\", \"rx\", \"ry\", \"rz\"];\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 .flip-group { display: flex; flex-direction: column; gap: 4px; }\n .flip-row { display: flex; gap: 8px; }\n .flip-row label { display: flex; align-items: center; gap: 2px; color: #7f8c8d; min-width: 36px; }\n .flip-row input { accent-color: #e74c3c; }\n .remap-group { display: grid; grid-template-columns: 1fr 1fr; gap: 3px 8px; }\n .remap-row { display: flex; gap: 4px; align-items: center; }\n .remap-row label { color: #7f8c8d; width: 24px; flex-shrink: 0; }\n .remap-row select { background: #16213e; color: #e0e0e0; border: 1px solid #1a4a8a; border-radius: 3px;\n font-size: 11px; padding: 1px 4px; flex: 1; min-width: 0; }\n .empty { color: #7f8c8d; font-style: italic; }\n</style>\n`;\n\nfunction mapSlider(v: number): number { return 0.0001 * Math.pow(500, v / 100); }\nfunction unmapSlider(v: number): number { return (100 * Math.log(v / 0.0001)) / Math.log(500); }\n\nexport class SatMouseDevices extends HTMLElement {\n private manager: InputManager | null = null;\n private container!: HTMLElement;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = STYLES + `<div class=\"container\"><span class=\"empty\">No devices</span></div>`;\n this.container = shadow.querySelector(\".container\")!;\n }\n\n connectedCallback() {\n onManagerReady((manager) => {\n this.manager = manager;\n manager.on(\"deviceStatus\", (event, device) => {\n if (event === \"connected\") this.addDevice(device);\n else this.removeDevice(device);\n });\n manager.on(\"stateChange\", (state) => {\n if (state === \"connected\") {\n manager.fetchDeviceInfo().then((devices) => devices.forEach((d) => this.addDevice(d)));\n }\n });\n });\n }\n\n private addDevice(device: DeviceInfo): void {\n if (this.shadowRoot!.getElementById(`dev-${device.id}`)) return;\n const empty = this.container.querySelector(\".empty\");\n if (empty) empty.remove();\n\n const mgr = this.manager!;\n const cfg = mgr.getDeviceConfig(device.id);\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 const controls = document.createElement(\"div\");\n controls.className = \"controls\";\n\n // Sensitivity sliders\n for (const type of [\"translation\", \"rotation\"] as const) {\n const row = document.createElement(\"div\");\n row.className = \"slider-row\";\n const val = cfg.sensitivity?.[type] ?? mgr.config.sensitivity[type];\n row.innerHTML = `<label>${type === \"translation\" ? \"Trans\" : \"Rot\"}</label>` +\n `<input type=\"range\" min=\"0\" max=\"100\" value=\"${Math.round(unmapSlider(val))}\">` +\n `<span>${val.toFixed(4)}</span>`;\n const slider = row.querySelector(\"input\")! as HTMLInputElement;\n const span = row.querySelector(\"span\")!;\n slider.addEventListener(\"input\", () => {\n const v = mapSlider(+slider.value);\n span.textContent = v.toFixed(4);\n mgr.updateDeviceConfig(device.id, {\n sensitivity: { ...mgr.getDeviceConfig(device.id).sensitivity, [type]: v },\n });\n });\n controls.appendChild(row);\n }\n\n // Flip checkboxes\n const flipGroup = document.createElement(\"div\");\n flipGroup.className = \"flip-group\";\n for (const group of [[\"tx\", \"ty\", \"tz\"], [\"rx\", \"ry\", \"rz\"]] as InputAxis[][]) {\n const row = document.createElement(\"div\");\n row.className = \"flip-row\";\n for (const axis of group) {\n const label = document.createElement(\"label\");\n const cb = document.createElement(\"input\");\n cb.type = \"checkbox\";\n cb.checked = cfg.flip?.[axis] ?? mgr.config.flip[axis];\n cb.addEventListener(\"change\", () => {\n mgr.updateDeviceConfig(device.id, {\n flip: { ...mgr.getDeviceConfig(device.id).flip, [axis]: cb.checked },\n });\n });\n label.appendChild(cb);\n label.appendChild(document.createTextNode(axis.toUpperCase()));\n row.appendChild(label);\n }\n flipGroup.appendChild(row);\n }\n controls.appendChild(flipGroup);\n\n // Axis remap\n const remapGroup = document.createElement(\"div\");\n remapGroup.className = \"remap-group\";\n const actionMap = cfg.actionMap ?? mgr.config.actionMap;\n for (const action of AXES) {\n const row = document.createElement(\"div\");\n row.className = \"remap-row\";\n row.innerHTML = `<label>${action.toUpperCase()}</label>`;\n const sel = document.createElement(\"select\");\n for (const src of AXES) {\n const opt = document.createElement(\"option\");\n opt.value = src;\n opt.textContent = src.toUpperCase();\n if (actionMap[action]?.source === src) opt.selected = true;\n sel.appendChild(opt);\n }\n sel.addEventListener(\"change\", () => {\n const current = mgr.getDeviceConfig(device.id).actionMap ?? { ...DEFAULT_ACTION_MAP };\n current[action] = { ...current[action], source: sel.value as InputAxis };\n mgr.updateDeviceConfig(device.id, { actionMap: current });\n });\n row.appendChild(sel);\n remapGroup.appendChild(row);\n }\n controls.appendChild(remapGroup);\n\n panel.appendChild(controls);\n this.container.appendChild(panel);\n }\n\n private removeDevice(device: DeviceInfo): void {\n this.shadowRoot!.getElementById(`dev-${device.id}`)?.remove();\n if (this.container.children.length === 0) {\n this.container.innerHTML = `<span class=\"empty\">No devices</span>`;\n }\n }\n}\n\ncustomElements.define(\"satmouse-devices\", SatMouseDevices);\n","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { SpatialData, ConnectionState, TransportProtocol } from \"../core/types.js\";\n\nconst TEMPLATE = `\n<style>\n :host { display: block; font-family: monospace; font-size: 12px; }\n .row { display: flex; justify-content: space-between; padding: 2px 0; }\n .label { color: #7f8c8d; font-weight: 600; width: 28px; }\n .value { color: #3498db; text-align: right; min-width: 50px; }\n .meta { color: #7f8c8d; font-size: 11px; padding: 2px 0; }\n</style>\n<div class=\"meta\"><span class=\"state\">Disconnected</span> · <span class=\"protocol\"></span> · <span class=\"fps\">0</span> fps</div>\n<div class=\"row\"><span class=\"label\">TX</span><span class=\"value\" id=\"tx\">0</span></div>\n<div class=\"row\"><span class=\"label\">TY</span><span class=\"value\" id=\"ty\">0</span></div>\n<div class=\"row\"><span class=\"label\">TZ</span><span class=\"value\" id=\"tz\">0</span></div>\n<div class=\"row\"><span class=\"label\">RX</span><span class=\"value\" id=\"rx\">0</span></div>\n<div class=\"row\"><span class=\"label\">RY</span><span class=\"value\" id=\"ry\">0</span></div>\n<div class=\"row\"><span class=\"label\">RZ</span><span class=\"value\" id=\"rz\">0</span></div>\n`;\n\nexport class SatMouseDebug extends HTMLElement {\n private els: Record<string, HTMLElement> = {};\n private frameCount = 0;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = TEMPLATE;\n for (const id of [\"tx\", \"ty\", \"tz\", \"rx\", \"ry\", \"rz\"]) {\n this.els[id] = shadow.getElementById(id)!;\n }\n this.els.state = shadow.querySelector(\".state\")!;\n this.els.protocol = shadow.querySelector(\".protocol\")!;\n this.els.fps = shadow.querySelector(\".fps\")!;\n }\n\n connectedCallback() {\n onManagerReady((manager) => this.bind(manager));\n }\n\n private bind(manager: InputManager): void {\n manager.on(\"rawSpatialData\", (data: SpatialData) => {\n this.frameCount++;\n this.els.tx.textContent = String(Math.round(data.translation.x));\n this.els.ty.textContent = String(Math.round(data.translation.y));\n this.els.tz.textContent = String(Math.round(data.translation.z));\n this.els.rx.textContent = String(Math.round(data.rotation.x));\n this.els.ry.textContent = String(Math.round(data.rotation.y));\n this.els.rz.textContent = String(Math.round(data.rotation.z));\n });\n\n manager.on(\"stateChange\", (state: ConnectionState, protocol: TransportProtocol) => {\n this.els.state.textContent = state;\n this.els.protocol.textContent = protocol !== \"none\" ? protocol : \"\";\n });\n\n setInterval(() => {\n this.els.fps.textContent = String(this.frameCount);\n this.frameCount = 0;\n }, 1000);\n }\n}\n\ncustomElements.define(\"satmouse-debug\", SatMouseDebug);\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/elements/registry.ts","../../src/elements/satmouse-status.ts","../../src/elements/satmouse-devices.ts","../../src/elements/satmouse-debug.ts"],"names":["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","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { ConnectionState, TransportProtocol } from \"../core/types.js\";\n\nconst TEMPLATE = `\n<style>\n :host { display: inline-flex; align-items: center; gap: 8px; font-family: inherit; font-size: 13px; }\n .dot { width: 8px; height: 8px; border-radius: 50%; background: #e74c3c; transition: background 0.3s; }\n .dot[data-state=\"connected\"] { background: #2ecc71; }\n .dot[data-state=\"connecting\"] { background: #f39c12; }\n .dot[data-state=\"failed\"] { background: #e74c3c; }\n .protocol { color: #7f8c8d; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; }\n .launch { padding: 4px 12px; background: #2980b9; color: #fff; border-radius: 4px; font-size: 11px;\n text-decoration: none; cursor: pointer; border: none; font-family: inherit; display: none; }\n .launch:hover { background: #3498db; }\n</style>\n<span class=\"dot\"></span>\n<span class=\"text\">Disconnected</span>\n<span class=\"protocol\"></span>\n<button class=\"launch\">Launch SatMouse</button>\n`;\n\nexport class SatMouseStatus extends HTMLElement {\n private dot!: HTMLElement;\n private text!: HTMLElement;\n private proto!: HTMLElement;\n private launch!: HTMLButtonElement;\n private disconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = TEMPLATE;\n this.dot = shadow.querySelector(\".dot\")!;\n this.text = shadow.querySelector(\".text\")!;\n this.proto = shadow.querySelector(\".protocol\")!;\n this.launch = shadow.querySelector(\".launch\")!;\n\n this.launch.addEventListener(\"click\", () => {\n // Try the URL scheme — if installed, the OS opens the app\n window.location.href = \"satmouse://launch\";\n // If we're still here after 1s, the scheme wasn't handled\n setTimeout(() => {\n if (!document.hidden) {\n if (confirm(\"SatMouse doesn't appear to be installed. Go to the download page?\")) {\n window.open(\"https://github.com/kelnishi/SatMouse/releases/latest\", \"_blank\", \"noopener\");\n }\n }\n }, 1000);\n });\n }\n\n connectedCallback() {\n // Show launch button if still disconnected after 3s (covers cold page load)\n this.disconnectTimer = setTimeout(() => { this.launch.style.display = \"inline-block\"; }, 3000);\n onManagerReady((manager) => this.bind(manager));\n }\n\n private bind(manager: InputManager): void {\n manager.on(\"stateChange\", (state: ConnectionState, protocol: TransportProtocol) => {\n this.dot.dataset.state = state;\n this.proto.textContent = protocol !== \"none\" ? protocol : \"\";\n\n if (this.disconnectTimer) { clearTimeout(this.disconnectTimer); this.disconnectTimer = null; }\n\n if (state === \"connected\") {\n this.text.textContent = \"Connected\";\n this.launch.style.display = \"none\";\n } else if (state === \"connecting\") {\n this.text.textContent = \"Connecting...\";\n this.launch.style.display = \"none\";\n } else if (state === \"failed\") {\n this.text.textContent = \"Not running\";\n this.launch.style.display = \"inline-block\";\n } else {\n this.text.textContent = \"Disconnected\";\n this.launch.style.display = \"none\";\n }\n });\n }\n}\n\ncustomElements.define(\"satmouse-status\", SatMouseStatus);\n","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { DeviceInfo } from \"../core/types.js\";\nimport type { InputAxis, AxisRoute } from \"../utils/action-map.js\";\nimport { FULL_AXES, buildRoutes, DEFAULT_ROUTES } from \"../utils/action-map.js\";\n\nconst STYLES = `\n<style>\n :host { display: block; font-family: inherit; font-size: 12px; }\n .panel { background: #0f3460; border: 1px solid #1a4a8a; border-radius: 6px; padding: 10px; margin-bottom: 8px; }\n summary { cursor: pointer; font-weight: 600; color: #e0e0e0; font-size: 13px; }\n .type { font-size: 10px; color: #7f8c8d; text-transform: uppercase; margin-left: 6px; }\n .controls { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }\n .slider-row { display: flex; align-items: center; gap: 6px; }\n .slider-row label { color: #7f8c8d; font-weight: 600; width: 38px; flex-shrink: 0; }\n .slider-row input[type=\"range\"] { flex: 1; min-width: 0; height: 4px; accent-color: #3498db; }\n .slider-row span { color: #7f8c8d; font-family: monospace; font-size: 10px; min-width: 44px; text-align: right; }\n .route-group { display: flex; flex-wrap: wrap; gap: 4px 12px; }\n .route-row { display: flex; gap: 4px; align-items: center; }\n .route-row label { color: #7f8c8d; white-space: nowrap; }\n .route-row select { background: #16213e; color: #e0e0e0; border: 1px solid #1a4a8a; border-radius: 3px;\n font-size: 11px; padding: 1px 4px; }\n .route-row input[type=\"checkbox\"] { accent-color: #e74c3c; margin: 0; }\n .empty { color: #7f8c8d; font-style: italic; }\n .reset-btn { background: none; border: 1px solid #1a4a8a; border-radius: 3px; color: #7f8c8d;\n font-size: 11px; padding: 3px 8px; cursor: pointer; margin-top: 4px; }\n .reset-btn:hover { color: #e0e0e0; border-color: #e74c3c; }\n</style>\n`;\n\nfunction mapSlider(v: number): number { return 0.0001 * Math.pow(500, v / 100); }\nfunction unmapSlider(v: number): number { return (100 * Math.log(v / 0.0001)) / Math.log(500); }\n\nexport class SatMouseDevices extends HTMLElement {\n private manager: InputManager | null = null;\n private container!: HTMLElement;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = STYLES + `<div class=\"container\"><span class=\"empty\">No devices</span></div>`;\n this.container = shadow.querySelector(\".container\")!;\n }\n\n connectedCallback() {\n onManagerReady((manager) => {\n this.manager = manager;\n manager.on(\"deviceStatus\", (event, device) => {\n if (event === \"connected\") this.addDevice(device);\n else this.removeDevice(device);\n });\n manager.on(\"stateChange\", (state) => {\n if (state === \"connected\") {\n manager.fetchDeviceInfo().then((devices) => devices.forEach((d) => this.addDevice(d)));\n }\n });\n });\n }\n\n private addDevice(device: DeviceInfo): void {\n const existing = this.shadowRoot!.getElementById(`dev-${device.id}`);\n if (existing) {\n this.refreshControls(existing as HTMLDetailsElement, device);\n return;\n }\n const empty = this.container.querySelector(\".empty\");\n if (empty) empty.remove();\n\n const panel = document.createElement(\"details\");\n panel.className = \"panel\";\n panel.id = `dev-${device.id}`;\n panel.open = true;\n\n const summary = document.createElement(\"summary\");\n summary.innerHTML = `${device.model ?? device.name}<span class=\"type\">${device.connectionType ?? \"\"}</span>`;\n panel.appendChild(summary);\n\n this.refreshControls(panel, device);\n this.container.appendChild(panel);\n }\n\n private refreshControls(panel: HTMLDetailsElement, device: DeviceInfo): void {\n const old = panel.querySelector(\".controls\");\n if (old) old.remove();\n\n const mgr = this.manager!;\n const cfg = mgr.getDeviceConfig(device.id);\n\n const controls = document.createElement(\"div\");\n controls.className = \"controls\";\n\n // Axis routes — one row per device input: [flip] [label] → [target dropdown] [scale slider]\n const routeGroup = document.createElement(\"div\");\n routeGroup.className = \"route-group\";\n const deviceAxes = device.axes ?? [\"tx\", \"ty\", \"tz\", \"rx\", \"ry\", \"rz\"];\n const routes = this.getRoutes(device.id, deviceAxes);\n\n for (let i = 0; i < deviceAxes.length; i++) {\n const route = routes[i] ?? { source: deviceAxes[i] as InputAxis, target: deviceAxes[i].replace(/[+-]$/, \"\") as InputAxis };\n const row = document.createElement(\"div\");\n row.className = \"route-row\";\n\n // Flip checkbox\n const cb = document.createElement(\"input\");\n cb.type = \"checkbox\";\n cb.checked = route.flip ?? false;\n cb.title = \"Flip\";\n const routeIndex = i;\n cb.addEventListener(\"change\", () => {\n this.updateRoute(device.id, routeIndex, deviceAxes, { flip: cb.checked });\n });\n row.appendChild(cb);\n\n // Label (device input name)\n const label = document.createElement(\"label\");\n label.textContent = device.axisLabels?.[i] ?? deviceAxes[i].toUpperCase();\n row.appendChild(label);\n\n // Target dropdown\n const sel = document.createElement(\"select\");\n for (const target of FULL_AXES) {\n const opt = document.createElement(\"option\");\n opt.value = target;\n opt.textContent = target.toUpperCase();\n if (target === route.target) opt.selected = true;\n sel.appendChild(opt);\n }\n sel.addEventListener(\"change\", () => {\n this.updateRoute(device.id, routeIndex, deviceAxes, { target: sel.value as InputAxis });\n });\n row.appendChild(sel);\n\n routeGroup.appendChild(row);\n }\n controls.appendChild(routeGroup);\n\n // Scale slider\n const sensRow = document.createElement(\"div\");\n sensRow.className = \"slider-row\";\n const currentScale = cfg.scale ?? mgr.config.scale;\n sensRow.innerHTML = `<label>Scale</label>` +\n `<input type=\"range\" min=\"0\" max=\"100\" value=\"${Math.round(unmapSlider(currentScale))}\">` +\n `<span>${currentScale.toFixed(4)}</span>`;\n const slider = sensRow.querySelector(\"input\")! as HTMLInputElement;\n const span = sensRow.querySelector(\"span\")!;\n slider.addEventListener(\"input\", () => {\n const v = mapSlider(+slider.value);\n span.textContent = v.toFixed(4);\n mgr.updateDeviceConfig(device.id, { scale: v });\n });\n controls.appendChild(sensRow);\n\n // Reset button\n const resetBtn = document.createElement(\"button\");\n resetBtn.className = \"reset-btn\";\n resetBtn.textContent = \"Restore Defaults\";\n resetBtn.addEventListener(\"click\", () => {\n mgr.resetDeviceConfig(device.id);\n this.refreshControls(panel, device);\n });\n controls.appendChild(resetBtn);\n\n panel.appendChild(controls);\n }\n\n private getRoutes(deviceId: string, deviceAxes: string[]): AxisRoute[] {\n // Only use saved device config routes — not the global fallback\n const mgr = this.manager!;\n const devCfg = mgr.config.devices[deviceId];\n if (devCfg?.routes && Array.isArray(devCfg.routes)) return devCfg.routes;\n\n // Check pattern matches\n for (const [pattern, cfg] of Object.entries(mgr.config.devices)) {\n if (pattern.endsWith(\"*\") && deviceId.startsWith(pattern.slice(0, -1))) {\n if (cfg.routes && Array.isArray(cfg.routes)) return cfg.routes;\n }\n }\n\n // Build from device axes\n return buildRoutes(deviceAxes);\n }\n\n private updateRoute(deviceId: string, index: number, deviceAxes: string[], patch: Partial<AxisRoute>): void {\n const base = this.getRoutes(deviceId, deviceAxes);\n const updated = base.map((r, j) => j === index ? { ...r, ...patch } : { ...r });\n this.manager!.updateDeviceConfig(deviceId, { routes: updated });\n }\n\n private removeDevice(device: DeviceInfo): void {\n this.shadowRoot!.getElementById(`dev-${device.id}`)?.remove();\n if (this.container.children.length === 0) {\n this.container.innerHTML = `<span class=\"empty\">No devices</span>`;\n }\n }\n}\n\ncustomElements.define(\"satmouse-devices\", SatMouseDevices);\n","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { SpatialData, ConnectionState, TransportProtocol } from \"../core/types.js\";\n\nconst TEMPLATE = `\n<style>\n :host { display: block; font-family: monospace; font-size: 12px; }\n .row { display: flex; justify-content: space-between; padding: 2px 0; }\n .label { color: #7f8c8d; font-weight: 600; width: 28px; }\n .value { color: #3498db; text-align: right; min-width: 50px; }\n .meta { color: #7f8c8d; font-size: 11px; padding: 2px 0; }\n</style>\n<div class=\"meta\"><span class=\"state\">Disconnected</span> · <span class=\"protocol\"></span> · <span class=\"fps\">0</span> fps</div>\n<div class=\"row\"><span class=\"label\">TX</span><span class=\"value\" id=\"tx\">0</span></div>\n<div class=\"row\"><span class=\"label\">TY</span><span class=\"value\" id=\"ty\">0</span></div>\n<div class=\"row\"><span class=\"label\">TZ</span><span class=\"value\" id=\"tz\">0</span></div>\n<div class=\"row\"><span class=\"label\">RX</span><span class=\"value\" id=\"rx\">0</span></div>\n<div class=\"row\"><span class=\"label\">RY</span><span class=\"value\" id=\"ry\">0</span></div>\n<div class=\"row\"><span class=\"label\">RZ</span><span class=\"value\" id=\"rz\">0</span></div>\n`;\n\nexport class SatMouseDebug extends HTMLElement {\n private els: Record<string, HTMLElement> = {};\n private frameCount = 0;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = TEMPLATE;\n for (const id of [\"tx\", \"ty\", \"tz\", \"rx\", \"ry\", \"rz\"]) {\n this.els[id] = shadow.getElementById(id)!;\n }\n this.els.state = shadow.querySelector(\".state\")!;\n this.els.protocol = shadow.querySelector(\".protocol\")!;\n this.els.fps = shadow.querySelector(\".fps\")!;\n }\n\n connectedCallback() {\n onManagerReady((manager) => this.bind(manager));\n }\n\n private bind(manager: InputManager): void {\n manager.on(\"rawSpatialData\", (data: SpatialData) => {\n this.frameCount++;\n this.els.tx.textContent = String(Math.round(data.translation.x));\n this.els.ty.textContent = String(Math.round(data.translation.y));\n this.els.tz.textContent = String(Math.round(data.translation.z));\n this.els.rx.textContent = String(Math.round(data.rotation.x));\n this.els.ry.textContent = String(Math.round(data.rotation.y));\n this.els.rz.textContent = String(Math.round(data.rotation.z));\n });\n\n manager.on(\"stateChange\", (state: ConnectionState, protocol: TransportProtocol) => {\n this.els.state.textContent = state;\n this.els.protocol.textContent = protocol !== \"none\" ? protocol : \"\";\n });\n\n setInterval(() => {\n this.els.fps.textContent = String(this.frameCount);\n this.frameCount = 0;\n }, 1000);\n }\n}\n\ncustomElements.define(\"satmouse-debug\", SatMouseDebug);\n"]}
|