@kelnishi/satmouse-client 0.9.15 → 0.10.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/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.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/react/index.d.cts +0 -313
- package/dist/react/index.d.ts +0 -313
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/utils/action-map.ts
|
|
4
|
+
var FULL_AXES = ["tx", "ty", "tz", "rx", "ry", "rz"];
|
|
5
|
+
var DEFAULT_ROUTES = [
|
|
6
|
+
{ source: "tx", target: "tx" },
|
|
7
|
+
{ source: "ty", target: "ty" },
|
|
8
|
+
{ source: "tz", target: "tz" },
|
|
9
|
+
{ source: "rx", target: "rx" },
|
|
10
|
+
{ source: "ry", target: "ry" },
|
|
11
|
+
{ source: "rz", target: "rz" }
|
|
12
|
+
];
|
|
13
|
+
function buildRoutes(axes) {
|
|
14
|
+
return axes.map((axis) => {
|
|
15
|
+
const base = axis.replace(/[+-]$/, "");
|
|
16
|
+
const flip = axis.endsWith("-");
|
|
17
|
+
return { source: axis, target: base, ...flip && { flip: true } };
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function readAxis(data, axis) {
|
|
21
|
+
const base = axis.replace(/[+-]$/, "");
|
|
22
|
+
switch (base) {
|
|
23
|
+
case "tx":
|
|
24
|
+
return data.translation.x;
|
|
25
|
+
case "ty":
|
|
26
|
+
return data.translation.y;
|
|
27
|
+
case "tz":
|
|
28
|
+
return data.translation.z;
|
|
29
|
+
case "rx":
|
|
30
|
+
return data.rotation.x;
|
|
31
|
+
case "ry":
|
|
32
|
+
return data.rotation.y;
|
|
33
|
+
case "rz":
|
|
34
|
+
return data.rotation.z;
|
|
35
|
+
default:
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function writeAxis(t, r, axis, value) {
|
|
40
|
+
const isNeg = axis.endsWith("-");
|
|
41
|
+
const base = axis.replace(/[+-]$/, "");
|
|
42
|
+
const sign = isNeg ? -1 : 1;
|
|
43
|
+
const group = base[0];
|
|
44
|
+
const key = base[1];
|
|
45
|
+
if (group === "t") t[key] += value * sign;
|
|
46
|
+
else r[key] += value * sign;
|
|
47
|
+
}
|
|
48
|
+
function applyRoutes(data, routes, scale = 1) {
|
|
49
|
+
const t = { x: 0, y: 0, z: 0 };
|
|
50
|
+
const r = { x: 0, y: 0, z: 0 };
|
|
51
|
+
for (const route of routes) {
|
|
52
|
+
let value = readAxis(data, route.source);
|
|
53
|
+
if (route.flip) value = -value;
|
|
54
|
+
value *= scale;
|
|
55
|
+
writeAxis(t, r, route.target, value);
|
|
56
|
+
}
|
|
57
|
+
return { translation: t, rotation: r, timestamp: data.timestamp, deviceId: data.deviceId };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
exports.DEFAULT_ROUTES = DEFAULT_ROUTES;
|
|
61
|
+
exports.FULL_AXES = FULL_AXES;
|
|
62
|
+
exports.applyRoutes = applyRoutes;
|
|
63
|
+
exports.buildRoutes = buildRoutes;
|
|
64
|
+
//# sourceMappingURL=chunk-JTG5GEIB.cjs.map
|
|
65
|
+
//# sourceMappingURL=chunk-JTG5GEIB.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/action-map.ts"],"names":[],"mappings":"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","file":"chunk-JTG5GEIB.cjs","sourcesContent":["import type { SpatialData } from \"../core/types.js\";\n\n/** Axis identifier — full or half */\nexport type InputAxis =\n | \"tx\" | \"ty\" | \"tz\" | \"rx\" | \"ry\" | \"rz\"\n | \"tx+\" | \"ty+\" | \"tz+\" | \"rx+\" | \"ry+\" | \"rz+\"\n | \"tx-\" | \"ty-\" | \"tz-\" | \"rx-\" | \"ry-\" | \"rz-\";\n\n/** The 6 full output axes */\nexport const FULL_AXES: InputAxis[] = [\"tx\", \"ty\", \"tz\", \"rx\", \"ry\", \"rz\"];\n\n/** A single axis route — reads from source, writes to target */\nexport interface AxisRoute {\n source: InputAxis;\n target: InputAxis;\n /** Negate the value (default: false) */\n flip?: boolean;\n}\n\n/** Default 6DOF passthrough */\nexport const DEFAULT_ROUTES: AxisRoute[] = [\n { source: \"tx\", target: \"tx\" },\n { source: \"ty\", target: \"ty\" },\n { source: \"tz\", target: \"tz\" },\n { source: \"rx\", target: \"rx\" },\n { source: \"ry\", target: \"ry\" },\n { source: \"rz\", target: \"rz\" },\n];\n\n/** Build passthrough routes from a device's axis list. Half-axes target their base axis.\n * Negative half-axes (e.g., \"ty-\") get flip: true. */\nexport function buildRoutes(axes: string[]): AxisRoute[] {\n return axes.map((axis) => {\n const base = axis.replace(/[+-]$/, \"\");\n const flip = axis.endsWith(\"-\");\n return { source: axis as InputAxis, target: base as InputAxis, ...(flip && { flip: true }) };\n });\n}\n\n/** Read a value from SpatialData by axis name. Half-axes read the same as the full axis. */\nfunction readAxis(data: SpatialData, axis: InputAxis): number {\n const base = axis.replace(/[+-]$/, \"\");\n switch (base) {\n case \"tx\": return data.translation.x;\n case \"ty\": return data.translation.y;\n case \"tz\": return data.translation.z;\n case \"rx\": return data.rotation.x;\n case \"ry\": return data.rotation.y;\n case \"rz\": return data.rotation.z;\n default: return 0;\n }\n}\n\n/** Write a value to accumulators. Half-axis targets: \"tz+\" adds, \"tz-\" subtracts. */\nfunction writeAxis(t: { x: number; y: number; z: number }, r: { x: number; y: number; z: number }, axis: InputAxis, value: number): void {\n const isNeg = axis.endsWith(\"-\");\n const base = axis.replace(/[+-]$/, \"\");\n const sign = isNeg ? -1 : 1;\n const group = base[0] as \"t\" | \"r\";\n const key = base[1] as \"x\" | \"y\" | \"z\";\n if (group === \"t\") t[key] += value * sign;\n else r[key] += value * sign;\n}\n\n/** Apply routes to SpatialData. Multiple routes targeting the same axis accumulate.\n * @param scale — global scale multiplier applied to all routes */\nexport function applyRoutes(data: SpatialData, routes: AxisRoute[], scale = 1): SpatialData {\n const t = { x: 0, y: 0, z: 0 };\n const r = { x: 0, y: 0, z: 0 };\n\n for (const route of routes) {\n let value = readAxis(data, route.source);\n if (route.flip) value = -value;\n value *= scale;\n writeAxis(t, r, route.target, value);\n }\n\n return { translation: t, rotation: r, timestamp: data.timestamp, deviceId: data.deviceId };\n}\n"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// src/utils/action-map.ts
|
|
2
|
+
var FULL_AXES = ["tx", "ty", "tz", "rx", "ry", "rz"];
|
|
3
|
+
var DEFAULT_ROUTES = [
|
|
4
|
+
{ source: "tx", target: "tx" },
|
|
5
|
+
{ source: "ty", target: "ty" },
|
|
6
|
+
{ source: "tz", target: "tz" },
|
|
7
|
+
{ source: "rx", target: "rx" },
|
|
8
|
+
{ source: "ry", target: "ry" },
|
|
9
|
+
{ source: "rz", target: "rz" }
|
|
10
|
+
];
|
|
11
|
+
function buildRoutes(axes) {
|
|
12
|
+
return axes.map((axis) => {
|
|
13
|
+
const base = axis.replace(/[+-]$/, "");
|
|
14
|
+
const flip = axis.endsWith("-");
|
|
15
|
+
return { source: axis, target: base, ...flip && { flip: true } };
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function readAxis(data, axis) {
|
|
19
|
+
const base = axis.replace(/[+-]$/, "");
|
|
20
|
+
switch (base) {
|
|
21
|
+
case "tx":
|
|
22
|
+
return data.translation.x;
|
|
23
|
+
case "ty":
|
|
24
|
+
return data.translation.y;
|
|
25
|
+
case "tz":
|
|
26
|
+
return data.translation.z;
|
|
27
|
+
case "rx":
|
|
28
|
+
return data.rotation.x;
|
|
29
|
+
case "ry":
|
|
30
|
+
return data.rotation.y;
|
|
31
|
+
case "rz":
|
|
32
|
+
return data.rotation.z;
|
|
33
|
+
default:
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function writeAxis(t, r, axis, value) {
|
|
38
|
+
const isNeg = axis.endsWith("-");
|
|
39
|
+
const base = axis.replace(/[+-]$/, "");
|
|
40
|
+
const sign = isNeg ? -1 : 1;
|
|
41
|
+
const group = base[0];
|
|
42
|
+
const key = base[1];
|
|
43
|
+
if (group === "t") t[key] += value * sign;
|
|
44
|
+
else r[key] += value * sign;
|
|
45
|
+
}
|
|
46
|
+
function applyRoutes(data, routes, scale = 1) {
|
|
47
|
+
const t = { x: 0, y: 0, z: 0 };
|
|
48
|
+
const r = { x: 0, y: 0, z: 0 };
|
|
49
|
+
for (const route of routes) {
|
|
50
|
+
let value = readAxis(data, route.source);
|
|
51
|
+
if (route.flip) value = -value;
|
|
52
|
+
value *= scale;
|
|
53
|
+
writeAxis(t, r, route.target, value);
|
|
54
|
+
}
|
|
55
|
+
return { translation: t, rotation: r, timestamp: data.timestamp, deviceId: data.deviceId };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { DEFAULT_ROUTES, FULL_AXES, applyRoutes, buildRoutes };
|
|
59
|
+
//# sourceMappingURL=chunk-RNM322RZ.js.map
|
|
60
|
+
//# sourceMappingURL=chunk-RNM322RZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/action-map.ts"],"names":[],"mappings":"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","file":"chunk-RNM322RZ.js","sourcesContent":["import type { SpatialData } from \"../core/types.js\";\n\n/** Axis identifier — full or half */\nexport type InputAxis =\n | \"tx\" | \"ty\" | \"tz\" | \"rx\" | \"ry\" | \"rz\"\n | \"tx+\" | \"ty+\" | \"tz+\" | \"rx+\" | \"ry+\" | \"rz+\"\n | \"tx-\" | \"ty-\" | \"tz-\" | \"rx-\" | \"ry-\" | \"rz-\";\n\n/** The 6 full output axes */\nexport const FULL_AXES: InputAxis[] = [\"tx\", \"ty\", \"tz\", \"rx\", \"ry\", \"rz\"];\n\n/** A single axis route — reads from source, writes to target */\nexport interface AxisRoute {\n source: InputAxis;\n target: InputAxis;\n /** Negate the value (default: false) */\n flip?: boolean;\n}\n\n/** Default 6DOF passthrough */\nexport const DEFAULT_ROUTES: AxisRoute[] = [\n { source: \"tx\", target: \"tx\" },\n { source: \"ty\", target: \"ty\" },\n { source: \"tz\", target: \"tz\" },\n { source: \"rx\", target: \"rx\" },\n { source: \"ry\", target: \"ry\" },\n { source: \"rz\", target: \"rz\" },\n];\n\n/** Build passthrough routes from a device's axis list. Half-axes target their base axis.\n * Negative half-axes (e.g., \"ty-\") get flip: true. */\nexport function buildRoutes(axes: string[]): AxisRoute[] {\n return axes.map((axis) => {\n const base = axis.replace(/[+-]$/, \"\");\n const flip = axis.endsWith(\"-\");\n return { source: axis as InputAxis, target: base as InputAxis, ...(flip && { flip: true }) };\n });\n}\n\n/** Read a value from SpatialData by axis name. Half-axes read the same as the full axis. */\nfunction readAxis(data: SpatialData, axis: InputAxis): number {\n const base = axis.replace(/[+-]$/, \"\");\n switch (base) {\n case \"tx\": return data.translation.x;\n case \"ty\": return data.translation.y;\n case \"tz\": return data.translation.z;\n case \"rx\": return data.rotation.x;\n case \"ry\": return data.rotation.y;\n case \"rz\": return data.rotation.z;\n default: return 0;\n }\n}\n\n/** Write a value to accumulators. Half-axis targets: \"tz+\" adds, \"tz-\" subtracts. */\nfunction writeAxis(t: { x: number; y: number; z: number }, r: { x: number; y: number; z: number }, axis: InputAxis, value: number): void {\n const isNeg = axis.endsWith(\"-\");\n const base = axis.replace(/[+-]$/, \"\");\n const sign = isNeg ? -1 : 1;\n const group = base[0] as \"t\" | \"r\";\n const key = base[1] as \"x\" | \"y\" | \"z\";\n if (group === \"t\") t[key] += value * sign;\n else r[key] += value * sign;\n}\n\n/** Apply routes to SpatialData. Multiple routes targeting the same axis accumulate.\n * @param scale — global scale multiplier applied to all routes */\nexport function applyRoutes(data: SpatialData, routes: AxisRoute[], scale = 1): SpatialData {\n const t = { x: 0, y: 0, z: 0 };\n const r = { x: 0, y: 0, z: 0 };\n\n for (const route of routes) {\n let value = readAxis(data, route.source);\n if (route.flip) value = -value;\n value *= scale;\n writeAxis(t, r, route.target, value);\n }\n\n return { translation: t, rotation: r, timestamp: data.timestamp, deviceId: data.deviceId };\n}\n"]}
|
|
@@ -36,6 +36,12 @@ interface DeviceInfo {
|
|
|
36
36
|
productId?: number;
|
|
37
37
|
connectionType?: "usb" | "wireless" | "bluetooth" | "unknown";
|
|
38
38
|
connected?: boolean;
|
|
39
|
+
/** Axes this device provides (e.g., ["tx","ty","tz","rx","ry","rz"] or ["tx","ty","rx","ry","tz+","rz+"]) */
|
|
40
|
+
axes?: string[];
|
|
41
|
+
/** Human-readable labels for axes (same order as axes array) */
|
|
42
|
+
axisLabels?: string[];
|
|
43
|
+
/** Number of buttons this device provides */
|
|
44
|
+
buttonCount?: number;
|
|
39
45
|
}
|
|
40
46
|
type ConnectionState = "disconnected" | "connecting" | "connected" | "failed";
|
|
41
47
|
type TransportProtocol = "webtransport" | "websocket" | "none";
|
|
@@ -36,6 +36,12 @@ interface DeviceInfo {
|
|
|
36
36
|
productId?: number;
|
|
37
37
|
connectionType?: "usb" | "wireless" | "bluetooth" | "unknown";
|
|
38
38
|
connected?: boolean;
|
|
39
|
+
/** Axes this device provides (e.g., ["tx","ty","tz","rx","ry","rz"] or ["tx","ty","rx","ry","tz+","rz+"]) */
|
|
40
|
+
axes?: string[];
|
|
41
|
+
/** Human-readable labels for axes (same order as axes array) */
|
|
42
|
+
axisLabels?: string[];
|
|
43
|
+
/** Number of buttons this device provides */
|
|
44
|
+
buttonCount?: number;
|
|
39
45
|
}
|
|
40
46
|
type ConnectionState = "disconnected" | "connecting" | "connected" | "failed";
|
|
41
47
|
type TransportProtocol = "webtransport" | "websocket" | "none";
|
package/dist/core/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as ThingDescription, S as SpatialData, B as ButtonEvent } from '../connection-
|
|
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-
|
|
1
|
+
import { T as ThingDescription, S as SpatialData, B as ButtonEvent } from '../connection-DQxI5qib.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-DQxI5qib.cjs';
|
|
3
3
|
|
|
4
4
|
interface ResolvedEndpoints {
|
|
5
5
|
webtransport?: {
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as ThingDescription, S as SpatialData, B as ButtonEvent } from '../connection-
|
|
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-
|
|
1
|
+
import { T as ThingDescription, S as SpatialData, B as ButtonEvent } from '../connection-DQxI5qib.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-DQxI5qib.js';
|
|
3
3
|
|
|
4
4
|
interface ResolvedEndpoints {
|
|
5
5
|
webtransport?: {
|
package/dist/elements/index.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkJTG5GEIB_cjs = require('../chunk-JTG5GEIB.cjs');
|
|
4
4
|
|
|
5
5
|
// src/elements/registry.ts
|
|
6
6
|
var globalManager = null;
|
|
@@ -94,7 +94,6 @@ var SatMouseStatus = class extends HTMLElement {
|
|
|
94
94
|
customElements.define("satmouse-status", SatMouseStatus);
|
|
95
95
|
|
|
96
96
|
// src/elements/satmouse-devices.ts
|
|
97
|
-
var AXES = ["tx", "ty", "tz", "rx", "ry", "rz"];
|
|
98
97
|
var STYLES = `
|
|
99
98
|
<style>
|
|
100
99
|
:host { display: block; font-family: inherit; font-size: 12px; }
|
|
@@ -106,16 +105,16 @@ var STYLES = `
|
|
|
106
105
|
.slider-row label { color: #7f8c8d; font-weight: 600; width: 38px; flex-shrink: 0; }
|
|
107
106
|
.slider-row input[type="range"] { flex: 1; min-width: 0; height: 4px; accent-color: #3498db; }
|
|
108
107
|
.slider-row span { color: #7f8c8d; font-family: monospace; font-size: 10px; min-width: 44px; text-align: right; }
|
|
109
|
-
.
|
|
110
|
-
.
|
|
111
|
-
.
|
|
112
|
-
.
|
|
113
|
-
|
|
114
|
-
.
|
|
115
|
-
.remap-row label { color: #7f8c8d; width: 24px; flex-shrink: 0; }
|
|
116
|
-
.remap-row select { background: #16213e; color: #e0e0e0; border: 1px solid #1a4a8a; border-radius: 3px;
|
|
117
|
-
font-size: 11px; padding: 1px 4px; flex: 1; min-width: 0; }
|
|
108
|
+
.route-group { display: flex; flex-wrap: wrap; gap: 4px 12px; }
|
|
109
|
+
.route-row { display: flex; gap: 4px; align-items: center; }
|
|
110
|
+
.route-row label { color: #7f8c8d; white-space: nowrap; }
|
|
111
|
+
.route-row select { background: #16213e; color: #e0e0e0; border: 1px solid #1a4a8a; border-radius: 3px;
|
|
112
|
+
font-size: 11px; padding: 1px 4px; }
|
|
113
|
+
.route-row input[type="checkbox"] { accent-color: #e74c3c; margin: 0; }
|
|
118
114
|
.empty { color: #7f8c8d; font-style: italic; }
|
|
115
|
+
.reset-btn { background: none; border: 1px solid #1a4a8a; border-radius: 3px; color: #7f8c8d;
|
|
116
|
+
font-size: 11px; padding: 3px 8px; cursor: pointer; margin-top: 4px; }
|
|
117
|
+
.reset-btn:hover { color: #e0e0e0; border-color: #e74c3c; }
|
|
119
118
|
</style>
|
|
120
119
|
`;
|
|
121
120
|
function mapSlider(v) {
|
|
@@ -148,11 +147,13 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
148
147
|
});
|
|
149
148
|
}
|
|
150
149
|
addDevice(device) {
|
|
151
|
-
|
|
150
|
+
const existing = this.shadowRoot.getElementById(`dev-${device.id}`);
|
|
151
|
+
if (existing) {
|
|
152
|
+
this.refreshControls(existing, device);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
152
155
|
const empty = this.container.querySelector(".empty");
|
|
153
156
|
if (empty) empty.remove();
|
|
154
|
-
const mgr = this.manager;
|
|
155
|
-
const cfg = mgr.getDeviceConfig(device.id);
|
|
156
157
|
const panel = document.createElement("details");
|
|
157
158
|
panel.className = "panel";
|
|
158
159
|
panel.id = `dev-${device.id}`;
|
|
@@ -160,72 +161,88 @@ var SatMouseDevices = class extends HTMLElement {
|
|
|
160
161
|
const summary = document.createElement("summary");
|
|
161
162
|
summary.innerHTML = `${device.model ?? device.name}<span class="type">${device.connectionType ?? ""}</span>`;
|
|
162
163
|
panel.appendChild(summary);
|
|
164
|
+
this.refreshControls(panel, device);
|
|
165
|
+
this.container.appendChild(panel);
|
|
166
|
+
}
|
|
167
|
+
refreshControls(panel, device) {
|
|
168
|
+
const old = panel.querySelector(".controls");
|
|
169
|
+
if (old) old.remove();
|
|
170
|
+
const mgr = this.manager;
|
|
171
|
+
const cfg = mgr.getDeviceConfig(device.id);
|
|
163
172
|
const controls = document.createElement("div");
|
|
164
173
|
controls.className = "controls";
|
|
165
|
-
|
|
174
|
+
const routeGroup = document.createElement("div");
|
|
175
|
+
routeGroup.className = "route-group";
|
|
176
|
+
const deviceAxes = device.axes ?? ["tx", "ty", "tz", "rx", "ry", "rz"];
|
|
177
|
+
const routes = this.getRoutes(device.id, deviceAxes);
|
|
178
|
+
for (let i = 0; i < deviceAxes.length; i++) {
|
|
179
|
+
const route = routes[i] ?? { source: deviceAxes[i], target: deviceAxes[i].replace(/[+-]$/, "") };
|
|
166
180
|
const row = document.createElement("div");
|
|
167
|
-
row.className = "
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
mgr.updateDeviceConfig(device.id, {
|
|
176
|
-
sensitivity: { ...mgr.getDeviceConfig(device.id).sensitivity, [type]: v }
|
|
177
|
-
});
|
|
181
|
+
row.className = "route-row";
|
|
182
|
+
const cb = document.createElement("input");
|
|
183
|
+
cb.type = "checkbox";
|
|
184
|
+
cb.checked = route.flip ?? false;
|
|
185
|
+
cb.title = "Flip";
|
|
186
|
+
const routeIndex = i;
|
|
187
|
+
cb.addEventListener("change", () => {
|
|
188
|
+
this.updateRoute(device.id, routeIndex, deviceAxes, { flip: cb.checked });
|
|
178
189
|
});
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
for (const group of [["tx", "ty", "tz"], ["rx", "ry", "rz"]]) {
|
|
184
|
-
const row = document.createElement("div");
|
|
185
|
-
row.className = "flip-row";
|
|
186
|
-
for (const axis of group) {
|
|
187
|
-
const label = document.createElement("label");
|
|
188
|
-
const cb = document.createElement("input");
|
|
189
|
-
cb.type = "checkbox";
|
|
190
|
-
cb.checked = cfg.flip?.[axis] ?? mgr.config.flip[axis];
|
|
191
|
-
cb.addEventListener("change", () => {
|
|
192
|
-
mgr.updateDeviceConfig(device.id, {
|
|
193
|
-
flip: { ...mgr.getDeviceConfig(device.id).flip, [axis]: cb.checked }
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
label.appendChild(cb);
|
|
197
|
-
label.appendChild(document.createTextNode(axis.toUpperCase()));
|
|
198
|
-
row.appendChild(label);
|
|
199
|
-
}
|
|
200
|
-
flipGroup.appendChild(row);
|
|
201
|
-
}
|
|
202
|
-
controls.appendChild(flipGroup);
|
|
203
|
-
const remapGroup = document.createElement("div");
|
|
204
|
-
remapGroup.className = "remap-group";
|
|
205
|
-
const actionMap = cfg.actionMap ?? mgr.config.actionMap;
|
|
206
|
-
for (const action of AXES) {
|
|
207
|
-
const row = document.createElement("div");
|
|
208
|
-
row.className = "remap-row";
|
|
209
|
-
row.innerHTML = `<label>${action.toUpperCase()}</label>`;
|
|
190
|
+
row.appendChild(cb);
|
|
191
|
+
const label = document.createElement("label");
|
|
192
|
+
label.textContent = device.axisLabels?.[i] ?? deviceAxes[i].toUpperCase();
|
|
193
|
+
row.appendChild(label);
|
|
210
194
|
const sel = document.createElement("select");
|
|
211
|
-
for (const
|
|
195
|
+
for (const target of chunkJTG5GEIB_cjs.FULL_AXES) {
|
|
212
196
|
const opt = document.createElement("option");
|
|
213
|
-
opt.value =
|
|
214
|
-
opt.textContent =
|
|
215
|
-
if (
|
|
197
|
+
opt.value = target;
|
|
198
|
+
opt.textContent = target.toUpperCase();
|
|
199
|
+
if (target === route.target) opt.selected = true;
|
|
216
200
|
sel.appendChild(opt);
|
|
217
201
|
}
|
|
218
202
|
sel.addEventListener("change", () => {
|
|
219
|
-
|
|
220
|
-
current[action] = { ...current[action], source: sel.value };
|
|
221
|
-
mgr.updateDeviceConfig(device.id, { actionMap: current });
|
|
203
|
+
this.updateRoute(device.id, routeIndex, deviceAxes, { target: sel.value });
|
|
222
204
|
});
|
|
223
205
|
row.appendChild(sel);
|
|
224
|
-
|
|
206
|
+
routeGroup.appendChild(row);
|
|
225
207
|
}
|
|
226
|
-
controls.appendChild(
|
|
208
|
+
controls.appendChild(routeGroup);
|
|
209
|
+
const sensRow = document.createElement("div");
|
|
210
|
+
sensRow.className = "slider-row";
|
|
211
|
+
const currentScale = cfg.scale ?? mgr.config.scale;
|
|
212
|
+
sensRow.innerHTML = `<label>Scale</label><input type="range" min="0" max="100" value="${Math.round(unmapSlider(currentScale))}"><span>${currentScale.toFixed(4)}</span>`;
|
|
213
|
+
const slider = sensRow.querySelector("input");
|
|
214
|
+
const span = sensRow.querySelector("span");
|
|
215
|
+
slider.addEventListener("input", () => {
|
|
216
|
+
const v = mapSlider(+slider.value);
|
|
217
|
+
span.textContent = v.toFixed(4);
|
|
218
|
+
mgr.updateDeviceConfig(device.id, { scale: v });
|
|
219
|
+
});
|
|
220
|
+
controls.appendChild(sensRow);
|
|
221
|
+
const resetBtn = document.createElement("button");
|
|
222
|
+
resetBtn.className = "reset-btn";
|
|
223
|
+
resetBtn.textContent = "Restore Defaults";
|
|
224
|
+
resetBtn.addEventListener("click", () => {
|
|
225
|
+
mgr.resetDeviceConfig(device.id);
|
|
226
|
+
this.refreshControls(panel, device);
|
|
227
|
+
});
|
|
228
|
+
controls.appendChild(resetBtn);
|
|
227
229
|
panel.appendChild(controls);
|
|
228
|
-
|
|
230
|
+
}
|
|
231
|
+
getRoutes(deviceId, deviceAxes) {
|
|
232
|
+
const mgr = this.manager;
|
|
233
|
+
const devCfg = mgr.config.devices[deviceId];
|
|
234
|
+
if (devCfg?.routes && Array.isArray(devCfg.routes)) return devCfg.routes;
|
|
235
|
+
for (const [pattern, cfg] of Object.entries(mgr.config.devices)) {
|
|
236
|
+
if (pattern.endsWith("*") && deviceId.startsWith(pattern.slice(0, -1))) {
|
|
237
|
+
if (cfg.routes && Array.isArray(cfg.routes)) return cfg.routes;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return chunkJTG5GEIB_cjs.buildRoutes(deviceAxes);
|
|
241
|
+
}
|
|
242
|
+
updateRoute(deviceId, index, deviceAxes, patch) {
|
|
243
|
+
const base = this.getRoutes(deviceId, deviceAxes);
|
|
244
|
+
const updated = base.map((r, j) => j === index ? { ...r, ...patch } : { ...r });
|
|
245
|
+
this.manager.updateDeviceConfig(deviceId, { routes: updated });
|
|
229
246
|
}
|
|
230
247
|
removeDevice(device) {
|
|
231
248
|
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":["DEFAULT_ACTION_MAP","TEMPLATE"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { InputManager } from \"../utils/input-manager.js\";\n\n/**\n * Global registry for SatMouse Web Components.\n *\n * Usage:\n * import { registerSatMouse } from \"@kelnishi/satmouse-client/elements\";\n * registerSatMouse(manager);\n * // All <satmouse-*> elements auto-connect to this manager\n */\n\nlet globalManager: InputManager | null = null;\nconst listeners = new Set<(m: InputManager) => void>();\n\nexport function registerSatMouse(manager: InputManager): void {\n globalManager = manager;\n for (const fn of listeners) fn(manager);\n listeners.clear();\n}\n\nexport function getManager(): InputManager | null {\n return globalManager;\n}\n\nexport function onManagerReady(fn: (m: InputManager) => void): void {\n if (globalManager) fn(globalManager);\n else listeners.add(fn);\n}\n","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { ConnectionState, TransportProtocol } from \"../core/types.js\";\n\nconst TEMPLATE = `\n<style>\n :host { display: inline-flex; align-items: center; gap: 8px; font-family: inherit; font-size: 13px; }\n .dot { width: 8px; height: 8px; border-radius: 50%; background: #e74c3c; transition: background 0.3s; }\n .dot[data-state=\"connected\"] { background: #2ecc71; }\n .dot[data-state=\"connecting\"] { background: #f39c12; }\n .dot[data-state=\"failed\"] { background: #e74c3c; }\n .protocol { color: #7f8c8d; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; }\n .launch { padding: 4px 12px; background: #2980b9; color: #fff; border-radius: 4px; font-size: 11px;\n text-decoration: none; cursor: pointer; border: none; font-family: inherit; display: none; }\n .launch:hover { background: #3498db; }\n</style>\n<span class=\"dot\"></span>\n<span class=\"text\">Disconnected</span>\n<span class=\"protocol\"></span>\n<button class=\"launch\">Launch SatMouse</button>\n`;\n\nexport class SatMouseStatus extends HTMLElement {\n private dot!: HTMLElement;\n private text!: HTMLElement;\n private proto!: HTMLElement;\n private launch!: HTMLButtonElement;\n private disconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = TEMPLATE;\n this.dot = shadow.querySelector(\".dot\")!;\n this.text = shadow.querySelector(\".text\")!;\n this.proto = shadow.querySelector(\".protocol\")!;\n this.launch = shadow.querySelector(\".launch\")!;\n\n this.launch.addEventListener(\"click\", () => {\n // Try the URL scheme — if installed, the OS opens the app\n window.location.href = \"satmouse://launch\";\n // If we're still here after 1s, the scheme wasn't handled\n setTimeout(() => {\n if (!document.hidden) {\n if (confirm(\"SatMouse doesn't appear to be installed. Go to the download page?\")) {\n window.open(\"https://github.com/kelnishi/SatMouse/releases/latest\", \"_blank\", \"noopener\");\n }\n }\n }, 1000);\n });\n }\n\n connectedCallback() {\n // Show launch button if still disconnected after 3s (covers cold page load)\n this.disconnectTimer = setTimeout(() => { this.launch.style.display = \"inline-block\"; }, 3000);\n onManagerReady((manager) => this.bind(manager));\n }\n\n private bind(manager: InputManager): void {\n manager.on(\"stateChange\", (state: ConnectionState, protocol: TransportProtocol) => {\n this.dot.dataset.state = state;\n this.proto.textContent = protocol !== \"none\" ? protocol : \"\";\n\n if (this.disconnectTimer) { clearTimeout(this.disconnectTimer); this.disconnectTimer = null; }\n\n if (state === \"connected\") {\n this.text.textContent = \"Connected\";\n this.launch.style.display = \"none\";\n } else if (state === \"connecting\") {\n this.text.textContent = \"Connecting...\";\n this.launch.style.display = \"none\";\n } else if (state === \"failed\") {\n this.text.textContent = \"Not running\";\n this.launch.style.display = \"inline-block\";\n } else {\n this.text.textContent = \"Disconnected\";\n this.launch.style.display = \"none\";\n }\n });\n }\n}\n\ncustomElements.define(\"satmouse-status\", SatMouseStatus);\n","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { DeviceInfo } from \"../core/types.js\";\nimport type { InputAxis } 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":["FULL_AXES","buildRoutes","TEMPLATE"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { InputManager } from \"../utils/input-manager.js\";\n\n/**\n * Global registry for SatMouse Web Components.\n *\n * Usage:\n * import { registerSatMouse } from \"@kelnishi/satmouse-client/elements\";\n * registerSatMouse(manager);\n * // All <satmouse-*> elements auto-connect to this manager\n */\n\nlet globalManager: InputManager | null = null;\nconst listeners = new Set<(m: InputManager) => void>();\n\nexport function registerSatMouse(manager: InputManager): void {\n globalManager = manager;\n for (const fn of listeners) fn(manager);\n listeners.clear();\n}\n\nexport function getManager(): InputManager | null {\n return globalManager;\n}\n\nexport function onManagerReady(fn: (m: InputManager) => void): void {\n if (globalManager) fn(globalManager);\n else listeners.add(fn);\n}\n","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { ConnectionState, TransportProtocol } from \"../core/types.js\";\n\nconst TEMPLATE = `\n<style>\n :host { display: inline-flex; align-items: center; gap: 8px; font-family: inherit; font-size: 13px; }\n .dot { width: 8px; height: 8px; border-radius: 50%; background: #e74c3c; transition: background 0.3s; }\n .dot[data-state=\"connected\"] { background: #2ecc71; }\n .dot[data-state=\"connecting\"] { background: #f39c12; }\n .dot[data-state=\"failed\"] { background: #e74c3c; }\n .protocol { color: #7f8c8d; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; }\n .launch { padding: 4px 12px; background: #2980b9; color: #fff; border-radius: 4px; font-size: 11px;\n text-decoration: none; cursor: pointer; border: none; font-family: inherit; display: none; }\n .launch:hover { background: #3498db; }\n</style>\n<span class=\"dot\"></span>\n<span class=\"text\">Disconnected</span>\n<span class=\"protocol\"></span>\n<button class=\"launch\">Launch SatMouse</button>\n`;\n\nexport class SatMouseStatus extends HTMLElement {\n private dot!: HTMLElement;\n private text!: HTMLElement;\n private proto!: HTMLElement;\n private launch!: HTMLButtonElement;\n private disconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = TEMPLATE;\n this.dot = shadow.querySelector(\".dot\")!;\n this.text = shadow.querySelector(\".text\")!;\n this.proto = shadow.querySelector(\".protocol\")!;\n this.launch = shadow.querySelector(\".launch\")!;\n\n this.launch.addEventListener(\"click\", () => {\n // Try the URL scheme — if installed, the OS opens the app\n window.location.href = \"satmouse://launch\";\n // If we're still here after 1s, the scheme wasn't handled\n setTimeout(() => {\n if (!document.hidden) {\n if (confirm(\"SatMouse doesn't appear to be installed. Go to the download page?\")) {\n window.open(\"https://github.com/kelnishi/SatMouse/releases/latest\", \"_blank\", \"noopener\");\n }\n }\n }, 1000);\n });\n }\n\n connectedCallback() {\n // Show launch button if still disconnected after 3s (covers cold page load)\n this.disconnectTimer = setTimeout(() => { this.launch.style.display = \"inline-block\"; }, 3000);\n onManagerReady((manager) => this.bind(manager));\n }\n\n private bind(manager: InputManager): void {\n manager.on(\"stateChange\", (state: ConnectionState, protocol: TransportProtocol) => {\n this.dot.dataset.state = state;\n this.proto.textContent = protocol !== \"none\" ? protocol : \"\";\n\n if (this.disconnectTimer) { clearTimeout(this.disconnectTimer); this.disconnectTimer = null; }\n\n if (state === \"connected\") {\n this.text.textContent = \"Connected\";\n this.launch.style.display = \"none\";\n } else if (state === \"connecting\") {\n this.text.textContent = \"Connecting...\";\n this.launch.style.display = \"none\";\n } else if (state === \"failed\") {\n this.text.textContent = \"Not running\";\n this.launch.style.display = \"inline-block\";\n } else {\n this.text.textContent = \"Disconnected\";\n this.launch.style.display = \"none\";\n }\n });\n }\n}\n\ncustomElements.define(\"satmouse-status\", SatMouseStatus);\n","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { DeviceInfo } from \"../core/types.js\";\nimport type { InputAxis, AxisRoute } from \"../utils/action-map.js\";\nimport { FULL_AXES, buildRoutes, DEFAULT_ROUTES } from \"../utils/action-map.js\";\n\nconst STYLES = `\n<style>\n :host { display: block; font-family: inherit; font-size: 12px; }\n .panel { background: #0f3460; border: 1px solid #1a4a8a; border-radius: 6px; padding: 10px; margin-bottom: 8px; }\n summary { cursor: pointer; font-weight: 600; color: #e0e0e0; font-size: 13px; }\n .type { font-size: 10px; color: #7f8c8d; text-transform: uppercase; margin-left: 6px; }\n .controls { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }\n .slider-row { display: flex; align-items: center; gap: 6px; }\n .slider-row label { color: #7f8c8d; font-weight: 600; width: 38px; flex-shrink: 0; }\n .slider-row input[type=\"range\"] { flex: 1; min-width: 0; height: 4px; accent-color: #3498db; }\n .slider-row span { color: #7f8c8d; font-family: monospace; font-size: 10px; min-width: 44px; text-align: right; }\n .route-group { display: flex; flex-wrap: wrap; gap: 4px 12px; }\n .route-row { display: flex; gap: 4px; align-items: center; }\n .route-row label { color: #7f8c8d; white-space: nowrap; }\n .route-row select { background: #16213e; color: #e0e0e0; border: 1px solid #1a4a8a; border-radius: 3px;\n font-size: 11px; padding: 1px 4px; }\n .route-row input[type=\"checkbox\"] { accent-color: #e74c3c; margin: 0; }\n .empty { color: #7f8c8d; font-style: italic; }\n .reset-btn { background: none; border: 1px solid #1a4a8a; border-radius: 3px; color: #7f8c8d;\n font-size: 11px; padding: 3px 8px; cursor: pointer; margin-top: 4px; }\n .reset-btn:hover { color: #e0e0e0; border-color: #e74c3c; }\n</style>\n`;\n\nfunction mapSlider(v: number): number { return 0.0001 * Math.pow(500, v / 100); }\nfunction unmapSlider(v: number): number { return (100 * Math.log(v / 0.0001)) / Math.log(500); }\n\nexport class SatMouseDevices extends HTMLElement {\n private manager: InputManager | null = null;\n private container!: HTMLElement;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = STYLES + `<div class=\"container\"><span class=\"empty\">No devices</span></div>`;\n this.container = shadow.querySelector(\".container\")!;\n }\n\n connectedCallback() {\n onManagerReady((manager) => {\n this.manager = manager;\n manager.on(\"deviceStatus\", (event, device) => {\n if (event === \"connected\") this.addDevice(device);\n else this.removeDevice(device);\n });\n manager.on(\"stateChange\", (state) => {\n if (state === \"connected\") {\n manager.fetchDeviceInfo().then((devices) => devices.forEach((d) => this.addDevice(d)));\n }\n });\n });\n }\n\n private addDevice(device: DeviceInfo): void {\n const existing = this.shadowRoot!.getElementById(`dev-${device.id}`);\n if (existing) {\n this.refreshControls(existing as HTMLDetailsElement, device);\n return;\n }\n const empty = this.container.querySelector(\".empty\");\n if (empty) empty.remove();\n\n const panel = document.createElement(\"details\");\n panel.className = \"panel\";\n panel.id = `dev-${device.id}`;\n panel.open = true;\n\n const summary = document.createElement(\"summary\");\n summary.innerHTML = `${device.model ?? device.name}<span class=\"type\">${device.connectionType ?? \"\"}</span>`;\n panel.appendChild(summary);\n\n this.refreshControls(panel, device);\n this.container.appendChild(panel);\n }\n\n private refreshControls(panel: HTMLDetailsElement, device: DeviceInfo): void {\n const old = panel.querySelector(\".controls\");\n if (old) old.remove();\n\n const mgr = this.manager!;\n const cfg = mgr.getDeviceConfig(device.id);\n\n const controls = document.createElement(\"div\");\n controls.className = \"controls\";\n\n // Axis routes — one row per device input: [flip] [label] → [target dropdown] [scale slider]\n const routeGroup = document.createElement(\"div\");\n routeGroup.className = \"route-group\";\n const deviceAxes = device.axes ?? [\"tx\", \"ty\", \"tz\", \"rx\", \"ry\", \"rz\"];\n const routes = this.getRoutes(device.id, deviceAxes);\n\n for (let i = 0; i < deviceAxes.length; i++) {\n const route = routes[i] ?? { source: deviceAxes[i] as InputAxis, target: deviceAxes[i].replace(/[+-]$/, \"\") as InputAxis };\n const row = document.createElement(\"div\");\n row.className = \"route-row\";\n\n // Flip checkbox\n const cb = document.createElement(\"input\");\n cb.type = \"checkbox\";\n cb.checked = route.flip ?? false;\n cb.title = \"Flip\";\n const routeIndex = i;\n cb.addEventListener(\"change\", () => {\n this.updateRoute(device.id, routeIndex, deviceAxes, { flip: cb.checked });\n });\n row.appendChild(cb);\n\n // Label (device input name)\n const label = document.createElement(\"label\");\n label.textContent = device.axisLabels?.[i] ?? deviceAxes[i].toUpperCase();\n row.appendChild(label);\n\n // Target dropdown\n const sel = document.createElement(\"select\");\n for (const target of FULL_AXES) {\n const opt = document.createElement(\"option\");\n opt.value = target;\n opt.textContent = target.toUpperCase();\n if (target === route.target) opt.selected = true;\n sel.appendChild(opt);\n }\n sel.addEventListener(\"change\", () => {\n this.updateRoute(device.id, routeIndex, deviceAxes, { target: sel.value as InputAxis });\n });\n row.appendChild(sel);\n\n routeGroup.appendChild(row);\n }\n controls.appendChild(routeGroup);\n\n // Scale slider\n const sensRow = document.createElement(\"div\");\n sensRow.className = \"slider-row\";\n const currentScale = cfg.scale ?? mgr.config.scale;\n sensRow.innerHTML = `<label>Scale</label>` +\n `<input type=\"range\" min=\"0\" max=\"100\" value=\"${Math.round(unmapSlider(currentScale))}\">` +\n `<span>${currentScale.toFixed(4)}</span>`;\n const slider = sensRow.querySelector(\"input\")! as HTMLInputElement;\n const span = sensRow.querySelector(\"span\")!;\n slider.addEventListener(\"input\", () => {\n const v = mapSlider(+slider.value);\n span.textContent = v.toFixed(4);\n mgr.updateDeviceConfig(device.id, { scale: v });\n });\n controls.appendChild(sensRow);\n\n // Reset button\n const resetBtn = document.createElement(\"button\");\n resetBtn.className = \"reset-btn\";\n resetBtn.textContent = \"Restore Defaults\";\n resetBtn.addEventListener(\"click\", () => {\n mgr.resetDeviceConfig(device.id);\n this.refreshControls(panel, device);\n });\n controls.appendChild(resetBtn);\n\n panel.appendChild(controls);\n }\n\n private getRoutes(deviceId: string, deviceAxes: string[]): AxisRoute[] {\n // Only use saved device config routes — not the global fallback\n const mgr = this.manager!;\n const devCfg = mgr.config.devices[deviceId];\n if (devCfg?.routes && Array.isArray(devCfg.routes)) return devCfg.routes;\n\n // Check pattern matches\n for (const [pattern, cfg] of Object.entries(mgr.config.devices)) {\n if (pattern.endsWith(\"*\") && deviceId.startsWith(pattern.slice(0, -1))) {\n if (cfg.routes && Array.isArray(cfg.routes)) return cfg.routes;\n }\n }\n\n // Build from device axes\n return buildRoutes(deviceAxes);\n }\n\n private updateRoute(deviceId: string, index: number, deviceAxes: string[], patch: Partial<AxisRoute>): void {\n const base = this.getRoutes(deviceId, deviceAxes);\n const updated = base.map((r, j) => j === index ? { ...r, ...patch } : { ...r });\n this.manager!.updateDeviceConfig(deviceId, { routes: updated });\n }\n\n private removeDevice(device: DeviceInfo): void {\n this.shadowRoot!.getElementById(`dev-${device.id}`)?.remove();\n if (this.container.children.length === 0) {\n this.container.innerHTML = `<span class=\"empty\">No devices</span>`;\n }\n }\n}\n\ncustomElements.define(\"satmouse-devices\", SatMouseDevices);\n","import { onManagerReady } from \"./registry.js\";\nimport type { InputManager } from \"../utils/input-manager.js\";\nimport type { SpatialData, ConnectionState, TransportProtocol } from \"../core/types.js\";\n\nconst TEMPLATE = `\n<style>\n :host { display: block; font-family: monospace; font-size: 12px; }\n .row { display: flex; justify-content: space-between; padding: 2px 0; }\n .label { color: #7f8c8d; font-weight: 600; width: 28px; }\n .value { color: #3498db; text-align: right; min-width: 50px; }\n .meta { color: #7f8c8d; font-size: 11px; padding: 2px 0; }\n</style>\n<div class=\"meta\"><span class=\"state\">Disconnected</span> · <span class=\"protocol\"></span> · <span class=\"fps\">0</span> fps</div>\n<div class=\"row\"><span class=\"label\">TX</span><span class=\"value\" id=\"tx\">0</span></div>\n<div class=\"row\"><span class=\"label\">TY</span><span class=\"value\" id=\"ty\">0</span></div>\n<div class=\"row\"><span class=\"label\">TZ</span><span class=\"value\" id=\"tz\">0</span></div>\n<div class=\"row\"><span class=\"label\">RX</span><span class=\"value\" id=\"rx\">0</span></div>\n<div class=\"row\"><span class=\"label\">RY</span><span class=\"value\" id=\"ry\">0</span></div>\n<div class=\"row\"><span class=\"label\">RZ</span><span class=\"value\" id=\"rz\">0</span></div>\n`;\n\nexport class SatMouseDebug extends HTMLElement {\n private els: Record<string, HTMLElement> = {};\n private frameCount = 0;\n\n constructor() {\n super();\n const shadow = this.attachShadow({ mode: \"open\" });\n shadow.innerHTML = TEMPLATE;\n for (const id of [\"tx\", \"ty\", \"tz\", \"rx\", \"ry\", \"rz\"]) {\n this.els[id] = shadow.getElementById(id)!;\n }\n this.els.state = shadow.querySelector(\".state\")!;\n this.els.protocol = shadow.querySelector(\".protocol\")!;\n this.els.fps = shadow.querySelector(\".fps\")!;\n }\n\n connectedCallback() {\n onManagerReady((manager) => this.bind(manager));\n }\n\n private bind(manager: InputManager): void {\n manager.on(\"rawSpatialData\", (data: SpatialData) => {\n this.frameCount++;\n this.els.tx.textContent = String(Math.round(data.translation.x));\n this.els.ty.textContent = String(Math.round(data.translation.y));\n this.els.tz.textContent = String(Math.round(data.translation.z));\n this.els.rx.textContent = String(Math.round(data.rotation.x));\n this.els.ry.textContent = String(Math.round(data.rotation.y));\n this.els.rz.textContent = String(Math.round(data.rotation.z));\n });\n\n manager.on(\"stateChange\", (state: ConnectionState, protocol: TransportProtocol) => {\n this.els.state.textContent = state;\n this.els.protocol.textContent = protocol !== \"none\" ? protocol : \"\";\n });\n\n setInterval(() => {\n this.els.fps.textContent = String(this.frameCount);\n this.frameCount = 0;\n }, 1000);\n }\n}\n\ncustomElements.define(\"satmouse-debug\", SatMouseDebug);\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { InputManager } from '../utils/index.cjs';
|
|
2
|
-
import '../connection-
|
|
2
|
+
import '../connection-DQxI5qib.cjs';
|
|
3
3
|
|
|
4
4
|
declare class SatMouseStatus extends HTMLElement {
|
|
5
5
|
private dot;
|
|
@@ -18,6 +18,9 @@ declare class SatMouseDevices extends HTMLElement {
|
|
|
18
18
|
constructor();
|
|
19
19
|
connectedCallback(): void;
|
|
20
20
|
private addDevice;
|
|
21
|
+
private refreshControls;
|
|
22
|
+
private getRoutes;
|
|
23
|
+
private updateRoute;
|
|
21
24
|
private removeDevice;
|
|
22
25
|
}
|
|
23
26
|
|
package/dist/elements/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { InputManager } from '../utils/index.js';
|
|
2
|
-
import '../connection-
|
|
2
|
+
import '../connection-DQxI5qib.js';
|
|
3
3
|
|
|
4
4
|
declare class SatMouseStatus extends HTMLElement {
|
|
5
5
|
private dot;
|
|
@@ -18,6 +18,9 @@ declare class SatMouseDevices extends HTMLElement {
|
|
|
18
18
|
constructor();
|
|
19
19
|
connectedCallback(): void;
|
|
20
20
|
private addDevice;
|
|
21
|
+
private refreshControls;
|
|
22
|
+
private getRoutes;
|
|
23
|
+
private updateRoute;
|
|
21
24
|
private removeDevice;
|
|
22
25
|
}
|
|
23
26
|
|