@wasao/kagemusha 0.2.0 → 0.3.4

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.
Files changed (85) hide show
  1. package/README.md +103 -453
  2. package/dist/commands/capture.js +57 -35
  3. package/dist/commands/capture.js.map +1 -1
  4. package/dist/commands/edit.d.ts +1 -1
  5. package/dist/commands/edit.d.ts.map +1 -1
  6. package/dist/commands/edit.js +43 -7
  7. package/dist/commands/edit.js.map +1 -1
  8. package/dist/commands/init.d.ts.map +1 -1
  9. package/dist/commands/init.js +75 -44
  10. package/dist/commands/init.js.map +1 -1
  11. package/dist/commands/login.js +3 -14
  12. package/dist/commands/login.js.map +1 -1
  13. package/dist/editor/inject-script/annotations.d.ts +11 -0
  14. package/dist/editor/inject-script/annotations.d.ts.map +1 -0
  15. package/dist/editor/inject-script/annotations.js +409 -0
  16. package/dist/editor/inject-script/annotations.js.map +1 -0
  17. package/dist/editor/inject-script/bridge.d.ts +13 -0
  18. package/dist/editor/inject-script/bridge.d.ts.map +1 -0
  19. package/dist/editor/inject-script/bridge.js +33 -0
  20. package/dist/editor/inject-script/bridge.js.map +1 -0
  21. package/dist/editor/inject-script/crop.d.ts +9 -0
  22. package/dist/editor/inject-script/crop.d.ts.map +1 -0
  23. package/dist/editor/inject-script/crop.js +236 -0
  24. package/dist/editor/inject-script/crop.js.map +1 -0
  25. package/dist/editor/inject-script/dom.d.ts +7 -0
  26. package/dist/editor/inject-script/dom.d.ts.map +1 -0
  27. package/dist/editor/inject-script/dom.js +32 -0
  28. package/dist/editor/inject-script/dom.js.map +1 -0
  29. package/dist/editor/inject-script/index.d.ts +2 -0
  30. package/dist/editor/inject-script/index.d.ts.map +1 -0
  31. package/dist/editor/inject-script/index.js +56 -0
  32. package/dist/editor/inject-script/index.js.map +1 -0
  33. package/dist/editor/inject-script/record.d.ts +5 -0
  34. package/dist/editor/inject-script/record.d.ts.map +1 -0
  35. package/dist/editor/inject-script/record.js +398 -0
  36. package/dist/editor/inject-script/record.js.map +1 -0
  37. package/dist/editor/inject-script/selector.d.ts +6 -0
  38. package/dist/editor/inject-script/selector.d.ts.map +1 -0
  39. package/dist/editor/inject-script/selector.js +112 -0
  40. package/dist/editor/inject-script/selector.js.map +1 -0
  41. package/dist/editor/inject-script/state.d.ts +27 -0
  42. package/dist/editor/inject-script/state.d.ts.map +1 -0
  43. package/dist/editor/inject-script/state.js +26 -0
  44. package/dist/editor/inject-script/state.js.map +1 -0
  45. package/dist/editor/inject-script/svg.d.ts +7 -0
  46. package/dist/editor/inject-script/svg.d.ts.map +1 -0
  47. package/dist/editor/inject-script/svg.js +39 -0
  48. package/dist/editor/inject-script/svg.js.map +1 -0
  49. package/dist/editor/inject-script/toolbar.d.ts +14 -0
  50. package/dist/editor/inject-script/toolbar.d.ts.map +1 -0
  51. package/dist/editor/inject-script/toolbar.js +240 -0
  52. package/dist/editor/inject-script/toolbar.js.map +1 -0
  53. package/dist/editor/inject-script/types.d.ts +102 -0
  54. package/dist/editor/inject-script/types.d.ts.map +1 -0
  55. package/dist/editor/inject-script/types.js +5 -0
  56. package/dist/editor/inject-script/types.js.map +1 -0
  57. package/dist/editor/inject-script.js +1248 -699
  58. package/dist/index.js +9 -2
  59. package/dist/index.js.map +1 -1
  60. package/dist/lib/canonical.d.ts +35 -3
  61. package/dist/lib/canonical.d.ts.map +1 -1
  62. package/dist/lib/canonical.js +85 -25
  63. package/dist/lib/canonical.js.map +1 -1
  64. package/dist/lib/diff.d.ts +23 -4
  65. package/dist/lib/diff.d.ts.map +1 -1
  66. package/dist/lib/diff.js +5 -6
  67. package/dist/lib/diff.js.map +1 -1
  68. package/dist/lib/page-ready.d.ts +18 -0
  69. package/dist/lib/page-ready.d.ts.map +1 -0
  70. package/dist/lib/page-ready.js +19 -0
  71. package/dist/lib/page-ready.js.map +1 -0
  72. package/dist/lib/screenshot.d.ts +4 -1
  73. package/dist/lib/screenshot.d.ts.map +1 -1
  74. package/dist/lib/screenshot.js +31 -5
  75. package/dist/lib/screenshot.js.map +1 -1
  76. package/dist/lib/staging.d.ts +0 -1
  77. package/dist/lib/staging.d.ts.map +1 -1
  78. package/dist/lib/staging.js +0 -3
  79. package/dist/lib/staging.js.map +1 -1
  80. package/dist/types.d.ts +5 -0
  81. package/dist/types.d.ts.map +1 -1
  82. package/package.json +20 -10
  83. package/dist/editor/inject-script.d.ts +0 -2
  84. package/dist/editor/inject-script.d.ts.map +0 -1
  85. package/dist/editor/inject-script.js.map +0 -1
