@edv4h/usketch-plugin-debug-hud 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/components/fps-graph.d.ts +7 -0
- package/dist/components/fps-graph.d.ts.map +1 -0
- package/dist/components/fps-graph.js +61 -0
- package/dist/components/fps-graph.js.map +1 -0
- package/dist/debug-hud.d.ts +21 -0
- package/dist/debug-hud.d.ts.map +1 -0
- package/dist/debug-hud.js +69 -0
- package/dist/debug-hud.js.map +1 -0
- package/dist/event-logger.d.ts +18 -0
- package/dist/event-logger.d.ts.map +1 -0
- package/dist/event-logger.js +38 -0
- package/dist/event-logger.js.map +1 -0
- package/dist/fps-counter.d.ts +15 -0
- package/dist/fps-counter.d.ts.map +1 -0
- package/dist/fps-counter.js +46 -0
- package/dist/fps-counter.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/overlays/minimap.d.ts +9 -0
- package/dist/overlays/minimap.d.ts.map +1 -0
- package/dist/overlays/minimap.js +53 -0
- package/dist/overlays/minimap.js.map +1 -0
- package/dist/overlays/shape-bounds-overlay.d.ts +8 -0
- package/dist/overlays/shape-bounds-overlay.d.ts.map +1 -0
- package/dist/overlays/shape-bounds-overlay.js +38 -0
- package/dist/overlays/shape-bounds-overlay.js.map +1 -0
- package/dist/panels/events-panel.d.ts +7 -0
- package/dist/panels/events-panel.d.ts.map +1 -0
- package/dist/panels/events-panel.js +59 -0
- package/dist/panels/events-panel.js.map +1 -0
- package/dist/panels/general-panel.d.ts +20 -0
- package/dist/panels/general-panel.d.ts.map +1 -0
- package/dist/panels/general-panel.js +75 -0
- package/dist/panels/general-panel.js.map +1 -0
- package/dist/panels/shapes-panel.d.ts +11 -0
- package/dist/panels/shapes-panel.d.ts.map +1 -0
- package/dist/panels/shapes-panel.js +101 -0
- package/dist/panels/shapes-panel.js.map +1 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +61 -0
- package/dist/plugin.js.map +1 -0
- package/dist/pointer-tracker.d.ts +16 -0
- package/dist/pointer-tracker.d.ts.map +1 -0
- package/dist/pointer-tracker.js +33 -0
- package/dist/pointer-tracker.js.map +1 -0
- package/dist/styles.d.ts +24 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +77 -0
- package/dist/styles.js.map +1 -0
- package/dist/sync-status-types.d.ts +16 -0
- package/dist/sync-status-types.d.ts.map +1 -0
- package/dist/sync-status-types.js +6 -0
- package/dist/sync-status-types.js.map +1 -0
- package/package.json +48 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 EdV4H
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FpsCounter } from "../fps-counter.js";
|
|
2
|
+
interface FpsGraphProps {
|
|
3
|
+
fpsCounter: FpsCounter;
|
|
4
|
+
}
|
|
5
|
+
export declare function FpsGraph({ fpsCounter }: FpsGraphProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=fps-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fps-graph.d.ts","sourceRoot":"","sources":["../../src/components/fps-graph.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,UAAU,aAAa;IACtB,UAAU,EAAE,UAAU,CAAC;CACvB;AAYD,wBAAgB,QAAQ,CAAC,EAAE,UAAU,EAAE,EAAE,aAAa,2CAyDrD"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
3
|
+
import { FPS_GREEN, FPS_RED, FPS_YELLOW } from "../styles.js";
|
|
4
|
+
const WIDTH = 120;
|
|
5
|
+
const HEIGHT = 32;
|
|
6
|
+
const MAX_FPS = 80;
|
|
7
|
+
function colorForFps(fps) {
|
|
8
|
+
if (fps >= 50)
|
|
9
|
+
return FPS_GREEN;
|
|
10
|
+
if (fps >= 30)
|
|
11
|
+
return FPS_YELLOW;
|
|
12
|
+
return FPS_RED;
|
|
13
|
+
}
|
|
14
|
+
export function FpsGraph({ fpsCounter }) {
|
|
15
|
+
const canvasRef = useRef(null);
|
|
16
|
+
const draw = useCallback(() => {
|
|
17
|
+
const canvas = canvasRef.current;
|
|
18
|
+
if (!canvas)
|
|
19
|
+
return;
|
|
20
|
+
const ctx = canvas.getContext("2d");
|
|
21
|
+
if (!ctx)
|
|
22
|
+
return;
|
|
23
|
+
const history = fpsCounter.getHistory();
|
|
24
|
+
ctx.clearRect(0, 0, WIDTH, HEIGHT);
|
|
25
|
+
if (history.length < 2)
|
|
26
|
+
return;
|
|
27
|
+
// Draw 60fps reference line
|
|
28
|
+
const y60 = HEIGHT - (60 / MAX_FPS) * HEIGHT;
|
|
29
|
+
ctx.strokeStyle = "rgba(255, 255, 255, 0.1)";
|
|
30
|
+
ctx.lineWidth = 1;
|
|
31
|
+
ctx.setLineDash([2, 2]);
|
|
32
|
+
ctx.beginPath();
|
|
33
|
+
ctx.moveTo(0, y60);
|
|
34
|
+
ctx.lineTo(WIDTH, y60);
|
|
35
|
+
ctx.stroke();
|
|
36
|
+
ctx.setLineDash([]);
|
|
37
|
+
// Draw FPS line
|
|
38
|
+
ctx.lineWidth = 1.5;
|
|
39
|
+
ctx.beginPath();
|
|
40
|
+
const step = WIDTH / (60 - 1);
|
|
41
|
+
const offset = (60 - history.length) * step;
|
|
42
|
+
for (let i = 0; i < history.length; i++) {
|
|
43
|
+
const x = offset + i * step;
|
|
44
|
+
const y = HEIGHT - (Math.min(history[i], MAX_FPS) / MAX_FPS) * HEIGHT;
|
|
45
|
+
if (i === 0)
|
|
46
|
+
ctx.moveTo(x, y);
|
|
47
|
+
else
|
|
48
|
+
ctx.lineTo(x, y);
|
|
49
|
+
}
|
|
50
|
+
const lastFps = history[history.length - 1];
|
|
51
|
+
ctx.strokeStyle = colorForFps(lastFps);
|
|
52
|
+
ctx.stroke();
|
|
53
|
+
}, [fpsCounter]);
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const unsub = fpsCounter.subscribe(draw);
|
|
56
|
+
draw();
|
|
57
|
+
return unsub;
|
|
58
|
+
}, [fpsCounter, draw]);
|
|
59
|
+
return (_jsx("canvas", { ref: canvasRef, width: WIDTH, height: HEIGHT, style: { width: WIDTH, height: HEIGHT, display: "block", marginTop: 2 } }));
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=fps-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fps-graph.js","sourceRoot":"","sources":["../../src/components/fps-graph.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BoardStore, CommandRegistry, EventBus, LayerManager, LayerRenderContext, ShapeRegistry, ToolRegistry } from "@edv4h/usketch-shared";
|
|
2
|
+
import type { EventLogger } from "./event-logger.js";
|
|
3
|
+
import type { FpsCounter } from "./fps-counter.js";
|
|
4
|
+
import type { PointerTracker } from "./pointer-tracker.js";
|
|
5
|
+
import type { SyncStatusTrackerLike } from "./sync-status-types.js";
|
|
6
|
+
interface DebugHudProps {
|
|
7
|
+
store: BoardStore;
|
|
8
|
+
fpsCounter: FpsCounter;
|
|
9
|
+
eventLogger: EventLogger;
|
|
10
|
+
pointerTracker: PointerTracker;
|
|
11
|
+
commands: CommandRegistry;
|
|
12
|
+
tools: ToolRegistry;
|
|
13
|
+
layers: LayerManager;
|
|
14
|
+
shapes: ShapeRegistry;
|
|
15
|
+
syncStatus?: SyncStatusTrackerLike;
|
|
16
|
+
events: EventBus;
|
|
17
|
+
ctx: LayerRenderContext;
|
|
18
|
+
}
|
|
19
|
+
export declare function DebugHud({ store, fpsCounter, eventLogger, pointerTracker, commands, tools, layers, shapes, syncStatus, events, ctx, }: DebugHudProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=debug-hud.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-hud.d.ts","sourceRoot":"","sources":["../src/debug-hud.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EACV,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAMnD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAEpE,UAAU,aAAa;IACtB,KAAK,EAAE,UAAU,CAAC;IAClB,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,MAAM,EAAE,QAAQ,CAAC;IACjB,GAAG,EAAE,kBAAkB,CAAC;CACxB;AAQD,wBAAgB,QAAQ,CAAC,EACxB,KAAK,EACL,UAAU,EACV,WAAW,EACX,cAAc,EACd,QAAQ,EACR,KAAK,EACL,MAAM,EACN,MAAM,EACN,UAAU,EACV,MAAM,EACN,GAAG,GACH,EAAE,aAAa,2CAmGf"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
import { Minimap } from "./overlays/minimap.js";
|
|
4
|
+
import { ShapeBoundsOverlay } from "./overlays/shape-bounds-overlay.js";
|
|
5
|
+
import { EventsPanel } from "./panels/events-panel.js";
|
|
6
|
+
import { GeneralPanel } from "./panels/general-panel.js";
|
|
7
|
+
import { ShapesPanel } from "./panels/shapes-panel.js";
|
|
8
|
+
import { FONT_FAMILY, TEXT_MUTED } from "./styles.js";
|
|
9
|
+
function isEditableTarget(target) {
|
|
10
|
+
if (!(target instanceof HTMLElement))
|
|
11
|
+
return false;
|
|
12
|
+
const tag = target.tagName;
|
|
13
|
+
return tag === "INPUT" || tag === "TEXTAREA" || target.isContentEditable;
|
|
14
|
+
}
|
|
15
|
+
export function DebugHud({ store, fpsCounter, eventLogger, pointerTracker, commands, tools, layers, shapes, syncStatus, events, ctx, }) {
|
|
16
|
+
const STORAGE_KEY = "usketch-debug-hud-visible";
|
|
17
|
+
const [visible, setVisible] = useState(() => {
|
|
18
|
+
try {
|
|
19
|
+
return localStorage.getItem(STORAGE_KEY) === "1";
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
const [hoveredShapeId, setHoveredShapeId] = useState(null);
|
|
26
|
+
// Keyboard shortcut (backtick)
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
const handler = (e) => {
|
|
29
|
+
if (isEditableTarget(e.target))
|
|
30
|
+
return;
|
|
31
|
+
if (e.key === "`" || e.code === "Backquote") {
|
|
32
|
+
if (!e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey) {
|
|
33
|
+
e.preventDefault();
|
|
34
|
+
setVisible((v) => {
|
|
35
|
+
const next = !v;
|
|
36
|
+
try {
|
|
37
|
+
localStorage.setItem(STORAGE_KEY, next ? "1" : "0");
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// ignore
|
|
41
|
+
}
|
|
42
|
+
return next;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
window.addEventListener("keydown", handler);
|
|
48
|
+
return () => window.removeEventListener("keydown", handler);
|
|
49
|
+
}, []);
|
|
50
|
+
const { viewport, shapes: shapeMap, selection } = ctx;
|
|
51
|
+
const activeToolId = store.getActiveToolId();
|
|
52
|
+
const hoveredShape = hoveredShapeId ? shapeMap.get(hoveredShapeId) : undefined;
|
|
53
|
+
// Shortcut hint — bottom-center (always visible)
|
|
54
|
+
const hint = (_jsxs("div", { style: {
|
|
55
|
+
position: "absolute",
|
|
56
|
+
bottom: 8,
|
|
57
|
+
left: "50%",
|
|
58
|
+
transform: "translateX(-50%)",
|
|
59
|
+
color: TEXT_MUTED,
|
|
60
|
+
fontSize: 10,
|
|
61
|
+
fontFamily: FONT_FAMILY,
|
|
62
|
+
pointerEvents: "none",
|
|
63
|
+
}, children: ["Debug HUD \u00B7 press ", _jsx("kbd", { style: { color: "#e0e0e0" }, children: "`" }), " to ", visible ? "close" : "open"] }));
|
|
64
|
+
if (!visible) {
|
|
65
|
+
return hint;
|
|
66
|
+
}
|
|
67
|
+
return (_jsxs(_Fragment, { children: [hint, _jsx(ShapeBoundsOverlay, { shape: hoveredShape, store: store }), _jsx(GeneralPanel, { store: store, fpsCounter: fpsCounter, pointerTracker: pointerTracker, commands: commands, tools: tools, layers: layers, shapes: shapes, syncStatus: syncStatus, events: events, viewport: viewport, activeToolId: activeToolId }), _jsx(ShapesPanel, { store: store, commands: commands, shapes: shapeMap, selection: selection, onHoverShape: setHoveredShapeId }), _jsx(EventsPanel, { eventLogger: eventLogger }), _jsx(Minimap, { shapes: shapeMap, viewport: viewport, selection: selection })] }));
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=debug-hud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-hud.js","sourceRoot":"","sources":["../src/debug-hud.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface EventLogEntry {
|
|
2
|
+
event: string;
|
|
3
|
+
timestamp: number;
|
|
4
|
+
count: number;
|
|
5
|
+
}
|
|
6
|
+
export declare class EventLogger {
|
|
7
|
+
private entries;
|
|
8
|
+
private listeners;
|
|
9
|
+
private snapshotCache;
|
|
10
|
+
push(entry: {
|
|
11
|
+
event: string;
|
|
12
|
+
timestamp: number;
|
|
13
|
+
}): void;
|
|
14
|
+
clear(): void;
|
|
15
|
+
subscribe(listener: () => void): () => void;
|
|
16
|
+
getSnapshot(): readonly EventLogEntry[];
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=event-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-logger.d.ts","sourceRoot":"","sources":["../src/event-logger.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACd;AAID,qBAAa,WAAW;IACvB,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,aAAa,CAAgC;IAErD,IAAI,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAiBvD,KAAK,IAAI,IAAI;IAQb,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAK3C,WAAW,IAAI,SAAS,aAAa,EAAE;CAGvC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
const MAX_ENTRIES = 200;
|
|
2
|
+
export class EventLogger {
|
|
3
|
+
entries = [];
|
|
4
|
+
listeners = new Set();
|
|
5
|
+
snapshotCache = [];
|
|
6
|
+
push(entry) {
|
|
7
|
+
const last = this.entries[this.entries.length - 1];
|
|
8
|
+
if (last && last.event === entry.event) {
|
|
9
|
+
last.count++;
|
|
10
|
+
last.timestamp = entry.timestamp;
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
this.entries.push({ ...entry, count: 1 });
|
|
14
|
+
if (this.entries.length > MAX_ENTRIES) {
|
|
15
|
+
this.entries.shift();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
this.snapshotCache = [...this.entries];
|
|
19
|
+
for (const listener of this.listeners) {
|
|
20
|
+
listener();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
clear() {
|
|
24
|
+
this.entries = [];
|
|
25
|
+
this.snapshotCache = [];
|
|
26
|
+
for (const listener of this.listeners) {
|
|
27
|
+
listener();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
subscribe(listener) {
|
|
31
|
+
this.listeners.add(listener);
|
|
32
|
+
return () => this.listeners.delete(listener);
|
|
33
|
+
}
|
|
34
|
+
getSnapshot() {
|
|
35
|
+
return this.snapshotCache;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=event-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-logger.js","sourceRoot":"","sources":["../src/event-logger.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB,MAAM,OAAO,WAAW;IACf,OAAO,GAAoB,EAAE,CAAC;IAC9B,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IAClC,aAAa,GAA6B,EAAE,CAAC;IAErD,IAAI,CAAC,KAA2C;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACnD,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC;YACxC,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;QAClC,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;YAC1C,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;gBACvC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YACtB,CAAC;QACF,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QACvC,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACvC,QAAQ,EAAE,CAAC;QACZ,CAAC;IACF,CAAC;IAED,KAAK;QACJ,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACvC,QAAQ,EAAE,CAAC;QACZ,CAAC;IACF,CAAC;IAED,SAAS,CAAC,QAAoB;QAC7B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED,WAAW;QACV,OAAO,IAAI,CAAC,aAAa,CAAC;IAC3B,CAAC;CACD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class FpsCounter {
|
|
2
|
+
private frameCount;
|
|
3
|
+
private lastTime;
|
|
4
|
+
private currentFps;
|
|
5
|
+
private rafId;
|
|
6
|
+
private listeners;
|
|
7
|
+
private historyBuffer;
|
|
8
|
+
start(): void;
|
|
9
|
+
stop(): void;
|
|
10
|
+
subscribe(listener: () => void): () => void;
|
|
11
|
+
getSnapshot(): number;
|
|
12
|
+
getHistory(): readonly number[];
|
|
13
|
+
private tick;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=fps-counter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fps-counter.d.ts","sourceRoot":"","sources":["../src/fps-counter.ts"],"names":[],"mappings":"AAEA,qBAAa,UAAU;IACtB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,aAAa,CAAgB;IAErC,KAAK,IAAI,IAAI;IAMb,IAAI,IAAI,IAAI;IAIZ,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAK3C,WAAW,IAAI,MAAM;IAIrB,UAAU,IAAI,SAAS,MAAM,EAAE;IAI/B,OAAO,CAAC,IAAI,CAiBV;CACF"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const HISTORY_SIZE = 60;
|
|
2
|
+
export class FpsCounter {
|
|
3
|
+
frameCount = 0;
|
|
4
|
+
lastTime = 0;
|
|
5
|
+
currentFps = 0;
|
|
6
|
+
rafId = 0;
|
|
7
|
+
listeners = new Set();
|
|
8
|
+
historyBuffer = [];
|
|
9
|
+
start() {
|
|
10
|
+
this.lastTime = performance.now();
|
|
11
|
+
this.frameCount = 0;
|
|
12
|
+
this.tick();
|
|
13
|
+
}
|
|
14
|
+
stop() {
|
|
15
|
+
cancelAnimationFrame(this.rafId);
|
|
16
|
+
}
|
|
17
|
+
subscribe(listener) {
|
|
18
|
+
this.listeners.add(listener);
|
|
19
|
+
return () => this.listeners.delete(listener);
|
|
20
|
+
}
|
|
21
|
+
getSnapshot() {
|
|
22
|
+
return this.currentFps;
|
|
23
|
+
}
|
|
24
|
+
getHistory() {
|
|
25
|
+
return this.historyBuffer;
|
|
26
|
+
}
|
|
27
|
+
tick = () => {
|
|
28
|
+
this.rafId = requestAnimationFrame(this.tick);
|
|
29
|
+
this.frameCount++;
|
|
30
|
+
const now = performance.now();
|
|
31
|
+
const elapsed = now - this.lastTime;
|
|
32
|
+
if (elapsed >= 1000) {
|
|
33
|
+
this.currentFps = Math.round((this.frameCount * 1000) / elapsed);
|
|
34
|
+
this.frameCount = 0;
|
|
35
|
+
this.lastTime = now;
|
|
36
|
+
this.historyBuffer.push(this.currentFps);
|
|
37
|
+
if (this.historyBuffer.length > HISTORY_SIZE) {
|
|
38
|
+
this.historyBuffer.shift();
|
|
39
|
+
}
|
|
40
|
+
for (const listener of this.listeners) {
|
|
41
|
+
listener();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=fps-counter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fps-counter.js","sourceRoot":"","sources":["../src/fps-counter.ts"],"names":[],"mappings":"AAAA,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB,MAAM,OAAO,UAAU;IACd,UAAU,GAAG,CAAC,CAAC;IACf,QAAQ,GAAG,CAAC,CAAC;IACb,UAAU,GAAG,CAAC,CAAC;IACf,KAAK,GAAG,CAAC,CAAC;IACV,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IAClC,aAAa,GAAa,EAAE,CAAC;IAErC,KAAK;QACJ,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAClC,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI,EAAE,CAAC;IACb,CAAC;IAED,IAAI;QACH,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,SAAS,CAAC,QAAoB;QAC7B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED,WAAW;QACV,OAAO,IAAI,CAAC,UAAU,CAAC;IACxB,CAAC;IAED,UAAU;QACT,OAAO,IAAI,CAAC,aAAa,CAAC;IAC3B,CAAC;IAEO,IAAI,GAAG,GAAS,EAAE;QACzB,IAAI,CAAC,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QACpC,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;YACrB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;YACjE,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;YACpB,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC;YACpB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACzC,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;gBAC9C,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;YAC5B,CAAC;YACD,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;gBACvC,QAAQ,EAAE,CAAC;YACZ,CAAC;QACF,CAAC;IACF,CAAC,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ShapeData, Viewport } from "@edv4h/usketch-shared";
|
|
2
|
+
interface MinimapProps {
|
|
3
|
+
shapes: ReadonlyMap<string, ShapeData>;
|
|
4
|
+
viewport: Viewport;
|
|
5
|
+
selection: ReadonlySet<string>;
|
|
6
|
+
}
|
|
7
|
+
export declare function Minimap({ shapes, viewport, selection }: MinimapProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=minimap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"minimap.d.ts","sourceRoot":"","sources":["../../src/overlays/minimap.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAIjE,UAAU,YAAY;IACrB,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACvC,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC/B;AAKD,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,YAAY,2CAmEpE"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { computeMinimap } from "@edv4h/usketch-shared";
|
|
3
|
+
import { ACCENT_DIM, PANEL_BG, PANEL_BLUR, PANEL_BORDER_RADIUS } from "../styles.js";
|
|
4
|
+
const MAP_W = 140;
|
|
5
|
+
const MAP_H = 90;
|
|
6
|
+
export function Minimap({ shapes, viewport, selection }) {
|
|
7
|
+
const shapeArr = Array.from(shapes.values());
|
|
8
|
+
// viewport.x/y is a screen-space translate offset, not a world origin.
|
|
9
|
+
const vpWorldX = -viewport.x / viewport.zoom;
|
|
10
|
+
const vpWorldY = -viewport.y / viewport.zoom;
|
|
11
|
+
const vpWorldW = window.innerWidth / viewport.zoom;
|
|
12
|
+
const vpWorldH = window.innerHeight / viewport.zoom;
|
|
13
|
+
const result = computeMinimap({
|
|
14
|
+
shapes: shapeArr,
|
|
15
|
+
viewportWorld: { x: vpWorldX, y: vpWorldY, width: vpWorldW, height: vpWorldH },
|
|
16
|
+
mapWidth: MAP_W,
|
|
17
|
+
mapHeight: MAP_H,
|
|
18
|
+
padding: 20,
|
|
19
|
+
minSize: 2,
|
|
20
|
+
});
|
|
21
|
+
return (_jsxs("div", { style: {
|
|
22
|
+
position: "absolute",
|
|
23
|
+
bottom: 8,
|
|
24
|
+
left: 8,
|
|
25
|
+
width: MAP_W,
|
|
26
|
+
height: MAP_H,
|
|
27
|
+
background: PANEL_BG,
|
|
28
|
+
borderRadius: PANEL_BORDER_RADIUS,
|
|
29
|
+
backdropFilter: PANEL_BLUR,
|
|
30
|
+
pointerEvents: "auto",
|
|
31
|
+
overflow: "hidden",
|
|
32
|
+
}, children: [result.rects.map((r) => (_jsx("div", { style: {
|
|
33
|
+
position: "absolute",
|
|
34
|
+
left: r.x,
|
|
35
|
+
top: r.y,
|
|
36
|
+
width: r.width,
|
|
37
|
+
height: r.height,
|
|
38
|
+
background: selection.has(r.id)
|
|
39
|
+
? "rgba(99, 102, 241, 0.8)"
|
|
40
|
+
: "rgba(255, 255, 255, 0.4)",
|
|
41
|
+
borderRadius: 1,
|
|
42
|
+
} }, r.id))), result.viewportRect && (_jsx("div", { style: {
|
|
43
|
+
position: "absolute",
|
|
44
|
+
left: result.viewportRect.x,
|
|
45
|
+
top: result.viewportRect.y,
|
|
46
|
+
width: result.viewportRect.width,
|
|
47
|
+
height: result.viewportRect.height,
|
|
48
|
+
border: `1px solid ${ACCENT_DIM}`,
|
|
49
|
+
borderRadius: 2,
|
|
50
|
+
boxSizing: "border-box",
|
|
51
|
+
} }))] }));
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=minimap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"minimap.js","sourceRoot":"","sources":["../../src/overlays/minimap.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,cAAc,EAAsB,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAQrF,MAAM,KAAK,GAAG,GAAG,CAAC;AAClB,MAAM,KAAK,GAAG,EAAE,CAAC;AAEjB,MAAM,UAAU,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAgB;IACpE,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAE7C,uEAAuE;IACvE,MAAM,QAAQ,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC7C,MAAM,QAAQ,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC7C,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC;IACnD,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC;IAEpD,MAAM,MAAM,GAAkB,cAAc,CAAC;QAC5C,MAAM,EAAE,QAAQ;QAChB,aAAa,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE;QAC9E,QAAQ,EAAE,KAAK;QACf,SAAS,EAAE,KAAK;QAChB,OAAO,EAAE,EAAE;QACX,OAAO,EAAE,CAAC;KACV,CAAC,CAAC;IAEH,OAAO,CACN,eACC,KAAK,EAAE;YACN,QAAQ,EAAE,UAAU;YACpB,MAAM,EAAE,CAAC;YACT,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,KAAK;YACb,UAAU,EAAE,QAAQ;YACpB,YAAY,EAAE,mBAAmB;YACjC,cAAc,EAAE,UAAU;YAC1B,aAAa,EAAE,MAAM;YACrB,QAAQ,EAAE,QAAQ;SAClB,aAGA,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CACxB,cAEC,KAAK,EAAE;oBACN,QAAQ,EAAE,UAAU;oBACpB,IAAI,EAAE,CAAC,CAAC,CAAC;oBACT,GAAG,EAAE,CAAC,CAAC,CAAC;oBACR,KAAK,EAAE,CAAC,CAAC,KAAK;oBACd,MAAM,EAAE,CAAC,CAAC,MAAM;oBAChB,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC9B,CAAC,CAAC,yBAAyB;wBAC3B,CAAC,CAAC,0BAA0B;oBAC7B,YAAY,EAAE,CAAC;iBACf,IAXI,CAAC,CAAC,EAAE,CAYR,CACF,CAAC,EAED,MAAM,CAAC,YAAY,IAAI,CACvB,cACC,KAAK,EAAE;oBACN,QAAQ,EAAE,UAAU;oBACpB,IAAI,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;oBAC3B,GAAG,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;oBAC1B,KAAK,EAAE,MAAM,CAAC,YAAY,CAAC,KAAK;oBAChC,MAAM,EAAE,MAAM,CAAC,YAAY,CAAC,MAAM;oBAClC,MAAM,EAAE,aAAa,UAAU,EAAE;oBACjC,YAAY,EAAE,CAAC;oBACf,SAAS,EAAE,YAAY;iBACvB,GACA,CACF,IACI,CACN,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BoardStore, ShapeData } from "@edv4h/usketch-shared";
|
|
2
|
+
interface ShapeBoundsOverlayProps {
|
|
3
|
+
shape: ShapeData | undefined;
|
|
4
|
+
store: BoardStore;
|
|
5
|
+
}
|
|
6
|
+
export declare function ShapeBoundsOverlay({ shape, store }: ShapeBoundsOverlayProps): import("react/jsx-runtime").JSX.Element | null;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=shape-bounds-overlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shape-bounds-overlay.d.ts","sourceRoot":"","sources":["../../src/overlays/shape-bounds-overlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAInE,UAAU,uBAAuB;IAChC,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;IAC7B,KAAK,EAAE,UAAU,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,uBAAuB,kDAgD3E"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { worldToScreen } from "@edv4h/usketch-shared";
|
|
3
|
+
import { useCallback, useSyncExternalStore } from "react";
|
|
4
|
+
export function ShapeBoundsOverlay({ shape, store }) {
|
|
5
|
+
// Subscribe to store so viewport changes trigger re-render
|
|
6
|
+
const viewport = useSyncExternalStore(useCallback((cb) => store.subscribe(cb), [store]), () => store.getViewport());
|
|
7
|
+
if (!shape)
|
|
8
|
+
return null;
|
|
9
|
+
const tl = worldToScreen(shape.x, shape.y, viewport);
|
|
10
|
+
const br = worldToScreen(shape.x + shape.width, shape.y + shape.height, viewport);
|
|
11
|
+
const screenX = tl.x;
|
|
12
|
+
const screenY = tl.y;
|
|
13
|
+
const screenW = br.x - tl.x;
|
|
14
|
+
const screenH = br.y - tl.y;
|
|
15
|
+
return (_jsx("div", { style: {
|
|
16
|
+
position: "absolute",
|
|
17
|
+
left: screenX,
|
|
18
|
+
top: screenY,
|
|
19
|
+
width: screenW,
|
|
20
|
+
height: screenH,
|
|
21
|
+
border: "2px dashed rgba(99, 102, 241, 0.7)",
|
|
22
|
+
borderRadius: 2,
|
|
23
|
+
pointerEvents: "none",
|
|
24
|
+
boxSizing: "border-box",
|
|
25
|
+
}, children: _jsxs("div", { style: {
|
|
26
|
+
position: "absolute",
|
|
27
|
+
top: -16,
|
|
28
|
+
left: 0,
|
|
29
|
+
fontSize: 9,
|
|
30
|
+
fontFamily: "'SF Mono', monospace",
|
|
31
|
+
color: "rgba(99, 102, 241, 0.9)",
|
|
32
|
+
background: "rgba(0, 0, 0, 0.6)",
|
|
33
|
+
padding: "1px 4px",
|
|
34
|
+
borderRadius: 2,
|
|
35
|
+
whiteSpace: "nowrap",
|
|
36
|
+
}, children: [shape.type, " (", Math.round(shape.width), "\u00D7", Math.round(shape.height), ")"] }) }));
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=shape-bounds-overlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shape-bounds-overlay.js","sourceRoot":"","sources":["../../src/overlays/shape-bounds-overlay.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAO1D,MAAM,UAAU,kBAAkB,CAAC,EAAE,KAAK,EAAE,KAAK,EAA2B;IAC3E,2DAA2D;IAC3D,MAAM,QAAQ,GAAG,oBAAoB,CACpC,WAAW,CAAC,CAAC,EAAc,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAC7D,GAAG,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CACzB,CAAC;IAEF,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACrD,MAAM,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClF,MAAM,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC;IACrB,MAAM,OAAO,GAAG,EAAE,CAAC,CAAC,CAAC;IACrB,MAAM,OAAO,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAC5B,MAAM,OAAO,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAE5B,OAAO,CACN,cACC,KAAK,EAAE;YACN,QAAQ,EAAE,UAAU;YACpB,IAAI,EAAE,OAAO;YACb,GAAG,EAAE,OAAO;YACZ,KAAK,EAAE,OAAO;YACd,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,oCAAoC;YAC5C,YAAY,EAAE,CAAC;YACf,aAAa,EAAE,MAAM;YACrB,SAAS,EAAE,YAAY;SACvB,YAED,eACC,KAAK,EAAE;gBACN,QAAQ,EAAE,UAAU;gBACpB,GAAG,EAAE,CAAC,EAAE;gBACR,IAAI,EAAE,CAAC;gBACP,QAAQ,EAAE,CAAC;gBACX,UAAU,EAAE,sBAAsB;gBAClC,KAAK,EAAE,yBAAyB;gBAChC,UAAU,EAAE,oBAAoB;gBAChC,OAAO,EAAE,SAAS;gBAClB,YAAY,EAAE,CAAC;gBACf,UAAU,EAAE,QAAQ;aACpB,aAEA,KAAK,CAAC,IAAI,QAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,YAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAC5D,GACD,CACN,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { EventLogger } from "../event-logger.js";
|
|
2
|
+
interface EventsPanelProps {
|
|
3
|
+
eventLogger: EventLogger;
|
|
4
|
+
}
|
|
5
|
+
export declare function EventsPanel({ eventLogger }: EventsPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
export {};
|
|
7
|
+
//# sourceMappingURL=events-panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events-panel.d.ts","sourceRoot":"","sources":["../../src/panels/events-panel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAiB,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGrE,UAAU,gBAAgB;IACzB,WAAW,EAAE,WAAW,CAAC;CACzB;AA4BD,wBAAgB,WAAW,CAAC,EAAE,WAAW,EAAE,EAAE,gBAAgB,2CAwE5D"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useState, useSyncExternalStore } from "react";
|
|
3
|
+
import { LABEL_STYLE, MINI_BUTTON, PANEL_BASE, SCROLLABLE_STYLE, TEXT_MUTED } from "../styles.js";
|
|
4
|
+
const EVENT_COLORS = {
|
|
5
|
+
// canvas events — each action gets its own shade
|
|
6
|
+
"canvas:pointerdown": "#3b82f6", // blue
|
|
7
|
+
"canvas:pointerup": "#60a5fa", // light blue
|
|
8
|
+
"canvas:pointermove": "#93c5fd", // lighter blue
|
|
9
|
+
"canvas:wheel": "#2563eb", // dark blue
|
|
10
|
+
"canvas:middle-down": "#1d4ed8", // darker blue
|
|
11
|
+
// shape events
|
|
12
|
+
shape: "#4ade80", // green
|
|
13
|
+
// tool events
|
|
14
|
+
tool: "#fbbf24", // yellow
|
|
15
|
+
// selection events
|
|
16
|
+
selection: "#c084fc", // purple
|
|
17
|
+
// viewport events
|
|
18
|
+
viewport: "#f472b6", // pink
|
|
19
|
+
// command events
|
|
20
|
+
command: "#fb923c", // orange
|
|
21
|
+
};
|
|
22
|
+
const DEFAULT_EVENT_COLOR = "#a0a0a0";
|
|
23
|
+
function eventColor(event) {
|
|
24
|
+
// Try exact match first, then prefix
|
|
25
|
+
return EVENT_COLORS[event] ?? EVENT_COLORS[event.split(":")[0]] ?? DEFAULT_EVENT_COLOR;
|
|
26
|
+
}
|
|
27
|
+
export function EventsPanel({ eventLogger }) {
|
|
28
|
+
const [filter, setFilter] = useState("");
|
|
29
|
+
const events = useSyncExternalStore(useCallback((cb) => eventLogger.subscribe(cb), [eventLogger]), () => eventLogger.getSnapshot());
|
|
30
|
+
const filtered = filter
|
|
31
|
+
? events.filter((e) => e.event.toLowerCase().includes(filter.toLowerCase()))
|
|
32
|
+
: events;
|
|
33
|
+
return (_jsxs("div", { style: {
|
|
34
|
+
...PANEL_BASE,
|
|
35
|
+
position: "absolute",
|
|
36
|
+
bottom: 8,
|
|
37
|
+
right: 8,
|
|
38
|
+
width: 280,
|
|
39
|
+
height: 240,
|
|
40
|
+
display: "flex",
|
|
41
|
+
flexDirection: "column",
|
|
42
|
+
}, children: [_jsxs("div", { style: {
|
|
43
|
+
...LABEL_STYLE,
|
|
44
|
+
display: "flex",
|
|
45
|
+
justifyContent: "space-between",
|
|
46
|
+
alignItems: "center",
|
|
47
|
+
}, children: [_jsxs("span", { children: ["Event Log (", filtered.length, ")"] }), _jsx("button", { type: "button", style: MINI_BUTTON, onClick: () => eventLogger.clear(), children: "Clear" })] }), _jsx("input", { type: "text", placeholder: "Filter events...", value: filter, onChange: (e) => setFilter(e.target.value), style: {
|
|
48
|
+
background: "rgba(255, 255, 255, 0.08)",
|
|
49
|
+
border: "1px solid rgba(255, 255, 255, 0.15)",
|
|
50
|
+
borderRadius: 3,
|
|
51
|
+
color: "#e0e0e0",
|
|
52
|
+
fontFamily: "'SF Mono', monospace",
|
|
53
|
+
fontSize: 10,
|
|
54
|
+
padding: "3px 6px",
|
|
55
|
+
outline: "none",
|
|
56
|
+
marginBottom: 4,
|
|
57
|
+
} }), _jsx("div", { style: { ...SCROLLABLE_STYLE, flexGrow: 1 }, children: filtered.length === 0 ? (_jsx("div", { style: { color: TEXT_MUTED }, children: "No events" })) : ([...filtered].reverse().map((entry, i) => (_jsxs("div", { style: { color: eventColor(entry.event) }, children: [_jsxs("span", { style: { color: TEXT_MUTED }, children: [new Date(entry.timestamp).toLocaleTimeString(), " "] }), entry.event, entry.count > 1 && _jsxs("span", { style: { color: TEXT_MUTED }, children: [" (", entry.count, ")"] })] }, `${entry.timestamp}-${i}`)))) })] }));
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=events-panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events-panel.js","sourceRoot":"","sources":["../../src/panels/events-panel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { BoardStore, CommandRegistry, EventBus, LayerManager, ShapeRegistry, ToolRegistry, Viewport } from "@edv4h/usketch-shared";
|
|
2
|
+
import type { FpsCounter } from "../fps-counter.js";
|
|
3
|
+
import type { PointerTracker } from "../pointer-tracker.js";
|
|
4
|
+
import type { SyncStatusTrackerLike } from "../sync-status-types.js";
|
|
5
|
+
interface GeneralPanelProps {
|
|
6
|
+
store: BoardStore;
|
|
7
|
+
fpsCounter: FpsCounter;
|
|
8
|
+
pointerTracker: PointerTracker;
|
|
9
|
+
commands: CommandRegistry;
|
|
10
|
+
tools: ToolRegistry;
|
|
11
|
+
layers: LayerManager;
|
|
12
|
+
shapes: ShapeRegistry;
|
|
13
|
+
syncStatus?: SyncStatusTrackerLike;
|
|
14
|
+
events: EventBus;
|
|
15
|
+
viewport: Viewport;
|
|
16
|
+
activeToolId: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function GeneralPanel({ store, fpsCounter, pointerTracker, commands, tools, layers, shapes, syncStatus, events, viewport, activeToolId, }: GeneralPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=general-panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"general-panel.d.ts","sourceRoot":"","sources":["../../src/panels/general-panel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EACV,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,MAAM,uBAAuB,CAAC;AAG/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAW5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAQrE,UAAU,iBAAiB;IAC1B,KAAK,EAAE,UAAU,CAAC;IAClB,UAAU,EAAE,UAAU,CAAC;IACvB,cAAc,EAAE,cAAc,CAAC;IAC/B,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,EAAE,YAAY,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,aAAa,CAAC;IACtB,UAAU,CAAC,EAAE,qBAAqB,CAAC;IACnC,MAAM,EAAE,QAAQ,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACrB;AA6BD,wBAAgB,YAAY,CAAC,EAC5B,KAAK,EACL,UAAU,EACV,cAAc,EACd,QAAQ,EACR,KAAK,EACL,MAAM,EACN,MAAM,EACN,UAAU,EACV,MAAM,EACN,QAAQ,EACR,YAAY,GACZ,EAAE,iBAAiB,2CA0MnB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useEffect, useState, useSyncExternalStore } from "react";
|
|
3
|
+
import { FpsGraph } from "../components/fps-graph.js";
|
|
4
|
+
import { fmt, fpsColor, INLINE_INPUT, LABEL_STYLE, MINI_BUTTON, MINI_BUTTON_ACCENT, PANEL_BASE, SECTION_STYLE, } from "../styles.js";
|
|
5
|
+
const DEFAULT_SYNC_SNAPSHOT = {
|
|
6
|
+
state: "loading",
|
|
7
|
+
shapeCount: 0,
|
|
8
|
+
lastSyncedAt: null,
|
|
9
|
+
error: null,
|
|
10
|
+
};
|
|
11
|
+
const SYNC_STATE_COLORS = {
|
|
12
|
+
loading: "#fbbf24",
|
|
13
|
+
synced: "#4ade80",
|
|
14
|
+
syncing: "#60a5fa",
|
|
15
|
+
error: "#f87171",
|
|
16
|
+
};
|
|
17
|
+
const SYNC_STATE_LABELS = {
|
|
18
|
+
loading: "Loading…",
|
|
19
|
+
synced: "Synced",
|
|
20
|
+
syncing: "Syncing…",
|
|
21
|
+
error: "Error",
|
|
22
|
+
};
|
|
23
|
+
function formatTimestamp(ts) {
|
|
24
|
+
if (ts === null)
|
|
25
|
+
return "—";
|
|
26
|
+
const d = new Date(ts);
|
|
27
|
+
return `${d.getHours().toString().padStart(2, "0")}:${d.getMinutes().toString().padStart(2, "0")}:${d.getSeconds().toString().padStart(2, "0")}`;
|
|
28
|
+
}
|
|
29
|
+
export function GeneralPanel({ store, fpsCounter, pointerTracker, commands, tools, layers, shapes, syncStatus, events, viewport, activeToolId, }) {
|
|
30
|
+
const fps = useSyncExternalStore(useCallback((cb) => fpsCounter.subscribe(cb), [fpsCounter]), () => fpsCounter.getSnapshot());
|
|
31
|
+
const pointer = useSyncExternalStore(useCallback((cb) => pointerTracker.subscribe(cb), [pointerTracker]), () => pointerTracker.getSnapshot());
|
|
32
|
+
const syncSnapshot = useSyncExternalStore(useCallback((cb) => (syncStatus ? syncStatus.subscribe(cb) : () => { }), [syncStatus]), () => syncStatus?.getSnapshot() ?? DEFAULT_SYNC_SNAPSHOT);
|
|
33
|
+
const canUndo = commands.canUndo();
|
|
34
|
+
const canRedo = commands.canRedo();
|
|
35
|
+
const historySize = commands.getHistorySize();
|
|
36
|
+
const historyCursor = commands.getCursor();
|
|
37
|
+
const toolCount = tools.getAll().size;
|
|
38
|
+
const layerCount = layers.getLayers().length;
|
|
39
|
+
const shapeTypeCount = shapes.getAll().size;
|
|
40
|
+
// GPU renderer stats (emitted by gpu-renderer plugin)
|
|
41
|
+
const [gpuStats, setGpuStats] = useState(null);
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
return events.on("gpu-renderer:stats", setGpuStats);
|
|
44
|
+
}, [events]);
|
|
45
|
+
// Phase 2: viewport editing
|
|
46
|
+
const [editingViewport, setEditingViewport] = useState(false);
|
|
47
|
+
const [vpDraft, setVpDraft] = useState({ x: "", y: "", zoom: "" });
|
|
48
|
+
const startEditViewport = () => {
|
|
49
|
+
setVpDraft({ x: String(viewport.x), y: String(viewport.y), zoom: String(viewport.zoom) });
|
|
50
|
+
setEditingViewport(true);
|
|
51
|
+
};
|
|
52
|
+
const commitViewport = () => {
|
|
53
|
+
const x = Number.parseFloat(vpDraft.x);
|
|
54
|
+
const y = Number.parseFloat(vpDraft.y);
|
|
55
|
+
const zoom = Number.parseFloat(vpDraft.zoom);
|
|
56
|
+
if (!Number.isNaN(x) && !Number.isNaN(y) && !Number.isNaN(zoom) && zoom > 0) {
|
|
57
|
+
store.setViewport({ x, y, zoom });
|
|
58
|
+
}
|
|
59
|
+
setEditingViewport(false);
|
|
60
|
+
};
|
|
61
|
+
return (_jsxs("div", { style: {
|
|
62
|
+
...PANEL_BASE,
|
|
63
|
+
position: "absolute",
|
|
64
|
+
top: 8,
|
|
65
|
+
right: 8,
|
|
66
|
+
width: 220,
|
|
67
|
+
}, children: [_jsxs("div", { style: SECTION_STYLE, children: [_jsxs("span", { style: { color: fpsColor(fps), fontWeight: "bold" }, children: [fps, " FPS"] }), _jsx(FpsGraph, { fpsCounter: fpsCounter })] }), _jsxs("div", { style: SECTION_STYLE, children: [_jsxs("div", { style: LABEL_STYLE, children: ["Viewport", " ", !editingViewport && (_jsx("button", { type: "button", style: MINI_BUTTON, onClick: startEditViewport, children: "edit" }))] }), editingViewport ? (_jsxs("div", { style: { display: "flex", gap: 3, alignItems: "center" }, children: [_jsx("input", { style: INLINE_INPUT, value: vpDraft.x, onChange: (e) => setVpDraft((d) => ({ ...d, x: e.target.value })), onKeyDown: (e) => e.key === "Enter" && commitViewport() }), _jsx("input", { style: INLINE_INPUT, value: vpDraft.y, onChange: (e) => setVpDraft((d) => ({ ...d, y: e.target.value })), onKeyDown: (e) => e.key === "Enter" && commitViewport() }), _jsx("input", { style: { ...INLINE_INPUT, width: 36 }, value: vpDraft.zoom, onChange: (e) => setVpDraft((d) => ({ ...d, zoom: e.target.value })), onKeyDown: (e) => e.key === "Enter" && commitViewport() }), _jsx("button", { type: "button", style: MINI_BUTTON_ACCENT, onClick: commitViewport, children: "OK" })] })) : (_jsxs("div", { children: ["x: ", fmt(viewport.x), " y: ", fmt(viewport.y), " zoom: ", fmt(viewport.zoom)] }))] }), _jsxs("div", { style: SECTION_STYLE, children: [_jsx("div", { style: LABEL_STYLE, children: "Active Tool" }), _jsx("div", { children: activeToolId })] }), _jsxs("div", { style: SECTION_STYLE, children: [_jsx("div", { style: LABEL_STYLE, children: "Pointer" }), _jsxs("div", { children: ["world: (", fmt(pointer.world.x), ", ", fmt(pointer.world.y), ")"] }), _jsxs("div", { children: ["screen: (", fmt(pointer.screen.x), ", ", fmt(pointer.screen.y), ")"] })] }), _jsxs("div", { style: SECTION_STYLE, children: [_jsxs("div", { style: LABEL_STYLE, children: ["History (", historyCursor + 1, "/", historySize, ")"] }), _jsxs("div", { style: { display: "flex", gap: 4 }, children: [_jsx("button", { type: "button", style: { ...MINI_BUTTON, opacity: canUndo ? 1 : 0.3 }, disabled: !canUndo, onClick: () => commands.undo(), children: "\u27F5 Undo" }), _jsx("button", { type: "button", style: { ...MINI_BUTTON, opacity: canRedo ? 1 : 0.3 }, disabled: !canRedo, onClick: () => commands.redo(), children: "Redo \u27F6" })] })] }), _jsxs("div", { style: SECTION_STYLE, children: [_jsx("div", { style: LABEL_STYLE, children: "Persistence (Yjs + IndexedDB)" }), _jsxs("div", { style: { display: "flex", alignItems: "center", gap: 5 }, children: [_jsx("span", { style: {
|
|
68
|
+
display: "inline-block",
|
|
69
|
+
width: 7,
|
|
70
|
+
height: 7,
|
|
71
|
+
borderRadius: "50%",
|
|
72
|
+
background: SYNC_STATE_COLORS[syncSnapshot.state] ?? "#888",
|
|
73
|
+
} }), _jsx("span", { style: { color: SYNC_STATE_COLORS[syncSnapshot.state] ?? "#888" }, children: SYNC_STATE_LABELS[syncSnapshot.state] ?? syncSnapshot.state })] }), _jsxs("div", { children: ["Shapes: ", syncSnapshot.shapeCount, " \u00B7 Last: ", formatTimestamp(syncSnapshot.lastSyncedAt)] }), syncSnapshot.error && (_jsx("div", { style: { color: "#f87171", fontSize: 10 }, children: syncSnapshot.error }))] }), _jsxs("div", { style: SECTION_STYLE, children: [_jsx("div", { style: LABEL_STYLE, children: "System" }), _jsxs("div", { children: ["Tools: ", toolCount, " \u00B7 Layers: ", layerCount, " \u00B7 Shape types: ", shapeTypeCount] })] }), _jsxs("div", { children: [_jsx("div", { style: LABEL_STYLE, children: "GPU Renderer" }), gpuStats ? (_jsxs("div", { children: [_jsx("div", { style: { color: "#4ade80" }, children: "Active" }), _jsxs("div", { children: ["GPU: ", gpuStats.gpuShapeCount, " (SDF: ", gpuStats.sdfCount, ", Lines:", " ", gpuStats.polylineCount, ")"] })] })) : (_jsx("div", { style: { color: "#888" }, children: "Inactive (DOM only)" }))] })] }));
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=general-panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"general-panel.js","sourceRoot":"","sources":["../../src/panels/general-panel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { BoardStore, CommandRegistry, ShapeData } from "@edv4h/usketch-shared";
|
|
2
|
+
interface ShapesPanelProps {
|
|
3
|
+
store: BoardStore;
|
|
4
|
+
commands: CommandRegistry;
|
|
5
|
+
shapes: ReadonlyMap<string, ShapeData>;
|
|
6
|
+
selection: ReadonlySet<string>;
|
|
7
|
+
onHoverShape: (id: string | null) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function ShapesPanel({ store, commands, shapes, selection, onHoverShape, }: ShapesPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=shapes-panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shapes-panel.d.ts","sourceRoot":"","sources":["../../src/panels/shapes-panel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAepF,UAAU,gBAAgB;IACzB,KAAK,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,eAAe,CAAC;IAC1B,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACvC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC/B,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CAC1C;AA4DD,wBAAgB,WAAW,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,MAAM,EACN,SAAS,EACT,YAAY,GACZ,EAAE,gBAAgB,2CA2FlB"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useState } from "react";
|
|
3
|
+
import { ACCENT_DIM, fmt, INLINE_INPUT, LABEL_STYLE, MINI_BUTTON, MINI_BUTTON_ACCENT, PANEL_BASE, SCROLLABLE_STYLE, shortId, TEXT_MUTED, } from "../styles.js";
|
|
4
|
+
const KNOWN_KEYS = new Set(["id", "type", "x", "y", "width", "height", "style", "rotation"]);
|
|
5
|
+
function EditableField({ label, value, onCommit, }) {
|
|
6
|
+
const [editing, setEditing] = useState(false);
|
|
7
|
+
const [draft, setDraft] = useState("");
|
|
8
|
+
const committedRef = useRef(false);
|
|
9
|
+
const start = () => {
|
|
10
|
+
committedRef.current = false;
|
|
11
|
+
setDraft(String(value));
|
|
12
|
+
setEditing(true);
|
|
13
|
+
};
|
|
14
|
+
const commit = () => {
|
|
15
|
+
if (committedRef.current)
|
|
16
|
+
return;
|
|
17
|
+
committedRef.current = true;
|
|
18
|
+
const n = Number.parseFloat(draft);
|
|
19
|
+
if (!Number.isNaN(n))
|
|
20
|
+
onCommit(n);
|
|
21
|
+
setEditing(false);
|
|
22
|
+
};
|
|
23
|
+
if (editing) {
|
|
24
|
+
return (_jsxs("span", { children: [label, ":", " ", _jsx("input", { style: { ...INLINE_INPUT, width: 44 }, value: draft, onChange: (e) => setDraft(e.target.value), onKeyDown: (e) => {
|
|
25
|
+
if (e.key === "Enter")
|
|
26
|
+
commit();
|
|
27
|
+
if (e.key === "Escape")
|
|
28
|
+
setEditing(false);
|
|
29
|
+
}, onBlur: commit,
|
|
30
|
+
// biome-ignore lint/a11y/noAutofocus: debug tool inline edit needs immediate focus
|
|
31
|
+
autoFocus: true })] }));
|
|
32
|
+
}
|
|
33
|
+
return (
|
|
34
|
+
// biome-ignore lint/a11y/useKeyWithClickEvents: debug tool
|
|
35
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: debug tool
|
|
36
|
+
_jsxs("span", { onClick: start, style: { cursor: "text" }, title: "Click to edit", children: [label, ": ", fmt(value)] }));
|
|
37
|
+
}
|
|
38
|
+
export function ShapesPanel({ store, commands, shapes, selection, onHoverShape, }) {
|
|
39
|
+
const [expandedId, setExpandedId] = useState(null);
|
|
40
|
+
const shapeEntries = Array.from(shapes.values());
|
|
41
|
+
const updateField = (id, field, value) => {
|
|
42
|
+
const shape = store.getShape(id);
|
|
43
|
+
if (!shape)
|
|
44
|
+
return;
|
|
45
|
+
const from = { [field]: shape[field] };
|
|
46
|
+
const to = { [field]: value };
|
|
47
|
+
commands.execute({
|
|
48
|
+
execute: () => store.updateShape(id, to),
|
|
49
|
+
undo: () => store.updateShape(id, from),
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
const deleteShape = (id) => {
|
|
53
|
+
const snapshot = store.getShape(id);
|
|
54
|
+
if (!snapshot)
|
|
55
|
+
return;
|
|
56
|
+
commands.execute({
|
|
57
|
+
execute: () => store.deleteShape(id),
|
|
58
|
+
undo: () => store.addShape(snapshot),
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
return (_jsxs("div", { style: {
|
|
62
|
+
...PANEL_BASE,
|
|
63
|
+
position: "absolute",
|
|
64
|
+
top: 8,
|
|
65
|
+
left: 8,
|
|
66
|
+
width: 240,
|
|
67
|
+
height: 300,
|
|
68
|
+
display: "flex",
|
|
69
|
+
flexDirection: "column",
|
|
70
|
+
}, children: [_jsxs("div", { style: LABEL_STYLE, children: ["Shapes (", shapes.size, ")"] }), _jsx("div", { style: { ...SCROLLABLE_STYLE, flexGrow: 1, maxHeight: "none" }, children: shapeEntries.length === 0 ? (_jsx("div", { style: { color: TEXT_MUTED }, children: "No shapes" })) : (shapeEntries.map((s) => {
|
|
71
|
+
const isSelected = selection.has(s.id);
|
|
72
|
+
const isExpanded = expandedId === s.id;
|
|
73
|
+
return (
|
|
74
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: debug tool
|
|
75
|
+
_jsxs("div", { onMouseEnter: () => onHoverShape(s.id), onMouseLeave: () => onHoverShape(null), children: [_jsxs("div", { onClick: () => setExpandedId(isExpanded ? null : s.id), style: {
|
|
76
|
+
padding: "2px 4px",
|
|
77
|
+
borderRadius: 3,
|
|
78
|
+
background: isSelected ? ACCENT_DIM : "transparent",
|
|
79
|
+
cursor: "pointer",
|
|
80
|
+
display: "flex",
|
|
81
|
+
justifyContent: "space-between",
|
|
82
|
+
alignItems: "center",
|
|
83
|
+
}, children: [_jsxs("span", { children: [isExpanded ? "▾" : "▸", " ", shortId(s.id), " ", _jsx("span", { style: { color: TEXT_MUTED }, children: s.type })] }), _jsxs("span", { style: { color: TEXT_MUTED, fontSize: 9 }, children: ["(", fmt(s.x), ", ", fmt(s.y), ")"] })] }), isExpanded && (_jsx(ShapeDetail, { shape: s, store: store, selection: selection, onUpdate: updateField, onDelete: deleteShape }))] }, s.id));
|
|
84
|
+
})) })] }));
|
|
85
|
+
}
|
|
86
|
+
function ShapeDetail({ shape, store, selection, onUpdate, onDelete, }) {
|
|
87
|
+
const customKeys = Object.keys(shape).filter((k) => !KNOWN_KEYS.has(k));
|
|
88
|
+
return (_jsxs("div", { style: {
|
|
89
|
+
padding: "4px 8px",
|
|
90
|
+
fontSize: 10,
|
|
91
|
+
lineHeight: "16px",
|
|
92
|
+
borderLeft: `2px solid ${ACCENT_DIM}`,
|
|
93
|
+
}, children: [_jsxs("div", { style: { color: TEXT_MUTED }, children: ["id: ", shape.id] }), _jsxs("div", { style: { color: TEXT_MUTED }, children: ["type: ", shape.type] }), _jsxs("div", { children: [_jsx(EditableField, { label: "x", value: shape.x, onCommit: (v) => onUpdate(shape.id, "x", v) }), " ", _jsx(EditableField, { label: "y", value: shape.y, onCommit: (v) => onUpdate(shape.id, "y", v) })] }), _jsxs("div", { children: [_jsx(EditableField, { label: "w", value: shape.width, onCommit: (v) => onUpdate(shape.id, "width", v) }), " ", _jsx(EditableField, { label: "h", value: shape.height, onCommit: (v) => onUpdate(shape.id, "height", v) })] }), shape.rotation !== undefined && (_jsx("div", { children: _jsx(EditableField, { label: "rot", value: shape.rotation, onCommit: (v) => onUpdate(shape.id, "rotation", v) }) })), _jsxs("div", { style: { color: TEXT_MUTED, marginTop: 2 }, children: ["style: fill=", shape.style.fill, " stroke=", shape.style.stroke, " w=", shape.style.strokeWidth, " op=", shape.style.opacity] }), customKeys.length > 0 && (_jsxs("div", { style: { marginTop: 2 }, children: [_jsx("div", { style: { color: TEXT_MUTED }, children: "custom:" }), _jsx("pre", { style: {
|
|
94
|
+
margin: 0,
|
|
95
|
+
fontSize: 9,
|
|
96
|
+
color: "#a0a0a0",
|
|
97
|
+
whiteSpace: "pre-wrap",
|
|
98
|
+
wordBreak: "break-all",
|
|
99
|
+
}, children: JSON.stringify(Object.fromEntries(customKeys.map((k) => [k, shape[k]])), null, 1) })] })), _jsxs("div", { style: { display: "flex", gap: 4, marginTop: 4 }, children: [!selection.has(shape.id) && (_jsx("button", { type: "button", style: MINI_BUTTON_ACCENT, onClick: () => store.setSelection([shape.id]), children: "Select" })), _jsx("button", { type: "button", style: { ...MINI_BUTTON, color: "#f87171" }, onClick: () => onDelete(shape.id), children: "Delete" })] })] }));
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=shapes-panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shapes-panel.js","sourceRoot":"","sources":["../../src/panels/shapes-panel.tsx"],"names":[],"mappings":"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"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgC,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAkBzF,eAAO,MAAM,cAAc,EAAE,aAmE5B,CAAC"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { DebugHud } from "./debug-hud.js";
|
|
3
|
+
import { EventLogger } from "./event-logger.js";
|
|
4
|
+
import { FpsCounter } from "./fps-counter.js";
|
|
5
|
+
import { PointerTracker } from "./pointer-tracker.js";
|
|
6
|
+
// Excluded from event log to avoid noise
|
|
7
|
+
const EXCLUDED_EVENTS = new Set(["canvas:pointermove"]);
|
|
8
|
+
function formatEventLabel(event, data) {
|
|
9
|
+
if (data == null || typeof data !== "object")
|
|
10
|
+
return event;
|
|
11
|
+
const obj = data;
|
|
12
|
+
if ("id" in obj && typeof obj.id === "string") {
|
|
13
|
+
return `${event} → ${obj.id}`;
|
|
14
|
+
}
|
|
15
|
+
return event;
|
|
16
|
+
}
|
|
17
|
+
export const debugHudPlugin = {
|
|
18
|
+
id: "debug-hud",
|
|
19
|
+
name: "Debug HUD",
|
|
20
|
+
setup(ctx) {
|
|
21
|
+
const fpsCounter = new FpsCounter();
|
|
22
|
+
const eventLogger = new EventLogger();
|
|
23
|
+
const pointerTracker = new PointerTracker();
|
|
24
|
+
// Start FPS counter
|
|
25
|
+
fpsCounter.start();
|
|
26
|
+
// Monkey-patch emit to capture events
|
|
27
|
+
const originalEmit = ctx.events.emit.bind(ctx.events);
|
|
28
|
+
ctx.events.emit = (event, data) => {
|
|
29
|
+
if (!EXCLUDED_EVENTS.has(event)) {
|
|
30
|
+
const label = formatEventLabel(event, data);
|
|
31
|
+
eventLogger.push({ event: label, timestamp: Date.now() });
|
|
32
|
+
}
|
|
33
|
+
originalEmit(event, data);
|
|
34
|
+
};
|
|
35
|
+
// Track pointer coordinates
|
|
36
|
+
const unsubPointer = ctx.events.on("canvas:pointermove", (data) => {
|
|
37
|
+
pointerTracker.update(data.worldPoint, data.screenPoint);
|
|
38
|
+
});
|
|
39
|
+
// Pick up sync status tracker from window (set by app.tsx)
|
|
40
|
+
const syncStatus = globalThis.__usketchSyncStatus;
|
|
41
|
+
// Register the fixed layer — always renders, visibility toggled inside component
|
|
42
|
+
ctx.layers.register({
|
|
43
|
+
id: "debug-hud",
|
|
44
|
+
order: 9999,
|
|
45
|
+
fixed: true,
|
|
46
|
+
render: (renderCtx) => (_jsx(DebugHud, { store: ctx.store, fpsCounter: fpsCounter, eventLogger: eventLogger, pointerTracker: pointerTracker, commands: ctx.commands, tools: ctx.tools, layers: ctx.layers, shapes: ctx.shapes, syncStatus: syncStatus, events: ctx.events, ctx: renderCtx })),
|
|
47
|
+
});
|
|
48
|
+
// Store teardown in closure — no module-level state
|
|
49
|
+
this.teardown = () => {
|
|
50
|
+
fpsCounter.stop();
|
|
51
|
+
pointerTracker.dispose();
|
|
52
|
+
ctx.events.emit = originalEmit;
|
|
53
|
+
unsubPointer();
|
|
54
|
+
ctx.layers.unregister("debug-hud");
|
|
55
|
+
};
|
|
56
|
+
},
|
|
57
|
+
teardown() {
|
|
58
|
+
// overwritten by setup()
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Point } from "@edv4h/usketch-shared";
|
|
2
|
+
export interface PointerState {
|
|
3
|
+
world: Point;
|
|
4
|
+
screen: Point;
|
|
5
|
+
}
|
|
6
|
+
export declare class PointerTracker {
|
|
7
|
+
private state;
|
|
8
|
+
private listeners;
|
|
9
|
+
private pending;
|
|
10
|
+
private timer;
|
|
11
|
+
update(world: Point, screen: Point): void;
|
|
12
|
+
subscribe(listener: () => void): () => void;
|
|
13
|
+
getSnapshot(): PointerState;
|
|
14
|
+
dispose(): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=pointer-tracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer-tracker.d.ts","sourceRoot":"","sources":["../src/pointer-tracker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,KAAK,CAAC;CACd;AAID,qBAAa,cAAc;IAC1B,OAAO,CAAC,KAAK,CAAmE;IAChF,OAAO,CAAC,SAAS,CAAyB;IAC1C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAA8C;IAE3D,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,GAAG,IAAI;IAczC,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAK3C,WAAW,IAAI,YAAY;IAI3B,OAAO,IAAI,IAAI;CAIf"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const THROTTLE_MS = 100;
|
|
2
|
+
export class PointerTracker {
|
|
3
|
+
state = { world: { x: 0, y: 0 }, screen: { x: 0, y: 0 } };
|
|
4
|
+
listeners = new Set();
|
|
5
|
+
pending = false;
|
|
6
|
+
timer = null;
|
|
7
|
+
update(world, screen) {
|
|
8
|
+
this.state = { world, screen };
|
|
9
|
+
if (!this.pending) {
|
|
10
|
+
this.pending = true;
|
|
11
|
+
this.timer = setTimeout(() => {
|
|
12
|
+
this.pending = false;
|
|
13
|
+
this.timer = null;
|
|
14
|
+
for (const listener of this.listeners) {
|
|
15
|
+
listener();
|
|
16
|
+
}
|
|
17
|
+
}, THROTTLE_MS);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
subscribe(listener) {
|
|
21
|
+
this.listeners.add(listener);
|
|
22
|
+
return () => this.listeners.delete(listener);
|
|
23
|
+
}
|
|
24
|
+
getSnapshot() {
|
|
25
|
+
return this.state;
|
|
26
|
+
}
|
|
27
|
+
dispose() {
|
|
28
|
+
if (this.timer)
|
|
29
|
+
clearTimeout(this.timer);
|
|
30
|
+
this.listeners.clear();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=pointer-tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pointer-tracker.js","sourceRoot":"","sources":["../src/pointer-tracker.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB,MAAM,OAAO,cAAc;IAClB,KAAK,GAAiB,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;IACxE,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IAClC,OAAO,GAAG,KAAK,CAAC;IAChB,KAAK,GAAyC,IAAI,CAAC;IAE3D,MAAM,CAAC,KAAY,EAAE,MAAa;QACjC,IAAI,CAAC,KAAK,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YACnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACpB,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;gBACrB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;gBAClB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;oBACvC,QAAQ,EAAE,CAAC;gBACZ,CAAC;YACF,CAAC,EAAE,WAAW,CAAC,CAAC;QACjB,CAAC;IACF,CAAC;IAED,SAAS,CAAC,QAAoB;QAC7B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED,WAAW;QACV,OAAO,IAAI,CAAC,KAAK,CAAC;IACnB,CAAC;IAED,OAAO;QACN,IAAI,IAAI,CAAC,KAAK;YAAE,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;CACD"}
|
package/dist/styles.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
export declare const PANEL_BG = "rgba(0, 0, 0, 0.82)";
|
|
3
|
+
export declare const PANEL_BORDER_RADIUS = 8;
|
|
4
|
+
export declare const PANEL_BLUR = "blur(8px)";
|
|
5
|
+
export declare const FONT_FAMILY = "'SF Mono', 'Fira Code', 'Consolas', monospace";
|
|
6
|
+
export declare const TEXT_COLOR = "#e0e0e0";
|
|
7
|
+
export declare const TEXT_MUTED = "#6b7280";
|
|
8
|
+
export declare const TEXT_LABEL = "#8b8b8b";
|
|
9
|
+
export declare const ACCENT = "rgba(99, 102, 241, 0.8)";
|
|
10
|
+
export declare const ACCENT_DIM = "rgba(99, 102, 241, 0.3)";
|
|
11
|
+
export declare const FPS_GREEN = "#4ade80";
|
|
12
|
+
export declare const FPS_YELLOW = "#fbbf24";
|
|
13
|
+
export declare const FPS_RED = "#f87171";
|
|
14
|
+
export declare const PANEL_BASE: React.CSSProperties;
|
|
15
|
+
export declare const LABEL_STYLE: React.CSSProperties;
|
|
16
|
+
export declare const SECTION_STYLE: React.CSSProperties;
|
|
17
|
+
export declare const SCROLLABLE_STYLE: React.CSSProperties;
|
|
18
|
+
export declare const MINI_BUTTON: React.CSSProperties;
|
|
19
|
+
export declare const MINI_BUTTON_ACCENT: React.CSSProperties;
|
|
20
|
+
export declare const INLINE_INPUT: React.CSSProperties;
|
|
21
|
+
export declare function fpsColor(fps: number): string;
|
|
22
|
+
export declare function fmt(n: number): string;
|
|
23
|
+
export declare function shortId(id: string): string;
|
|
24
|
+
//# sourceMappingURL=styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,eAAO,MAAM,QAAQ,wBAAwB,CAAC;AAC9C,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,eAAO,MAAM,UAAU,cAAc,CAAC;AACtC,eAAO,MAAM,WAAW,kDAAkD,CAAC;AAC3E,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,MAAM,4BAA4B,CAAC;AAChD,eAAO,MAAM,UAAU,4BAA4B,CAAC;AACpD,eAAO,MAAM,SAAS,YAAY,CAAC;AACnC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,OAAO,YAAY,CAAC;AAEjC,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,aAW9B,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,aAI/B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,aAEjC,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,aAKpC,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,aAS/B,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,aAGtC,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,aAUhC,CAAC;AAEF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI5C;AAED,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAErC;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE1C"}
|
package/dist/styles.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export const PANEL_BG = "rgba(0, 0, 0, 0.82)";
|
|
2
|
+
export const PANEL_BORDER_RADIUS = 8;
|
|
3
|
+
export const PANEL_BLUR = "blur(8px)";
|
|
4
|
+
export const FONT_FAMILY = "'SF Mono', 'Fira Code', 'Consolas', monospace";
|
|
5
|
+
export const TEXT_COLOR = "#e0e0e0";
|
|
6
|
+
export const TEXT_MUTED = "#6b7280";
|
|
7
|
+
export const TEXT_LABEL = "#8b8b8b";
|
|
8
|
+
export const ACCENT = "rgba(99, 102, 241, 0.8)";
|
|
9
|
+
export const ACCENT_DIM = "rgba(99, 102, 241, 0.3)";
|
|
10
|
+
export const FPS_GREEN = "#4ade80";
|
|
11
|
+
export const FPS_YELLOW = "#fbbf24";
|
|
12
|
+
export const FPS_RED = "#f87171";
|
|
13
|
+
export const PANEL_BASE = {
|
|
14
|
+
background: PANEL_BG,
|
|
15
|
+
color: TEXT_COLOR,
|
|
16
|
+
fontFamily: FONT_FAMILY,
|
|
17
|
+
fontSize: 11,
|
|
18
|
+
lineHeight: "16px",
|
|
19
|
+
borderRadius: PANEL_BORDER_RADIUS,
|
|
20
|
+
backdropFilter: PANEL_BLUR,
|
|
21
|
+
padding: 10,
|
|
22
|
+
pointerEvents: "auto",
|
|
23
|
+
userSelect: "none",
|
|
24
|
+
};
|
|
25
|
+
export const LABEL_STYLE = {
|
|
26
|
+
color: TEXT_LABEL,
|
|
27
|
+
fontSize: 10,
|
|
28
|
+
marginBottom: 2,
|
|
29
|
+
};
|
|
30
|
+
export const SECTION_STYLE = {
|
|
31
|
+
marginBottom: 6,
|
|
32
|
+
};
|
|
33
|
+
export const SCROLLABLE_STYLE = {
|
|
34
|
+
maxHeight: 200,
|
|
35
|
+
overflowY: "auto",
|
|
36
|
+
fontSize: 10,
|
|
37
|
+
lineHeight: "14px",
|
|
38
|
+
};
|
|
39
|
+
export const MINI_BUTTON = {
|
|
40
|
+
border: "none",
|
|
41
|
+
borderRadius: 4,
|
|
42
|
+
background: "rgba(255, 255, 255, 0.1)",
|
|
43
|
+
color: TEXT_COLOR,
|
|
44
|
+
fontSize: 10,
|
|
45
|
+
fontFamily: FONT_FAMILY,
|
|
46
|
+
cursor: "pointer",
|
|
47
|
+
padding: "2px 6px",
|
|
48
|
+
};
|
|
49
|
+
export const MINI_BUTTON_ACCENT = {
|
|
50
|
+
...MINI_BUTTON,
|
|
51
|
+
background: ACCENT_DIM,
|
|
52
|
+
};
|
|
53
|
+
export const INLINE_INPUT = {
|
|
54
|
+
background: "rgba(255, 255, 255, 0.08)",
|
|
55
|
+
border: "1px solid rgba(255, 255, 255, 0.15)",
|
|
56
|
+
borderRadius: 3,
|
|
57
|
+
color: TEXT_COLOR,
|
|
58
|
+
fontFamily: FONT_FAMILY,
|
|
59
|
+
fontSize: 10,
|
|
60
|
+
padding: "1px 4px",
|
|
61
|
+
width: 50,
|
|
62
|
+
outline: "none",
|
|
63
|
+
};
|
|
64
|
+
export function fpsColor(fps) {
|
|
65
|
+
if (fps >= 50)
|
|
66
|
+
return FPS_GREEN;
|
|
67
|
+
if (fps >= 30)
|
|
68
|
+
return FPS_YELLOW;
|
|
69
|
+
return FPS_RED;
|
|
70
|
+
}
|
|
71
|
+
export function fmt(n) {
|
|
72
|
+
return Number.isInteger(n) ? String(n) : n.toFixed(1);
|
|
73
|
+
}
|
|
74
|
+
export function shortId(id) {
|
|
75
|
+
return id.length > 8 ? `${id.slice(0, 8)}…` : id;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=styles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../src/styles.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural types matching SyncStatusTracker from @edv4h/usketch-store.
|
|
3
|
+
* Defined locally to avoid adding a dependency on the store package.
|
|
4
|
+
*/
|
|
5
|
+
export type SyncState = "loading" | "synced" | "syncing" | "error";
|
|
6
|
+
export interface SyncStatusSnapshot {
|
|
7
|
+
state: SyncState;
|
|
8
|
+
shapeCount: number;
|
|
9
|
+
lastSyncedAt: number | null;
|
|
10
|
+
error: string | null;
|
|
11
|
+
}
|
|
12
|
+
export interface SyncStatusTrackerLike {
|
|
13
|
+
getSnapshot(): SyncStatusSnapshot;
|
|
14
|
+
subscribe(listener: () => void): () => void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=sync-status-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-status-types.d.ts","sourceRoot":"","sources":["../src/sync-status-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAEnE,MAAM,WAAW,kBAAkB;IAClC,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACrC,WAAW,IAAI,kBAAkB,CAAC;IAClC,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CAC5C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-status-types.js","sourceRoot":"","sources":["../src/sync-status-types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@edv4h/usketch-plugin-debug-hud",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"source": "./src/index.ts",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@edv4h/usketch-shared": "1.0.0"
|
|
16
|
+
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"react": ">=19"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@types/react": "19.2.14",
|
|
22
|
+
"typescript": "5.9.3",
|
|
23
|
+
"vitest": "3.2.4"
|
|
24
|
+
},
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md"
|
|
31
|
+
],
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/EdV4H/usketch.git",
|
|
36
|
+
"directory": "plugins/usketch-plugin-debug-hud"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://github.com/EdV4H/usketch#readme",
|
|
39
|
+
"bugs": {
|
|
40
|
+
"url": "https://github.com/EdV4H/usketch/issues"
|
|
41
|
+
},
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsc -p tsconfig.json",
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"test": "vitest run --passWithNoTests",
|
|
46
|
+
"clean": "rm -rf dist"
|
|
47
|
+
}
|
|
48
|
+
}
|