@kelnishi/satmouse-client 0.16.1 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -73,33 +73,66 @@ function Scene() {
73
73
  <satmouse-debug></satmouse-debug>
74
74
  ```
75
75
 
76
- ## Per-Device Configuration
76
+ ## Configuration
77
77
 
78
- Axis routing with per-device flip, scale, and remapping:
78
+ ### Device class defaults
79
+
80
+ Set routes, scales, and behavior by device class — applies to all devices of that type:
79
81
 
80
82
  ```typescript
81
83
  const manager = new InputManager({
82
84
  translateScale: 0.001,
83
85
  rotateScale: 0.001,
84
- wScale: 0.001,
85
- devices: {
86
- "cnx-*": {
86
+ deviceClasses: {
87
+ spacemouse: {
88
+ // Built-in default: flips Y/Z axes (3Dconnexion convention)
89
+ rotateScale: 0.0005,
90
+ },
91
+ gamepad: {
87
92
  routes: [
88
93
  { source: "tx", target: "tx" },
89
- { source: "ty", target: "ty", flip: true },
90
- { source: "tz", target: "tz", flip: true },
94
+ { source: "tz", target: "tz" },
91
95
  { source: "rx", target: "rx" },
92
- { source: "ry", target: "ry", flip: true },
93
- { source: "rz", target: "rz", flip: true },
96
+ { source: "rz", target: "rz" },
97
+ { source: "ty", target: "ty" }, // L2 trigger
98
+ { source: "ry", target: "ty", flip: true }, // R2 trigger (push-pull)
94
99
  ],
100
+ deadZone: 0.05,
95
101
  },
96
102
  },
97
103
  });
104
+ ```
105
+
106
+ Device classes: `"spacemouse"`, `"gamepad"`, `"dial"`, `"joystick"`, `"6dof"`, `"other"`
107
+
108
+ ### Per-device overrides
109
+
110
+ Override config for a specific device by ID or vendor pattern:
111
+
112
+ ```typescript
113
+ const manager = new InputManager({
114
+ devices: {
115
+ // All PlayStation controllers (vendor 054c)
116
+ "hid-54c-*": { translateScale: 0.002 },
117
+ // A specific device by ID
118
+ "hid-54c-9cc-1": { dominant: true },
119
+ },
120
+ });
98
121
 
99
- // Update per-device at runtime
122
+ // Update at runtime
100
123
  manager.updateDeviceConfig("cnx-c635", { translateScale: 0.0005 });
101
124
  ```
102
125
 
126
+ ### Resolution order
127
+
128
+ Config is resolved per-device in this priority:
129
+
130
+ 1. **Exact device ID** — `devices["hid-54c-9cc-1"]`
131
+ 2. **ID pattern** — `devices["hid-54c-*"]`
132
+ 3. **Device class** — `deviceClasses["gamepad"]`
133
+ 4. **Device axes metadata** — auto-generated passthrough from bridge
134
+ 5. **Global defaults** — `routes`, `translateScale`, etc.
135
+
103
136
  ## Button-to-Key Mapping
104
137
 
105
138
  Map device buttons to keyboard events:
@@ -162,4 +162,4 @@ declare class SatMouseConnection extends TypedEmitter<SatMouseEvents> {
162
162
  private clearReconnect;
163
163
  }
164
164
 
165
- export { type ButtonEvent as B, type ConnectOptions as C, type DeviceInfo as D, type SpatialData as S, type ThingDescription as T, type Vec3 as V, type ConnectionState as a, SatMouseConnection as b, type SatMouseEvents as c, type TransportProtocol as d, TypedEmitter as e, buildSatMouseUri as f, parseSatMouseUri as p };
165
+ export { type ButtonEvent as B, type ConnectOptions as C, type DeviceInfo as D, type SpatialData as S, type ThingDescription as T, type Vec3 as V, type ConnectionState as a, SatMouseConnection as b, type SatMouseEvents as c, type TransportProtocol as d, TypedEmitter as e, buildSatMouseUri as f, type DeviceClass as g, parseSatMouseUri as p };
@@ -162,4 +162,4 @@ declare class SatMouseConnection extends TypedEmitter<SatMouseEvents> {
162
162
  private clearReconnect;
163
163
  }
164
164
 
165
- export { type ButtonEvent as B, type ConnectOptions as C, type DeviceInfo as D, type SpatialData as S, type ThingDescription as T, type Vec3 as V, type ConnectionState as a, SatMouseConnection as b, type SatMouseEvents as c, type TransportProtocol as d, TypedEmitter as e, buildSatMouseUri as f, parseSatMouseUri as p };
165
+ export { type ButtonEvent as B, type ConnectOptions as C, type DeviceInfo as D, type SpatialData as S, type ThingDescription as T, type Vec3 as V, type ConnectionState as a, SatMouseConnection as b, type SatMouseEvents as c, type TransportProtocol as d, TypedEmitter as e, buildSatMouseUri as f, type DeviceClass as g, parseSatMouseUri as p };
@@ -1,5 +1,5 @@
1
- import { T as ThingDescription, S as SpatialData, B as ButtonEvent } from '../connection-DXjjuaLv.cjs';
2
- export { C as ConnectOptions, a as ConnectionState, D as DeviceInfo, b as SatMouseConnection, c as SatMouseEvents, d as TransportProtocol, e as TypedEmitter, V as Vec3, f as buildSatMouseUri, p as parseSatMouseUri } from '../connection-DXjjuaLv.cjs';
1
+ import { T as ThingDescription, S as SpatialData, B as ButtonEvent } from '../connection-DcA50IC2.cjs';
2
+ export { C as ConnectOptions, a as ConnectionState, D as DeviceInfo, b as SatMouseConnection, c as SatMouseEvents, d as TransportProtocol, e as TypedEmitter, V as Vec3, f as buildSatMouseUri, p as parseSatMouseUri } from '../connection-DcA50IC2.cjs';
3
3
 
4
4
  interface ResolvedEndpoints {
5
5
  webtransport?: {
@@ -1,5 +1,5 @@
1
- import { T as ThingDescription, S as SpatialData, B as ButtonEvent } from '../connection-DXjjuaLv.js';
2
- export { C as ConnectOptions, a as ConnectionState, D as DeviceInfo, b as SatMouseConnection, c as SatMouseEvents, d as TransportProtocol, e as TypedEmitter, V as Vec3, f as buildSatMouseUri, p as parseSatMouseUri } from '../connection-DXjjuaLv.js';
1
+ import { T as ThingDescription, S as SpatialData, B as ButtonEvent } from '../connection-DcA50IC2.js';
2
+ export { C as ConnectOptions, a as ConnectionState, D as DeviceInfo, b as SatMouseConnection, c as SatMouseEvents, d as TransportProtocol, e as TypedEmitter, V as Vec3, f as buildSatMouseUri, p as parseSatMouseUri } from '../connection-DcA50IC2.js';
3
3
 
4
4
  interface ResolvedEndpoints {
5
5
  webtransport?: {
@@ -285,7 +285,7 @@ var SatMouseDevices = class extends HTMLElement {
285
285
  const routeGroup = document.createElement("div");
286
286
  routeGroup.className = "route-group";
287
287
  const deviceAxes = device.axes ?? ["tx", "ty", "tz", "rx", "ry", "rz"];
288
- const routes = this.getRoutes(device.id, deviceAxes);
288
+ const routes = this.getRoutes(device, deviceAxes);
289
289
  for (let i = 0; i < deviceAxes.length; i++) {
290
290
  const route = routes[i] ?? { source: deviceAxes[i], target: deviceAxes[i].replace(/[+-]$/, "") };
291
291
  const row = document.createElement("div");
@@ -414,19 +414,24 @@ var SatMouseDevices = class extends HTMLElement {
414
414
  controls.appendChild(resetBtn);
415
415
  panel.appendChild(controls);
416
416
  }
417
- getRoutes(deviceId, deviceAxes) {
417
+ getRoutes(device, deviceAxes) {
418
418
  const mgr = this.manager;
419
- const devCfg = mgr.config.devices[deviceId];
419
+ const devCfg = mgr.config.devices[device.id];
420
420
  if (devCfg?.routes && Array.isArray(devCfg.routes)) return devCfg.routes;
421
421
  for (const [pattern, cfg] of Object.entries(mgr.config.devices)) {
422
- if (pattern.endsWith("*") && deviceId.startsWith(pattern.slice(0, -1))) {
422
+ if (pattern.endsWith("*") && device.id.startsWith(pattern.slice(0, -1))) {
423
423
  if (cfg.routes && Array.isArray(cfg.routes)) return cfg.routes;
424
424
  }
425
425
  }
426
+ if (device.deviceClass && mgr.config.deviceClasses) {
427
+ const classCfg = mgr.config.deviceClasses[device.deviceClass];
428
+ if (classCfg?.routes && Array.isArray(classCfg.routes)) return classCfg.routes;
429
+ }
426
430
  return chunkY75556IA_cjs.buildRoutes(deviceAxes);
427
431
  }
428
432
  updateRoute(deviceId, index, deviceAxes, patch) {
429
- const base = this.getRoutes(deviceId, deviceAxes);
433
+ const device = Array.from(this.manager.getDevicesWithConfig()).find((d) => d.device.id === deviceId)?.device;
434
+ const base = this.getRoutes(device ?? { id: deviceId }, deviceAxes);
430
435
  const updated = base.map((r, j) => j === index ? { ...r, ...patch } : { ...r });
431
436
  this.manager.updateDeviceConfig(deviceId, { routes: updated });
432
437
  }
@@ -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.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 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(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 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/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,5 +1,5 @@
1
1
  import { InputManager } from '../utils/index.cjs';
2
- import '../connection-DXjjuaLv.cjs';
2
+ import '../connection-DcA50IC2.cjs';
3
3
 
4
4
  declare class SatMouseStatus extends HTMLElement {
5
5
  private dot;
@@ -1,5 +1,5 @@
1
1
  import { InputManager } from '../utils/index.js';
2
- import '../connection-DXjjuaLv.js';
2
+ import '../connection-DcA50IC2.js';
3
3
 
4
4
  declare class SatMouseStatus extends HTMLElement {
5
5
  private dot;
@@ -283,7 +283,7 @@ var SatMouseDevices = class extends HTMLElement {
283
283
  const routeGroup = document.createElement("div");
284
284
  routeGroup.className = "route-group";
285
285
  const deviceAxes = device.axes ?? ["tx", "ty", "tz", "rx", "ry", "rz"];
286
- const routes = this.getRoutes(device.id, deviceAxes);
286
+ const routes = this.getRoutes(device, deviceAxes);
287
287
  for (let i = 0; i < deviceAxes.length; i++) {
288
288
  const route = routes[i] ?? { source: deviceAxes[i], target: deviceAxes[i].replace(/[+-]$/, "") };
289
289
  const row = document.createElement("div");
@@ -412,19 +412,24 @@ var SatMouseDevices = class extends HTMLElement {
412
412
  controls.appendChild(resetBtn);
413
413
  panel.appendChild(controls);
414
414
  }
415
- getRoutes(deviceId, deviceAxes) {
415
+ getRoutes(device, deviceAxes) {
416
416
  const mgr = this.manager;
417
- const devCfg = mgr.config.devices[deviceId];
417
+ const devCfg = mgr.config.devices[device.id];
418
418
  if (devCfg?.routes && Array.isArray(devCfg.routes)) return devCfg.routes;
419
419
  for (const [pattern, cfg] of Object.entries(mgr.config.devices)) {
420
- if (pattern.endsWith("*") && deviceId.startsWith(pattern.slice(0, -1))) {
420
+ if (pattern.endsWith("*") && device.id.startsWith(pattern.slice(0, -1))) {
421
421
  if (cfg.routes && Array.isArray(cfg.routes)) return cfg.routes;
422
422
  }
423
423
  }
424
+ if (device.deviceClass && mgr.config.deviceClasses) {
425
+ const classCfg = mgr.config.deviceClasses[device.deviceClass];
426
+ if (classCfg?.routes && Array.isArray(classCfg.routes)) return classCfg.routes;
427
+ }
424
428
  return buildRoutes(deviceAxes);
425
429
  }
426
430
  updateRoute(deviceId, index, deviceAxes, patch) {
427
- const base = this.getRoutes(deviceId, deviceAxes);
431
+ const device = Array.from(this.manager.getDevicesWithConfig()).find((d) => d.device.id === deviceId)?.device;
432
+ const base = this.getRoutes(device ?? { id: deviceId }, deviceAxes);
428
433
  const updated = base.map((r, j) => j === index ? { ...r, ...patch } : { ...r });
429
434
  this.manager.updateDeviceConfig(deviceId, { routes: updated });
430
435
  }