@@ -0,0 +1,39 @@
1
+ // SVG overlay layer — covers the entire page and hosts annotation shapes
2
+ // + crop visualization. Sits at z-index just below the toolbar.
3
+ import { SVG_NS } from "./state.js";
4
+ let svgEl = null;
5
+ let captureGroupEl = null;
6
+ export const initSvgLayer = () => {
7
+ const svg = document.createElementNS(SVG_NS, "svg");
8
+ svg.id = "kagemusha-svg-layer";
9
+ svg.classList.add("drawing");
10
+ document.documentElement.appendChild(svg);
11
+ const updateSvgSize = () => {
12
+ svg.setAttribute("width", String(window.innerWidth));
13
+ svg.setAttribute("height", String(document.documentElement.scrollHeight));
14
+ };
15
+ updateSvgSize();
16
+ window.addEventListener("resize", updateSvgSize);
17
+ const defs = document.createElementNS(SVG_NS, "defs");
18
+ defs.innerHTML =
19
+ '<marker id="kg-arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto" fill="#FF0000"><polygon points="0 0, 10 3.5, 0 7"/></marker>';
20
+ svg.appendChild(defs);
21
+ // Capture-region visualization goes BEFORE annotations so it renders behind.
22
+ const captureGroup = document.createElementNS(SVG_NS, "g");
23
+ captureGroup.id = "kagemusha-capture-group";
24
+ svg.appendChild(captureGroup);
25
+ svgEl = svg;
26
+ captureGroupEl = captureGroup;
27
+ return { svg, captureGroup };
28
+ };
29
+ export const getSvg = () => {
30
+ if (!svgEl)
31
+ throw new Error("SVG layer not initialized");
32
+ return svgEl;
33
+ };
34
+ export const getCaptureGroup = () => {
35
+ if (!captureGroupEl)
36
+ throw new Error("Capture group not initialized");
37
+ return captureGroupEl;
38
+ };
39
+ //# sourceMappingURL=svg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svg.js","sourceRoot":"","sources":["../../../src/editor/inject-script/svg.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,gEAAgE;AAEhE,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,IAAI,KAAK,GAAsB,IAAI,CAAC;AACpC,IAAI,cAAc,GAAuB,IAAI,CAAC;AAE9C,MAAM,CAAC,MAAM,YAAY,GAAG,GAG1B,EAAE;IACH,MAAM,GAAG,GAAG,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACpD,GAAG,CAAC,EAAE,GAAG,qBAAqB,CAAC;IAC/B,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC7B,QAAQ,CAAC,eAAe,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAE1C,MAAM,aAAa,GAAG,GAAG,EAAE;QAC1B,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;QACrD,GAAG,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC;IACF,aAAa,EAAE,CAAC;IAChB,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAEjD,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtD,IAAI,CAAC,SAAS;QACb,6JAA6J,CAAC;IAC/J,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAEtB,6EAA6E;IAC7E,MAAM,YAAY,GAAG,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,GAAG,CAAgB,CAAC;IAC1E,YAAY,CAAC,EAAE,GAAG,yBAAyB,CAAC;IAC5C,GAAG,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IAE9B,KAAK,GAAG,GAAG,CAAC;IACZ,cAAc,GAAG,YAAY,CAAC;IAC9B,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC;AAC9B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAG,GAAe,EAAE;IACtC,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACzD,OAAO,KAAK,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,GAAgB,EAAE;IAChD,IAAI,CAAC,cAAc;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACtE,OAAO,cAAc,CAAC;AACvB,CAAC,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { Tool } from "./types.js";
2
+ interface ToolbarCallbacks {
3
+ onToolChange: (next: Tool) => void;
4
+ onSave: () => void;
5
+ onDelete: () => void;
6
+ }
7
+ export declare const initToolbar: (cb: ToolbarCallbacks, svg: SVGElement) => void;
8
+ export declare const setTool: (t: Tool) => void;
9
+ export declare const setCaptureMode: (mode: "fullPage" | "crop", opts?: {
10
+ resetSelection?: boolean;
11
+ }) => void;
12
+ export declare const registerCropHooks: (onEnter: () => void, onExit: () => void) => void;
13
+ export {};
14
+ //# sourceMappingURL=toolbar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolbar.d.ts","sourceRoot":"","sources":["../../../src/editor/inject-script/toolbar.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAgHvC,UAAU,gBAAgB;IACzB,YAAY,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACnC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACrB;AAID,eAAO,MAAM,WAAW,GAAI,IAAI,gBAAgB,EAAE,KAAK,UAAU,KAAG,IA0CnE,CAAC;AAgEF,eAAO,MAAM,OAAO,GAAI,GAAG,IAAI,KAAG,IAcjC,CAAC;AAEF,eAAO,MAAM,cAAc,GAC1B,MAAM,UAAU,GAAG,MAAM,EACzB,OAAM;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAO,KACrC,IAcF,CAAC;AAGF,eAAO,MAAM,iBAAiB,GAC7B,SAAS,MAAM,IAAI,EACnB,QAAQ,MAAM,IAAI,KAChB,IAGF,CAAC"}
@@ -0,0 +1,240 @@
1
+ // Toolbar — floating bar of annotation/capture controls, draggable by its
2
+ // ⋮⋮ handle. Appended to <html> so host SPA modals that mark <body>'s
3
+ // children as `inert` / `aria-hidden="true"` don't disable interactions.
4
+ //
5
+ // No coordinate offset is applied — the toolbar is purely an overlay, host
6
+ // page content stays at its native document positions. Annotations are
7
+ // recorded in raw page coordinates (= `e.pageX/Y`) so what you draw in edit
8
+ // is exactly what kagemusha screenshots at capture time. If the toolbar
9
+ // covers content the user wants to annotate, drag it out of the way.
10
+ import { state } from "./state.js";
11
+ const TOOLBAR_HTML = `
12
+ <style>
13
+ /* INT_MAX guarantees kagemusha UI sits above any host SPA dialog / modal. */
14
+ :root {
15
+ --kg-z-top: 2147483647;
16
+ --kg-z-below-top: 2147483646;
17
+ }
18
+ #kagemusha-toolbar {
19
+ position: fixed; top: 16px; left: 16px; z-index: var(--kg-z-top);
20
+ background: #16213e; padding: 8px 16px; display: flex; align-items: center; gap: 10px;
21
+ box-shadow: 0 4px 16px rgba(0,0,0,0.35); font-family: -apple-system, sans-serif;
22
+ flex-wrap: nowrap; overflow-x: auto;
23
+ border-radius: 10px;
24
+ max-width: calc(100vw - 32px);
25
+ }
26
+ #kagemusha-toolbar .kg-drag-handle {
27
+ cursor: move; padding: 4px 6px; margin: -2px 2px -2px -10px;
28
+ color: #888; font-size: 14px; line-height: 1; user-select: none;
29
+ border-right: 1px solid #2a2a4e;
30
+ }
31
+ #kagemusha-toolbar .kg-drag-handle:hover { color: #fff; }
32
+ #kagemusha-toolbar.kg-dragging { opacity: 0.95; cursor: grabbing; }
33
+ #kagemusha-toolbar button {
34
+ padding: 6px 12px; border: 1px solid #444; border-radius: 6px;
35
+ background: #1a1a2e; color: #fff; font-size: 13px; cursor: pointer;
36
+ }
37
+ #kagemusha-toolbar button:hover { background: #2a2a4e; }
38
+ #kagemusha-toolbar button.active { background: #6366f1; border-color: #6366f1; }
39
+ #kagemusha-toolbar button.cap-btn.active { background: #0ea5e9; border-color: #0ea5e9; }
40
+ #kagemusha-toolbar button#kg-record.active { background: #ef4444; border-color: #ef4444; }
41
+ #kagemusha-toolbar button.picking {
42
+ background: #0ea5e9; border-color: #0ea5e9; color: #fff;
43
+ box-shadow: 0 0 0 2px rgba(14,165,233,0.4);
44
+ animation: kg-picking-pulse 1.2s ease-in-out infinite;
45
+ }
46
+ @keyframes kg-picking-pulse {
47
+ 0%, 100% { box-shadow: 0 0 0 2px rgba(14,165,233,0.4); }
48
+ 50% { box-shadow: 0 0 0 6px rgba(14,165,233,0.1); }
49
+ }
50
+ #kagemusha-toolbar button:disabled { opacity: 0.4; cursor: not-allowed; }
51
+ #kagemusha-toolbar #kg-rec-group { display: none; align-items: center; gap: 10px; }
52
+ #kagemusha-toolbar #kg-rec-group.visible { display: flex; }
53
+ #kagemusha-toolbar #kg-steps-toggle.has-steps { background: #6366f1; border-color: #6366f1; }
54
+ #kagemusha-toolbar #kg-steps-toggle.open { background: #6366f1; border-color: #6366f1; }
55
+ .kagemusha-picker-outline {
56
+ position: fixed; border: 2px solid #0ea5e9;
57
+ background: rgba(14,165,233,0.08); pointer-events: none;
58
+ z-index: var(--kg-z-below-top); border-radius: 2px;
59
+ transition: all 60ms ease-out;
60
+ }
61
+ #kagemusha-toolbar .sep { width: 1px; height: 24px; background: #444; }
62
+ #kagemusha-toolbar .title { color: #888; font-size: 13px; }
63
+ #kagemusha-toolbar .group-label { color: #7a89b0; font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; margin-right: -4px; }
64
+ #kagemusha-toolbar .save-btn { background: #22c55e; border-color: #22c55e; font-weight: 600; margin-left: auto; }
65
+ #kagemusha-toolbar .save-btn:hover { background: #16a34a; }
66
+ #kagemusha-svg-layer {
67
+ position: absolute; top: 0; left: 0; width: 100%;
68
+ z-index: var(--kg-z-below-top); pointer-events: none;
69
+ }
70
+ #kagemusha-svg-layer.drawing { pointer-events: auto; cursor: crosshair; }
71
+ #kagemusha-svg-layer.cropping { pointer-events: auto; cursor: crosshair; }
72
+ #kagemusha-svg-layer .annotation { pointer-events: auto; cursor: move; }
73
+ #kagemusha-svg-layer.cropping .annotation { pointer-events: none; }
74
+ #kagemusha-svg-layer .annotation.selected { filter: drop-shadow(0 0 3px #6366f1); }
75
+ #kagemusha-svg-layer .capture-crop-box { fill: rgba(14,165,233,0.10); stroke: #0ea5e9; stroke-width: 2; stroke-dasharray: 8 4; pointer-events: none; }
76
+ #kagemusha-svg-layer.cropping .capture-crop-box { pointer-events: auto; cursor: move; }
77
+ #kagemusha-svg-layer .crop-handle { fill: #fff; stroke: #0ea5e9; stroke-width: 2; pointer-events: none; }
78
+ #kagemusha-svg-layer.cropping .crop-handle { pointer-events: auto; }
79
+ #kagemusha-svg-layer .crop-handle.nw, #kagemusha-svg-layer .crop-handle.se { cursor: nwse-resize; }
80
+ #kagemusha-svg-layer .crop-handle.ne, #kagemusha-svg-layer .crop-handle.sw { cursor: nesw-resize; }
81
+ #kagemusha-svg-layer .crop-handle.n, #kagemusha-svg-layer .crop-handle.s { cursor: ns-resize; }
82
+ #kagemusha-svg-layer .crop-handle.e, #kagemusha-svg-layer .crop-handle.w { cursor: ew-resize; }
83
+ .kagemusha-hint {
84
+ position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%);
85
+ color: #fff; background: rgba(0,0,0,0.7); padding: 6px 16px; border-radius: 8px;
86
+ font-size: 12px; z-index: var(--kg-z-top); font-family: -apple-system, sans-serif;
87
+ }
88
+ </style>
89
+ <span class="kg-drag-handle" title="Drag to move toolbar">⋮⋮</span>
90
+ <span class="title">🥷</span>
91
+ <div class="sep"></div>
92
+ <span class="group-label">Capture</span>
93
+ <button id="kg-cap-full" class="cap-btn active">📷 Full</button>
94
+ <button id="kg-cap-crop" class="cap-btn">✂️ Crop</button>
95
+ <div class="sep"></div>
96
+ <span class="group-label">Annotate</span>
97
+ <button id="kg-tool-rect" class="active">▭ Rect</button>
98
+ <button id="kg-tool-arrow">→ Arrow</button>
99
+ <button id="kg-tool-label">T Label</button>
100
+ <div class="sep"></div>
101
+ <span class="group-label">Pre-steps</span>
102
+ <button id="kg-record">🔴 Record</button>
103
+ <div id="kg-rec-group">
104
+ <button id="kg-rec-wait">+ Wait</button>
105
+ <button id="kg-rec-wfs">+ WaitForSelector</button>
106
+ <button id="kg-rec-hover">+ Hover</button>
107
+ </div>
108
+ <button id="kg-steps-toggle">📋 Steps (0)</button>
109
+ <div class="sep"></div>
110
+ <button id="kg-delete">🗑 Delete</button>
111
+ <button class="save-btn" id="kg-save">💾 Save</button>
112
+ `;
113
+ let svgRef = null;
114
+ // Crop module registers visual hooks via `registerCropHooks` after init.
115
+ // Setter-based wiring avoids a circular import (toolbar → crop → toolbar).
116
+ let cropOnEnter = () => { };
117
+ let cropOnExit = () => { };
118
+ let callbacks = null;
119
+ export const initToolbar = (cb, svg) => {
120
+ callbacks = cb;
121
+ svgRef = svg;
122
+ const toolbar = document.createElement("div");
123
+ toolbar.id = "kagemusha-toolbar";
124
+ toolbar.innerHTML = TOOLBAR_HTML;
125
+ // Append to <html> (not <body>) so SPA modals that mark <body>'s children
126
+ // as `inert` / `aria-hidden="true"` don't disable our toolbar interactions.
127
+ document.documentElement.appendChild(toolbar);
128
+ const hint = document.createElement("div");
129
+ hint.className = "kagemusha-hint";
130
+ hint.textContent =
131
+ "Click and drag to add annotations. Click to select. Press Delete to remove.";
132
+ document.documentElement.appendChild(hint);
133
+ document
134
+ .getElementById("kg-tool-rect")
135
+ ?.addEventListener("click", () => setTool("rect"));
136
+ document
137
+ .getElementById("kg-tool-arrow")
138
+ ?.addEventListener("click", () => setTool("arrow"));
139
+ document
140
+ .getElementById("kg-tool-label")
141
+ ?.addEventListener("click", () => setTool("label"));
142
+ document
143
+ .getElementById("kg-cap-full")
144
+ ?.addEventListener("click", () => setCaptureMode("fullPage"));
145
+ document
146
+ .getElementById("kg-cap-crop")
147
+ ?.addEventListener("click", () => setCaptureMode("crop", { resetSelection: !state.captureCrop }));
148
+ document
149
+ .getElementById("kg-delete")
150
+ ?.addEventListener("click", () => cb.onDelete());
151
+ document
152
+ .getElementById("kg-save")
153
+ ?.addEventListener("click", () => cb.onSave());
154
+ wireDragHandle(toolbar);
155
+ };
156
+ // Drag the toolbar by its ⋮⋮ handle. Position is clamped to the viewport so
157
+ // it can't slip off-screen. Kept simple — no docking magic or persistence.
158
+ const wireDragHandle = (toolbar) => {
159
+ const handle = toolbar.querySelector(".kg-drag-handle");
160
+ if (!handle)
161
+ return;
162
+ let dragging = false;
163
+ let offsetX = 0;
164
+ let offsetY = 0;
165
+ handle.addEventListener("mousedown", (e) => {
166
+ const m = e;
167
+ m.preventDefault();
168
+ const rect = toolbar.getBoundingClientRect();
169
+ offsetX = m.clientX - rect.left;
170
+ offsetY = m.clientY - rect.top;
171
+ dragging = true;
172
+ toolbar.classList.add("kg-dragging");
173
+ // Prevent text selection while dragging.
174
+ document.body.style.userSelect = "none";
175
+ });
176
+ document.addEventListener("mousemove", (e) => {
177
+ if (!dragging)
178
+ return;
179
+ const x = Math.max(0, Math.min(window.innerWidth - toolbar.offsetWidth, e.clientX - offsetX));
180
+ const y = Math.max(0, Math.min(window.innerHeight - toolbar.offsetHeight, e.clientY - offsetY));
181
+ toolbar.style.left = `${x}px`;
182
+ toolbar.style.top = `${y}px`;
183
+ });
184
+ document.addEventListener("mouseup", () => {
185
+ if (!dragging)
186
+ return;
187
+ dragging = false;
188
+ toolbar.classList.remove("kg-dragging");
189
+ document.body.style.userSelect = "";
190
+ });
191
+ };
192
+ const updateCaptureUi = () => {
193
+ document
194
+ .querySelectorAll("#kagemusha-toolbar .cap-btn")
195
+ .forEach((b) => {
196
+ b.classList.remove("active");
197
+ });
198
+ const activeId = state.captureMode === "fullPage" ? "kg-cap-full" : "kg-cap-crop";
199
+ document.getElementById(activeId)?.classList.add("active");
200
+ if (svgRef) {
201
+ svgRef.classList.toggle("cropping", state.tool === "crop");
202
+ svgRef.classList.toggle("drawing", state.tool === "rect" || state.tool === "arrow" || state.tool === "label");
203
+ }
204
+ };
205
+ export const setTool = (t) => {
206
+ state.tool = t;
207
+ document
208
+ .querySelectorAll("#kg-tool-rect, #kg-tool-arrow, #kg-tool-label")
209
+ .forEach((b) => {
210
+ b.classList.remove("active");
211
+ });
212
+ if (t === "rect" || t === "arrow" || t === "label") {
213
+ document.getElementById(`kg-tool-${t}`)?.classList.add("active");
214
+ }
215
+ updateCaptureUi();
216
+ callbacks?.onToolChange(t);
217
+ };
218
+ export const setCaptureMode = (mode, opts = {}) => {
219
+ state.captureMode = mode;
220
+ if (mode === "fullPage") {
221
+ state.captureCrop = null;
222
+ cropOnExit();
223
+ setTool("rect");
224
+ }
225
+ else {
226
+ if (opts.resetSelection)
227
+ state.captureCrop = null;
228
+ cropOnEnter();
229
+ // Switch tool indicator but leave the visual state of crop selection alone
230
+ state.tool = "crop";
231
+ updateCaptureUi();
232
+ }
233
+ callbacks?.onToolChange(state.tool);
234
+ };
235
+ // Allow crop module to register its visual-clear / redraw hooks.
236
+ export const registerCropHooks = (onEnter, onExit) => {
237
+ cropOnEnter = onEnter;
238
+ cropOnExit = onExit;
239
+ };
240
+ //# sourceMappingURL=toolbar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolbar.js","sourceRoot":"","sources":["../../../src/editor/inject-script/toolbar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,102 @@
1
+ export type { CaptureAction, ScreenshotDefinition, } from "../../types.js";
2
+ export interface Decoration {
3
+ type: "rect" | "arrow" | "label";
4
+ target?: {
5
+ x: number;
6
+ y: number;
7
+ width: number;
8
+ height: number;
9
+ };
10
+ from?: {
11
+ x: number;
12
+ y: number;
13
+ };
14
+ to?: {
15
+ x: number;
16
+ y: number;
17
+ };
18
+ position?: {
19
+ x: number;
20
+ y: number;
21
+ };
22
+ text?: string;
23
+ style?: {
24
+ color?: string;
25
+ strokeWidth?: number;
26
+ fontSize?: number;
27
+ background?: string;
28
+ };
29
+ }
30
+ export type CaptureSpec = {
31
+ mode: "fullPage";
32
+ } | {
33
+ mode: "crop";
34
+ crop: {
35
+ start: {
36
+ x: number;
37
+ y: number;
38
+ };
39
+ end: {
40
+ x: number;
41
+ y: number;
42
+ };
43
+ };
44
+ };
45
+ export interface Annotation {
46
+ id: string;
47
+ type: "rect" | "arrow" | "label";
48
+ x?: number;
49
+ y?: number;
50
+ width?: number;
51
+ height?: number;
52
+ fromX?: number;
53
+ fromY?: number;
54
+ toX?: number;
55
+ toY?: number;
56
+ text?: string;
57
+ }
58
+ export interface DragState {
59
+ type: "create-rect" | "create-arrow" | "move";
60
+ id: string;
61
+ el: SVGElement;
62
+ sx?: number;
63
+ sy?: number;
64
+ lastX?: number;
65
+ lastY?: number;
66
+ }
67
+ export type CropHandle = "nw" | "ne" | "sw" | "se" | "n" | "s" | "e" | "w";
68
+ export type CropDragState = {
69
+ kind: "create";
70
+ sx: number;
71
+ sy: number;
72
+ } | {
73
+ kind: "move";
74
+ sx: number;
75
+ sy: number;
76
+ orig: {
77
+ x: number;
78
+ y: number;
79
+ w: number;
80
+ h: number;
81
+ };
82
+ } | {
83
+ kind: "resize";
84
+ handle: CropHandle;
85
+ sx: number;
86
+ sy: number;
87
+ orig: {
88
+ x: number;
89
+ y: number;
90
+ w: number;
91
+ h: number;
92
+ };
93
+ };
94
+ export type Tool = "rect" | "arrow" | "label" | "crop";
95
+ import type { CaptureAction } from "../../types.js";
96
+ export interface EditorBridge {
97
+ __kagemusha_save: (payloadJson: string) => void;
98
+ __kagemusha_loadAnnotations: (decorations: Decoration[]) => void;
99
+ __kagemusha_loadCapture: (capture: CaptureSpec) => void;
100
+ __kagemusha_loadSteps: (steps: CaptureAction[]) => void;
101
+ }
102
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/editor/inject-script/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ // Shared types for the inject editor. Kept in one file because the page-scoped
2
+ // editor is small enough to avoid one-type-per-file overhead — and the GUI
3
+ // rewrite will likely consume these as a single import.
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/editor/inject-script/types.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,2EAA2E;AAC3E,wDAAwD"}