@insitue/sdk 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +203 -0
- package/dist/capture-only.d.ts +26 -16
- package/dist/capture-only.js +1 -2
- package/dist/{chunk-62N4L6RA.js → chunk-BCKDBCPG.js} +781 -68
- package/dist/index.d.ts +52 -25
- package/dist/index.js +26 -25
- package/package.json +1 -6
- package/dist/chunk-VRINS2SK.js +0 -1236
- package/dist/chunk-ZV3AVYBI.js +0 -400
- package/dist/overlay.d.ts +0 -6
- package/dist/overlay.js +0 -7
|
@@ -682,9 +682,6 @@ function installRuntimeCollectors() {
|
|
|
682
682
|
});
|
|
683
683
|
});
|
|
684
684
|
}
|
|
685
|
-
function runtimeErrorCount() {
|
|
686
|
-
return errorBuf.length;
|
|
687
|
-
}
|
|
688
685
|
function runtimeSnapshot() {
|
|
689
686
|
return {
|
|
690
687
|
console: consoleBuf.slice(),
|
|
@@ -802,54 +799,6 @@ function beginPick(mode = "element") {
|
|
|
802
799
|
});
|
|
803
800
|
}
|
|
804
801
|
|
|
805
|
-
// src/capture-settings.ts
|
|
806
|
-
var DEFAULT_SETTINGS = {
|
|
807
|
-
alwaysPixelPerfect: false,
|
|
808
|
-
disableLayer2: false
|
|
809
|
-
};
|
|
810
|
-
function storageKey() {
|
|
811
|
-
if (typeof location === "undefined") return "insitu:capture-settings";
|
|
812
|
-
return `insitu:capture-settings:${location.host}`;
|
|
813
|
-
}
|
|
814
|
-
var cached = null;
|
|
815
|
-
function getCaptureSettings() {
|
|
816
|
-
if (cached) return cached;
|
|
817
|
-
if (typeof localStorage === "undefined") {
|
|
818
|
-
cached = { ...DEFAULT_SETTINGS };
|
|
819
|
-
return cached;
|
|
820
|
-
}
|
|
821
|
-
try {
|
|
822
|
-
const raw = localStorage.getItem(storageKey());
|
|
823
|
-
if (!raw) {
|
|
824
|
-
cached = { ...DEFAULT_SETTINGS };
|
|
825
|
-
return cached;
|
|
826
|
-
}
|
|
827
|
-
const parsed = JSON.parse(raw);
|
|
828
|
-
cached = { ...DEFAULT_SETTINGS, ...parsed };
|
|
829
|
-
return cached;
|
|
830
|
-
} catch {
|
|
831
|
-
cached = { ...DEFAULT_SETTINGS };
|
|
832
|
-
return cached;
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
function setCaptureSettings(patch) {
|
|
836
|
-
const next = { ...getCaptureSettings(), ...patch };
|
|
837
|
-
cached = next;
|
|
838
|
-
if (typeof localStorage !== "undefined") {
|
|
839
|
-
try {
|
|
840
|
-
localStorage.setItem(storageKey(), JSON.stringify(next));
|
|
841
|
-
} catch {
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
for (const l3 of listeners) l3(next);
|
|
845
|
-
}
|
|
846
|
-
var listeners = /* @__PURE__ */ new Set();
|
|
847
|
-
function onCaptureSettingsChange(l3) {
|
|
848
|
-
listeners.add(l3);
|
|
849
|
-
l3(getCaptureSettings());
|
|
850
|
-
return () => listeners.delete(l3);
|
|
851
|
-
}
|
|
852
|
-
|
|
853
802
|
// ../../node_modules/.pnpm/html-to-image@1.11.13/node_modules/html-to-image/es/util.js
|
|
854
803
|
function resolveUrl(url, baseUrl) {
|
|
855
804
|
if (url.match(/^[a-z]+:\/\//i)) {
|
|
@@ -1641,6 +1590,49 @@ async function toCanvas(node, options = {}) {
|
|
|
1641
1590
|
return canvas;
|
|
1642
1591
|
}
|
|
1643
1592
|
|
|
1593
|
+
// src/capture-settings.ts
|
|
1594
|
+
var DEFAULT_SETTINGS = {
|
|
1595
|
+
alwaysPixelPerfect: false,
|
|
1596
|
+
disableLayer2: false
|
|
1597
|
+
};
|
|
1598
|
+
function storageKey() {
|
|
1599
|
+
if (typeof location === "undefined") return "insitu:capture-settings";
|
|
1600
|
+
return `insitu:capture-settings:${location.host}`;
|
|
1601
|
+
}
|
|
1602
|
+
var cached = null;
|
|
1603
|
+
function getCaptureSettings() {
|
|
1604
|
+
if (cached) return cached;
|
|
1605
|
+
if (typeof localStorage === "undefined") {
|
|
1606
|
+
cached = { ...DEFAULT_SETTINGS };
|
|
1607
|
+
return cached;
|
|
1608
|
+
}
|
|
1609
|
+
try {
|
|
1610
|
+
const raw = localStorage.getItem(storageKey());
|
|
1611
|
+
if (!raw) {
|
|
1612
|
+
cached = { ...DEFAULT_SETTINGS };
|
|
1613
|
+
return cached;
|
|
1614
|
+
}
|
|
1615
|
+
const parsed = JSON.parse(raw);
|
|
1616
|
+
cached = { ...DEFAULT_SETTINGS, ...parsed };
|
|
1617
|
+
return cached;
|
|
1618
|
+
} catch {
|
|
1619
|
+
cached = { ...DEFAULT_SETTINGS };
|
|
1620
|
+
return cached;
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
function setCaptureSettings(patch) {
|
|
1624
|
+
const next = { ...getCaptureSettings(), ...patch };
|
|
1625
|
+
cached = next;
|
|
1626
|
+
if (typeof localStorage !== "undefined") {
|
|
1627
|
+
try {
|
|
1628
|
+
localStorage.setItem(storageKey(), JSON.stringify(next));
|
|
1629
|
+
} catch {
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
for (const l3 of listeners) l3(next);
|
|
1633
|
+
}
|
|
1634
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
1635
|
+
|
|
1644
1636
|
// src/capture.ts
|
|
1645
1637
|
var IMAGE_PLACEHOLDER = "data:image/svg+xml;base64," + (typeof btoa !== "undefined" ? btoa(
|
|
1646
1638
|
'<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32"><rect width="32" height="32" fill="#e8e8e8"/><path d="M0 0 L32 32 M32 0 L0 32" stroke="#b0b0b0" stroke-width="1.5"/></svg>'
|
|
@@ -2230,22 +2222,743 @@ async function buildBundle(sel) {
|
|
|
2230
2222
|
};
|
|
2231
2223
|
}
|
|
2232
2224
|
|
|
2225
|
+
// src/client.ts
|
|
2226
|
+
var CompanionClient = class {
|
|
2227
|
+
constructor(port, events) {
|
|
2228
|
+
this.port = port;
|
|
2229
|
+
this.events = events;
|
|
2230
|
+
this.base = `http://127.0.0.1:${port}`;
|
|
2231
|
+
this.wsUrl = `ws://127.0.0.1:${port}`;
|
|
2232
|
+
}
|
|
2233
|
+
port;
|
|
2234
|
+
events;
|
|
2235
|
+
ws = null;
|
|
2236
|
+
base;
|
|
2237
|
+
wsUrl;
|
|
2238
|
+
pending = /* @__PURE__ */ new Map();
|
|
2239
|
+
async connect() {
|
|
2240
|
+
this.events.onState("connecting");
|
|
2241
|
+
let token;
|
|
2242
|
+
try {
|
|
2243
|
+
const res = await fetch(`${this.base}/insitu/handshake`);
|
|
2244
|
+
if (!res.ok) throw new Error(`handshake ${res.status}`);
|
|
2245
|
+
token = (await res.json()).token;
|
|
2246
|
+
} catch (e3) {
|
|
2247
|
+
this.events.onState("error", `companion unreachable (run \`npx insitue\`)`);
|
|
2248
|
+
return;
|
|
2249
|
+
}
|
|
2250
|
+
await new Promise((done) => {
|
|
2251
|
+
const ws = new WebSocket(this.wsUrl);
|
|
2252
|
+
this.ws = ws;
|
|
2253
|
+
ws.onopen = () => ws.send(
|
|
2254
|
+
JSON.stringify({ t: "hello", protocolVersion: PROTOCOL_VERSION, token })
|
|
2255
|
+
);
|
|
2256
|
+
ws.onmessage = (ev) => {
|
|
2257
|
+
const msg = JSON.parse(ev.data);
|
|
2258
|
+
if (msg.t === "hello-ok") {
|
|
2259
|
+
this.events.onState("connected", `companion ${msg.companionVersion}`);
|
|
2260
|
+
done();
|
|
2261
|
+
} else if (msg.t === "pong") {
|
|
2262
|
+
const cb = this.pending.get(msg.nonce);
|
|
2263
|
+
if (cb) {
|
|
2264
|
+
this.pending.delete(msg.nonce);
|
|
2265
|
+
cb(performance.now() - Number(msg.nonce.split(":")[1]));
|
|
2266
|
+
}
|
|
2267
|
+
} else if (msg.t === "agent-status") {
|
|
2268
|
+
this.events.onAgentStatus?.({
|
|
2269
|
+
ready: msg.ready,
|
|
2270
|
+
transport: msg.transport,
|
|
2271
|
+
warnings: msg.warnings,
|
|
2272
|
+
blockers: msg.blockers
|
|
2273
|
+
});
|
|
2274
|
+
} else if (msg.t === "agent-stream") {
|
|
2275
|
+
this.events.onAgentEvent?.(msg.event);
|
|
2276
|
+
} else if (msg.t === "changeset-proposed") {
|
|
2277
|
+
this.events.onChangeset?.(msg.turnId, msg.files);
|
|
2278
|
+
} else if (msg.t === "changeset-applied") {
|
|
2279
|
+
this.events.onApplied?.(
|
|
2280
|
+
msg.turnId,
|
|
2281
|
+
msg.files,
|
|
2282
|
+
msg.checkpointRef
|
|
2283
|
+
);
|
|
2284
|
+
} else if (msg.t === "agent-undone") {
|
|
2285
|
+
this.events.onUndone?.(msg.turnId, msg.restored);
|
|
2286
|
+
} else if (msg.t === "agent-session-undone") {
|
|
2287
|
+
this.events.onSessionUndone?.(msg.restored);
|
|
2288
|
+
} else if (msg.t === "agent-session-committed") {
|
|
2289
|
+
this.events.onSessionCommitted?.(msg.commit, msg.files);
|
|
2290
|
+
} else if (msg.t === "capture-resolved") {
|
|
2291
|
+
this.events.onResolved?.(msg.id, msg.resolved, msg.note);
|
|
2292
|
+
} else if (msg.t === "subscribers-attached") {
|
|
2293
|
+
this.events.onSubscribersAttached?.(msg.count);
|
|
2294
|
+
} else if (msg.t === "error") {
|
|
2295
|
+
this.events.onState("error", `${msg.code}: ${msg.message}`);
|
|
2296
|
+
done();
|
|
2297
|
+
}
|
|
2298
|
+
};
|
|
2299
|
+
ws.onerror = () => {
|
|
2300
|
+
this.events.onState("error", "websocket error");
|
|
2301
|
+
done();
|
|
2302
|
+
};
|
|
2303
|
+
ws.onclose = () => {
|
|
2304
|
+
if (this.ws === ws) this.events.onState("idle");
|
|
2305
|
+
};
|
|
2306
|
+
});
|
|
2307
|
+
}
|
|
2308
|
+
ping() {
|
|
2309
|
+
return new Promise((resolve, reject) => {
|
|
2310
|
+
const ws = this.ws;
|
|
2311
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) {
|
|
2312
|
+
reject(new Error("not connected"));
|
|
2313
|
+
return;
|
|
2314
|
+
}
|
|
2315
|
+
const nonce = `n:${performance.now()}:${Math.random()}`;
|
|
2316
|
+
this.pending.set(nonce, resolve);
|
|
2317
|
+
ws.send(JSON.stringify({ t: "ping", nonce }));
|
|
2318
|
+
setTimeout(() => {
|
|
2319
|
+
if (this.pending.delete(nonce)) reject(new Error("ping timeout"));
|
|
2320
|
+
}, 3e3);
|
|
2321
|
+
});
|
|
2322
|
+
}
|
|
2323
|
+
submitCapture(bundle) {
|
|
2324
|
+
const ws = this.ws;
|
|
2325
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) return false;
|
|
2326
|
+
ws.send(JSON.stringify({ t: "capture", bundle }));
|
|
2327
|
+
return true;
|
|
2328
|
+
}
|
|
2329
|
+
sendTurn(turnId, bundleId, userMessage) {
|
|
2330
|
+
const ws = this.ws;
|
|
2331
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) return false;
|
|
2332
|
+
ws.send(
|
|
2333
|
+
JSON.stringify({ t: "agent-turn", turnId, bundleId, userMessage })
|
|
2334
|
+
);
|
|
2335
|
+
return true;
|
|
2336
|
+
}
|
|
2337
|
+
/** #162: route the user's typed intent to a CLI/MCP subscriber
|
|
2338
|
+
* (e.g. claude with `/insitue:connect` open) instead of the
|
|
2339
|
+
* in-overlay headless agent. No reply arrives back through this
|
|
2340
|
+
* client — the external claude shows its work in its own
|
|
2341
|
+
* terminal. Callers should switch the panel UI to a "Sent to
|
|
2342
|
+
* claude in your terminal" affordance after this returns. */
|
|
2343
|
+
sendAsk(turnId, bundleId, text) {
|
|
2344
|
+
const ws = this.ws;
|
|
2345
|
+
if (!ws || ws.readyState !== WebSocket.OPEN) return false;
|
|
2346
|
+
ws.send(
|
|
2347
|
+
JSON.stringify({ t: "agent-ask-external", turnId, bundleId, text })
|
|
2348
|
+
);
|
|
2349
|
+
return true;
|
|
2350
|
+
}
|
|
2351
|
+
cancelTurn(turnId) {
|
|
2352
|
+
this.ws?.send(JSON.stringify({ t: "agent-cancel", turnId }));
|
|
2353
|
+
}
|
|
2354
|
+
sendDecision(turnId, decision, files, reason) {
|
|
2355
|
+
this.ws?.send(
|
|
2356
|
+
JSON.stringify({ t: "agent-decision", turnId, decision, files, reason })
|
|
2357
|
+
);
|
|
2358
|
+
}
|
|
2359
|
+
sendUndo(turnId) {
|
|
2360
|
+
this.ws?.send(JSON.stringify({ t: "agent-undo", turnId }));
|
|
2361
|
+
}
|
|
2362
|
+
sendUndoSession() {
|
|
2363
|
+
this.ws?.send(JSON.stringify({ t: "agent-undo-session" }));
|
|
2364
|
+
}
|
|
2365
|
+
sendCommitSession(message) {
|
|
2366
|
+
this.ws?.send(JSON.stringify({ t: "agent-commit-session", message }));
|
|
2367
|
+
}
|
|
2368
|
+
dispose() {
|
|
2369
|
+
this.ws?.close();
|
|
2370
|
+
this.ws = null;
|
|
2371
|
+
}
|
|
2372
|
+
};
|
|
2373
|
+
|
|
2374
|
+
// src/capture-only.ts
|
|
2375
|
+
var DEFAULT_INGEST = "https://www.insitue.com/api/v1/capture";
|
|
2376
|
+
var DEFAULT_COMPANION_PORT = 5747;
|
|
2377
|
+
function resolveSink(opts) {
|
|
2378
|
+
if (opts.sink) return opts.sink;
|
|
2379
|
+
if (opts.projectKey) {
|
|
2380
|
+
return opts.endpoint ? {
|
|
2381
|
+
kind: "cloud",
|
|
2382
|
+
projectKey: opts.projectKey,
|
|
2383
|
+
endpoint: opts.endpoint
|
|
2384
|
+
} : { kind: "cloud", projectKey: opts.projectKey };
|
|
2385
|
+
}
|
|
2386
|
+
return { kind: "companion" };
|
|
2387
|
+
}
|
|
2388
|
+
async function postCloud(sink, draft) {
|
|
2389
|
+
const endpoint = sink.endpoint ?? DEFAULT_INGEST;
|
|
2390
|
+
try {
|
|
2391
|
+
await fetch(endpoint, {
|
|
2392
|
+
method: "POST",
|
|
2393
|
+
headers: {
|
|
2394
|
+
"content-type": "application/json",
|
|
2395
|
+
"x-insitue-key": sink.projectKey
|
|
2396
|
+
},
|
|
2397
|
+
body: JSON.stringify({
|
|
2398
|
+
bundle: draft.bundle,
|
|
2399
|
+
note: draft.bundle.userNote ?? null,
|
|
2400
|
+
projectKey: sink.projectKey
|
|
2401
|
+
}),
|
|
2402
|
+
credentials: "omit",
|
|
2403
|
+
keepalive: true
|
|
2404
|
+
});
|
|
2405
|
+
} catch {
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
var CLOUD = {
|
|
2409
|
+
ink: "#16161a",
|
|
2410
|
+
sub: "#6b6c77",
|
|
2411
|
+
faint: "#9a9aa4",
|
|
2412
|
+
line: "#e9e9ee",
|
|
2413
|
+
surface: "#ffffff",
|
|
2414
|
+
surface2: "#f6f6f9",
|
|
2415
|
+
accent: "linear-gradient(180deg,#6b63ff,#5751e6)",
|
|
2416
|
+
accentSolid: "#5751e6",
|
|
2417
|
+
accentRing: "rgba(91,91,240,.30)",
|
|
2418
|
+
good: "#117a52",
|
|
2419
|
+
goodBg: "#ecfdf5",
|
|
2420
|
+
goodLine: "#b6e6cf",
|
|
2421
|
+
warnBg: "#fff7ed",
|
|
2422
|
+
warnLine: "#fbd9b1",
|
|
2423
|
+
warnInk: "#8a4b00",
|
|
2424
|
+
sans: '-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,"Helvetica Neue",Arial,sans-serif',
|
|
2425
|
+
mono: 'ui-monospace,"SF Mono",SFMono-Regular,Menlo,monospace',
|
|
2426
|
+
shadow: "0 12px 40px rgba(20,20,35,.16),0 2px 8px rgba(20,20,35,.08)",
|
|
2427
|
+
buttonInk: "#ffffff"
|
|
2428
|
+
};
|
|
2429
|
+
var DEV = {
|
|
2430
|
+
ink: "#ececef",
|
|
2431
|
+
sub: "#a0a0aa",
|
|
2432
|
+
faint: "#6b6b75",
|
|
2433
|
+
line: "#26262d",
|
|
2434
|
+
surface: "#13131a",
|
|
2435
|
+
surface2: "#1a1a22",
|
|
2436
|
+
accent: "linear-gradient(180deg,#ff8240,#ff6b00)",
|
|
2437
|
+
accentSolid: "#ff6b00",
|
|
2438
|
+
accentRing: "rgba(255,107,0,.28)",
|
|
2439
|
+
good: "#5fd190",
|
|
2440
|
+
goodBg: "#0f1f15",
|
|
2441
|
+
goodLine: "#1f4030",
|
|
2442
|
+
warnBg: "#251a0f",
|
|
2443
|
+
warnLine: "#5a3a1a",
|
|
2444
|
+
warnInk: "#f5b56b",
|
|
2445
|
+
sans: '-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,"Helvetica Neue",Arial,sans-serif',
|
|
2446
|
+
mono: 'ui-monospace,"SF Mono",SFMono-Regular,Menlo,monospace',
|
|
2447
|
+
shadow: "0 14px 44px rgba(0,0,0,.55),0 2px 10px rgba(0,0,0,.35)",
|
|
2448
|
+
buttonInk: "#0f0f12"
|
|
2449
|
+
};
|
|
2450
|
+
function defaultDeliver(draft) {
|
|
2451
|
+
globalThis.__insitu_capture__ = {
|
|
2452
|
+
title: draft.title,
|
|
2453
|
+
body: draft.body,
|
|
2454
|
+
bundle: draft.bundle
|
|
2455
|
+
};
|
|
2456
|
+
console.info("[insitue] capture:", draft.title);
|
|
2457
|
+
try {
|
|
2458
|
+
const blob = new Blob([JSON.stringify(draft, null, 2)], {
|
|
2459
|
+
type: "application/json"
|
|
2460
|
+
});
|
|
2461
|
+
const a3 = document.createElement("a");
|
|
2462
|
+
a3.href = URL.createObjectURL(blob);
|
|
2463
|
+
a3.download = `insitue-capture-${Date.now()}.json`;
|
|
2464
|
+
a3.click();
|
|
2465
|
+
URL.revokeObjectURL(a3.href);
|
|
2466
|
+
} catch {
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
function CaptureApp(props) {
|
|
2470
|
+
const isDev = props.sink.kind === "companion";
|
|
2471
|
+
const C3 = isDev ? DEV : CLOUD;
|
|
2472
|
+
const [phase, setPhase] = d2("idle");
|
|
2473
|
+
const [bundle, setBundle] = d2(null);
|
|
2474
|
+
const [note, setNote] = d2("");
|
|
2475
|
+
const [tabCaptureActive, setTabCaptureActive] = d2(false);
|
|
2476
|
+
const [tabCaptureDenied, setTabCaptureDenied] = d2(false);
|
|
2477
|
+
const [companionState, setCompanionState] = d2(
|
|
2478
|
+
isDev ? "connecting" : "idle"
|
|
2479
|
+
);
|
|
2480
|
+
const [companionDetail, setCompanionDetail] = d2("");
|
|
2481
|
+
const noteRef = A2(null);
|
|
2482
|
+
const companionRef = A2(null);
|
|
2483
|
+
y2(() => {
|
|
2484
|
+
if (!isDev) return;
|
|
2485
|
+
const port = props.sink.kind === "companion" ? props.sink.port ?? DEFAULT_COMPANION_PORT : DEFAULT_COMPANION_PORT;
|
|
2486
|
+
let cancelled = false;
|
|
2487
|
+
let reconnectTimer = null;
|
|
2488
|
+
const connect = () => {
|
|
2489
|
+
if (cancelled) return;
|
|
2490
|
+
const c3 = new CompanionClient(port, {
|
|
2491
|
+
onState: (s3, detail) => {
|
|
2492
|
+
setCompanionState(s3);
|
|
2493
|
+
if (detail) setCompanionDetail(detail);
|
|
2494
|
+
if (s3 === "error" || s3 === "idle") {
|
|
2495
|
+
if (!cancelled) {
|
|
2496
|
+
reconnectTimer = setTimeout(connect, 2500);
|
|
2497
|
+
}
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
});
|
|
2501
|
+
companionRef.current = c3;
|
|
2502
|
+
void c3.connect();
|
|
2503
|
+
};
|
|
2504
|
+
connect();
|
|
2505
|
+
return () => {
|
|
2506
|
+
cancelled = true;
|
|
2507
|
+
if (reconnectTimer) clearTimeout(reconnectTimer);
|
|
2508
|
+
companionRef.current?.dispose();
|
|
2509
|
+
companionRef.current = null;
|
|
2510
|
+
};
|
|
2511
|
+
}, [isDev, props.sink]);
|
|
2512
|
+
y2(() => {
|
|
2513
|
+
return onDisplayMediaChange((active, reason) => {
|
|
2514
|
+
setTabCaptureActive(active);
|
|
2515
|
+
if (reason === "denied") setTabCaptureDenied(true);
|
|
2516
|
+
if (reason === "granted") setTabCaptureDenied(false);
|
|
2517
|
+
});
|
|
2518
|
+
}, []);
|
|
2519
|
+
const retryWithPixelPerfect = async () => {
|
|
2520
|
+
if (!bundle?.target?.selector) {
|
|
2521
|
+
await retryDisplayMedia();
|
|
2522
|
+
return;
|
|
2523
|
+
}
|
|
2524
|
+
const granted = await retryDisplayMedia();
|
|
2525
|
+
if (granted) {
|
|
2526
|
+
setPhase("picking");
|
|
2527
|
+
const sel = await beginPick("element").catch(() => null);
|
|
2528
|
+
if (sel) {
|
|
2529
|
+
setBundle(await buildBundle(sel));
|
|
2530
|
+
setPhase("compose");
|
|
2531
|
+
} else {
|
|
2532
|
+
setPhase("compose");
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
};
|
|
2536
|
+
const sink = new IssueTrackerSink(async (draft) => {
|
|
2537
|
+
globalThis.__insitu_capture__ = {
|
|
2538
|
+
title: draft.title,
|
|
2539
|
+
body: draft.body,
|
|
2540
|
+
bundle: draft.bundle
|
|
2541
|
+
};
|
|
2542
|
+
if (props.onCapture) {
|
|
2543
|
+
props.onCapture(draft, draft.bundle);
|
|
2544
|
+
return;
|
|
2545
|
+
}
|
|
2546
|
+
if (props.sink.kind === "cloud") {
|
|
2547
|
+
await postCloud(props.sink, draft);
|
|
2548
|
+
return;
|
|
2549
|
+
}
|
|
2550
|
+
const client = companionRef.current;
|
|
2551
|
+
if (!client || companionState !== "connected") {
|
|
2552
|
+
defaultDeliver(draft);
|
|
2553
|
+
return;
|
|
2554
|
+
}
|
|
2555
|
+
client.submitCapture(draft.bundle);
|
|
2556
|
+
});
|
|
2557
|
+
y2(() => {
|
|
2558
|
+
if (phase !== "sent") return;
|
|
2559
|
+
const t4 = setTimeout(() => {
|
|
2560
|
+
setPhase("idle");
|
|
2561
|
+
setBundle(null);
|
|
2562
|
+
setNote("");
|
|
2563
|
+
}, 2400);
|
|
2564
|
+
return () => clearTimeout(t4);
|
|
2565
|
+
}, [phase]);
|
|
2566
|
+
y2(() => {
|
|
2567
|
+
if (phase === "compose") {
|
|
2568
|
+
const id = setTimeout(() => noteRef.current?.focus(), 30);
|
|
2569
|
+
return () => clearTimeout(id);
|
|
2570
|
+
}
|
|
2571
|
+
return void 0;
|
|
2572
|
+
}, [phase]);
|
|
2573
|
+
y2(() => {
|
|
2574
|
+
const onKey = (ev) => {
|
|
2575
|
+
const t4 = ev.target;
|
|
2576
|
+
const tagName = t4?.tagName?.toLowerCase();
|
|
2577
|
+
const inHostInput = tagName === "input" || tagName === "textarea" || t4?.isContentEditable;
|
|
2578
|
+
const isMeta = ev.metaKey || ev.ctrlKey;
|
|
2579
|
+
if (isMeta && (ev.key === "k" || ev.key === "K") && !inHostInput) {
|
|
2580
|
+
if (phase === "idle" || phase === "compose" || phase === "sent") {
|
|
2581
|
+
ev.preventDefault();
|
|
2582
|
+
void startPick();
|
|
2583
|
+
}
|
|
2584
|
+
return;
|
|
2585
|
+
}
|
|
2586
|
+
if (ev.key === "Escape") {
|
|
2587
|
+
if (phase === "compose") {
|
|
2588
|
+
ev.preventDefault();
|
|
2589
|
+
reset();
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
};
|
|
2593
|
+
window.addEventListener("keydown", onKey, true);
|
|
2594
|
+
return () => window.removeEventListener("keydown", onKey, true);
|
|
2595
|
+
}, [phase]);
|
|
2596
|
+
const startPick = async () => {
|
|
2597
|
+
setPhase("picking");
|
|
2598
|
+
try {
|
|
2599
|
+
const sel = await beginPick("element");
|
|
2600
|
+
if (!sel) {
|
|
2601
|
+
setPhase("idle");
|
|
2602
|
+
return;
|
|
2603
|
+
}
|
|
2604
|
+
setBundle(await buildBundle(sel));
|
|
2605
|
+
setPhase("compose");
|
|
2606
|
+
} catch {
|
|
2607
|
+
setPhase("idle");
|
|
2608
|
+
}
|
|
2609
|
+
};
|
|
2610
|
+
const send = async () => {
|
|
2611
|
+
if (!bundle) return;
|
|
2612
|
+
setPhase("sending");
|
|
2613
|
+
const withNote = note.trim() ? { ...bundle, userNote: note.trim() } : bundle;
|
|
2614
|
+
try {
|
|
2615
|
+
await sink.submit(withNote);
|
|
2616
|
+
} finally {
|
|
2617
|
+
setPhase("sent");
|
|
2618
|
+
}
|
|
2619
|
+
};
|
|
2620
|
+
const reset = () => {
|
|
2621
|
+
setPhase("idle");
|
|
2622
|
+
setBundle(null);
|
|
2623
|
+
setNote("");
|
|
2624
|
+
};
|
|
2625
|
+
const onNoteKeyDown = (ev) => {
|
|
2626
|
+
if (isDev) {
|
|
2627
|
+
if (ev.key === "Enter" && !ev.shiftKey && note.trim() && bundle) {
|
|
2628
|
+
ev.preventDefault();
|
|
2629
|
+
void send();
|
|
2630
|
+
}
|
|
2631
|
+
} else if ((ev.metaKey || ev.ctrlKey) && ev.key === "Enter") {
|
|
2632
|
+
ev.preventDefault();
|
|
2633
|
+
if (note.trim() && bundle) void send();
|
|
2634
|
+
}
|
|
2635
|
+
};
|
|
2636
|
+
const dot = k("span", {
|
|
2637
|
+
style: `width:9px;height:9px;border-radius:3px;background:${C3.accent};box-shadow:0 1px 4px ${C3.accentRing}`
|
|
2638
|
+
});
|
|
2639
|
+
const confidenceLabel = (b2) => {
|
|
2640
|
+
if (!b2?.target) return null;
|
|
2641
|
+
const c3 = b2.target.confidence;
|
|
2642
|
+
if (c3 === "exact") return "exact";
|
|
2643
|
+
if (c3 === "approximate") return "approximate";
|
|
2644
|
+
if (c3 === "selector-only") return "selector only";
|
|
2645
|
+
return c3;
|
|
2646
|
+
};
|
|
2647
|
+
if (phase === "idle" || phase === "picking") {
|
|
2648
|
+
const picking = phase === "picking";
|
|
2649
|
+
const offline = isDev && companionState !== "connected";
|
|
2650
|
+
return k(
|
|
2651
|
+
"button",
|
|
2652
|
+
{
|
|
2653
|
+
onClick: picking ? void 0 : () => void startPick(),
|
|
2654
|
+
style: `all:unset;position:fixed;bottom:20px;right:20px;z-index:2147483000;display:flex;align-items:center;gap:9px;cursor:${picking ? "default" : "pointer"};padding:11px 16px;font:600 13.5px/1 ${C3.sans};color:${C3.ink};background:${C3.surface};border:1px solid ${C3.line};border-radius:999px;box-shadow:${C3.shadow};letter-spacing:-.01em`,
|
|
2655
|
+
title: isDev ? offline ? "InSitue companion not running \u2014 start `claude` with /insitue:connect" : "Pick an element to talk to claude about" : "Report a problem"
|
|
2656
|
+
},
|
|
2657
|
+
picking ? [
|
|
2658
|
+
k("span", {
|
|
2659
|
+
style: `width:9px;height:9px;border-radius:50%;background:${C3.accentSolid};animation:ipulse 1.1s ease-in-out infinite`
|
|
2660
|
+
}),
|
|
2661
|
+
k("span", { style: `color:${C3.sub}` }, isDev ? "Click an element" : "Click the broken element"),
|
|
2662
|
+
k("span", { style: `color:${C3.faint}` }, "\xB7 Esc to cancel"),
|
|
2663
|
+
k(
|
|
2664
|
+
"style",
|
|
2665
|
+
{},
|
|
2666
|
+
"@keyframes ipulse{0%,100%{opacity:.35}50%{opacity:1}}"
|
|
2667
|
+
)
|
|
2668
|
+
] : isDev ? [
|
|
2669
|
+
k("span", {
|
|
2670
|
+
style: `width:9px;height:9px;border-radius:50%;background:${offline ? "#9a9aa4" : "#5fd190"};box-shadow:${offline ? "none" : "0 0 6px #5fd190"}`
|
|
2671
|
+
}),
|
|
2672
|
+
k("span", {}, "InSitue Dev"),
|
|
2673
|
+
k(
|
|
2674
|
+
"span",
|
|
2675
|
+
{ style: `color:${C3.faint};font-family:${C3.mono};font-size:11px` },
|
|
2676
|
+
offline ? "offline" : "\u2192 claude"
|
|
2677
|
+
),
|
|
2678
|
+
k(
|
|
2679
|
+
"span",
|
|
2680
|
+
{
|
|
2681
|
+
style: `color:${C3.faint};font-family:${C3.mono};font-size:10.5px;padding:1px 5px;border:1px solid ${C3.line};border-radius:4px;background:${C3.surface2}`,
|
|
2682
|
+
title: "Press to pick an element"
|
|
2683
|
+
},
|
|
2684
|
+
"\u2318K"
|
|
2685
|
+
)
|
|
2686
|
+
] : [dot, "Report a problem"]
|
|
2687
|
+
);
|
|
2688
|
+
}
|
|
2689
|
+
const t3 = bundle?.target;
|
|
2690
|
+
const targetLabel = t3?.componentStack?.[0]?.name ?? t3?.selector?.split(">").pop()?.trim() ?? "selection";
|
|
2691
|
+
const conf = confidenceLabel(bundle);
|
|
2692
|
+
const isPoorSource = bundle?.target?.confidence === "selector-only";
|
|
2693
|
+
const card = (children) => k(
|
|
2694
|
+
"div",
|
|
2695
|
+
{
|
|
2696
|
+
style: `position:fixed;bottom:20px;right:20px;z-index:2147483000;width:360px;font:14px/1.55 ${C3.sans};color:${C3.ink};background:${C3.surface};border:1px solid ${C3.line};border-radius:16px;box-shadow:${C3.shadow};overflow:hidden`
|
|
2697
|
+
},
|
|
2698
|
+
children
|
|
2699
|
+
);
|
|
2700
|
+
if (phase === "sent") {
|
|
2701
|
+
const sentTitle = isDev ? "Sent to claude" : "Report sent";
|
|
2702
|
+
const sentBody = isDev ? "Switch to your terminal \u2014 claude has the pick + your description and is ready to act." : "The team has everything to reproduce and fix this \u2014 no follow-up needed.";
|
|
2703
|
+
return card([
|
|
2704
|
+
k(
|
|
2705
|
+
"div",
|
|
2706
|
+
{ style: "padding:30px 22px;text-align:center" },
|
|
2707
|
+
[
|
|
2708
|
+
k(
|
|
2709
|
+
"div",
|
|
2710
|
+
{
|
|
2711
|
+
style: `width:46px;height:46px;border-radius:50%;margin:0 auto 12px;display:flex;align-items:center;justify-content:center;color:${C3.buttonInk};font-size:22px;background:${C3.accent};box-shadow:0 6px 18px ${C3.accentRing}`
|
|
2712
|
+
},
|
|
2713
|
+
"\u2713"
|
|
2714
|
+
),
|
|
2715
|
+
k(
|
|
2716
|
+
"div",
|
|
2717
|
+
{ style: "font-weight:680;font-size:15px;letter-spacing:-.01em" },
|
|
2718
|
+
sentTitle
|
|
2719
|
+
),
|
|
2720
|
+
k(
|
|
2721
|
+
"div",
|
|
2722
|
+
{ style: `color:${C3.sub};margin-top:5px;font-size:13px` },
|
|
2723
|
+
sentBody
|
|
2724
|
+
)
|
|
2725
|
+
]
|
|
2726
|
+
)
|
|
2727
|
+
]);
|
|
2728
|
+
}
|
|
2729
|
+
const sending = phase === "sending";
|
|
2730
|
+
const title = isDev ? "Tell claude what to change" : "Report a problem";
|
|
2731
|
+
const placeholderText = isDev ? "Describe what should change about this element\u2026" : "What's wrong? (optional but helps)";
|
|
2732
|
+
const sendButtonLabel = sending ? isDev ? "Sending\u2026" : "Sending\u2026" : isDev ? "Send to claude \u23CE" : "Send report";
|
|
2733
|
+
return card([
|
|
2734
|
+
// Header
|
|
2735
|
+
k(
|
|
2736
|
+
"div",
|
|
2737
|
+
{
|
|
2738
|
+
style: `display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid ${C3.line}`
|
|
2739
|
+
},
|
|
2740
|
+
[
|
|
2741
|
+
k(
|
|
2742
|
+
"div",
|
|
2743
|
+
{ style: "display:flex;align-items:center;gap:8px;font-weight:680;letter-spacing:-.01em" },
|
|
2744
|
+
[dot, title]
|
|
2745
|
+
),
|
|
2746
|
+
k(
|
|
2747
|
+
"button",
|
|
2748
|
+
{
|
|
2749
|
+
onClick: reset,
|
|
2750
|
+
style: `all:unset;cursor:pointer;color:${C3.faint};font-size:16px;line-height:1;padding:2px 4px`,
|
|
2751
|
+
title: "Close"
|
|
2752
|
+
},
|
|
2753
|
+
"\u2715"
|
|
2754
|
+
)
|
|
2755
|
+
]
|
|
2756
|
+
),
|
|
2757
|
+
k("div", { style: "padding:16px" }, [
|
|
2758
|
+
// Target chip with confidence badge
|
|
2759
|
+
k(
|
|
2760
|
+
"div",
|
|
2761
|
+
{
|
|
2762
|
+
style: `display:flex;align-items:center;gap:8px;padding:9px 11px;background:${C3.surface2};border:1px solid ${C3.line};border-radius:10px;font:12px/1.3 ${C3.mono};color:${C3.sub};margin-bottom:12px`
|
|
2763
|
+
},
|
|
2764
|
+
[
|
|
2765
|
+
k("span", { style: `color:${C3.accentSolid}` }, "\u25CE"),
|
|
2766
|
+
k(
|
|
2767
|
+
"span",
|
|
2768
|
+
{
|
|
2769
|
+
style: "overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0"
|
|
2770
|
+
},
|
|
2771
|
+
`${targetLabel}${t3?.source ? ` \xB7 ${t3.source.file.split("/").pop()}:${t3.source.line ?? "?"}` : ""}`
|
|
2772
|
+
),
|
|
2773
|
+
conf ? k(
|
|
2774
|
+
"span",
|
|
2775
|
+
{
|
|
2776
|
+
style: `flex:none;padding:1px 7px;border-radius:999px;font-size:10.5px;letter-spacing:.02em;${isPoorSource ? `background:${C3.warnBg};color:${C3.warnInk};border:1px solid ${C3.warnLine}` : `background:${C3.goodBg};color:${C3.good};border:1px solid ${C3.goodLine}`}`
|
|
2777
|
+
},
|
|
2778
|
+
conf
|
|
2779
|
+
) : null
|
|
2780
|
+
]
|
|
2781
|
+
),
|
|
2782
|
+
// Bulletproof selection: if the pick is selector-only, refuse
|
|
2783
|
+
// to send and offer a re-pick. Telling claude "we couldn't
|
|
2784
|
+
// find the file" is worse than asking the user to try a
|
|
2785
|
+
// parent.
|
|
2786
|
+
isPoorSource ? k(
|
|
2787
|
+
"div",
|
|
2788
|
+
{
|
|
2789
|
+
style: `padding:9px 11px;background:${C3.warnBg};border:1px solid ${C3.warnLine};color:${C3.warnInk};border-radius:10px;font-size:12px;margin-bottom:12px;line-height:1.4`
|
|
2790
|
+
},
|
|
2791
|
+
[
|
|
2792
|
+
k(
|
|
2793
|
+
"div",
|
|
2794
|
+
{ style: "font-weight:600;margin-bottom:3px" },
|
|
2795
|
+
"Couldn't resolve the source file for this element."
|
|
2796
|
+
),
|
|
2797
|
+
k(
|
|
2798
|
+
"div",
|
|
2799
|
+
{},
|
|
2800
|
+
"Try picking a parent \u2014 most often the issue is an unnamed wrapper. The selector alone isn't enough to find the file."
|
|
2801
|
+
)
|
|
2802
|
+
]
|
|
2803
|
+
) : null,
|
|
2804
|
+
bundle?.screenshot ? k("img", {
|
|
2805
|
+
src: bundle.screenshot.dataUrl,
|
|
2806
|
+
style: `width:100%;max-height:120px;object-fit:cover;border:1px solid ${C3.line};border-radius:10px;margin-bottom:12px`
|
|
2807
|
+
}) : bundle?.screenshotUnavailable ? k(
|
|
2808
|
+
"div",
|
|
2809
|
+
{
|
|
2810
|
+
style: `font-size:12px;color:${C3.faint};background:${C3.surface2};border:1px solid ${C3.line};border-radius:10px;padding:10px;margin-bottom:12px;word-break:break-word`
|
|
2811
|
+
},
|
|
2812
|
+
`Screenshot unavailable \u2014 ${bundle.screenshotUnavailable}`
|
|
2813
|
+
) : null,
|
|
2814
|
+
bundle?.screenshot?.qualityNote && !tabCaptureActive ? k(
|
|
2815
|
+
"div",
|
|
2816
|
+
{
|
|
2817
|
+
style: `display:flex;align-items:center;gap:8px;padding:9px 11px;background:${C3.warnBg};border:1px solid ${C3.warnLine};color:${C3.warnInk};border-radius:10px;font-size:12px;margin-bottom:12px`
|
|
2818
|
+
},
|
|
2819
|
+
[
|
|
2820
|
+
k(
|
|
2821
|
+
"span",
|
|
2822
|
+
{ style: "flex:1" },
|
|
2823
|
+
"Some content didn't capture cleanly. Enable tab capture for a pixel-perfect screenshot."
|
|
2824
|
+
),
|
|
2825
|
+
k(
|
|
2826
|
+
"button",
|
|
2827
|
+
{
|
|
2828
|
+
onClick: () => void retryWithPixelPerfect(),
|
|
2829
|
+
style: `all:unset;cursor:pointer;color:${C3.accentSolid};font-weight:600;padding:2px 8px;border:1px solid ${C3.line};border-radius:6px;background:${C3.surface}`
|
|
2830
|
+
},
|
|
2831
|
+
"Enable"
|
|
2832
|
+
)
|
|
2833
|
+
]
|
|
2834
|
+
) : null,
|
|
2835
|
+
tabCaptureActive ? k(
|
|
2836
|
+
"div",
|
|
2837
|
+
{
|
|
2838
|
+
style: `display:flex;align-items:center;gap:8px;padding:7px 11px;background:${C3.goodBg};border:1px solid ${C3.goodLine};color:${C3.good};border-radius:10px;font-size:11.5px;margin-bottom:12px`
|
|
2839
|
+
},
|
|
2840
|
+
[
|
|
2841
|
+
k("span", {
|
|
2842
|
+
style: `width:8px;height:8px;border-radius:50%;background:${C3.good};box-shadow:0 0 6px ${C3.good}`
|
|
2843
|
+
}),
|
|
2844
|
+
k(
|
|
2845
|
+
"span",
|
|
2846
|
+
{ style: "flex:1" },
|
|
2847
|
+
"Tab capture active \u2014 screenshots are pixel-perfect."
|
|
2848
|
+
),
|
|
2849
|
+
k(
|
|
2850
|
+
"button",
|
|
2851
|
+
{
|
|
2852
|
+
onClick: () => stopDisplayMedia("user"),
|
|
2853
|
+
style: `all:unset;cursor:pointer;color:${C3.good};font-weight:600;padding:2px 6px`
|
|
2854
|
+
},
|
|
2855
|
+
"Stop"
|
|
2856
|
+
)
|
|
2857
|
+
]
|
|
2858
|
+
) : null,
|
|
2859
|
+
k("textarea", {
|
|
2860
|
+
ref: (el) => {
|
|
2861
|
+
noteRef.current = el;
|
|
2862
|
+
},
|
|
2863
|
+
value: note,
|
|
2864
|
+
rows: 3,
|
|
2865
|
+
placeholder: placeholderText,
|
|
2866
|
+
disabled: sending,
|
|
2867
|
+
onInput: (e3) => setNote(e3.target.value),
|
|
2868
|
+
onKeyDown: onNoteKeyDown,
|
|
2869
|
+
style: `width:100%;box-sizing:border-box;font:14px/1.5 ${isDev ? C3.mono : C3.sans};color:${C3.ink};background:${C3.surface};border:1px solid ${C3.line};border-radius:10px;padding:10px 12px;resize:none;outline:none`
|
|
2870
|
+
}),
|
|
2871
|
+
k("div", { style: "display:flex;gap:8px;margin-top:12px" }, [
|
|
2872
|
+
k(
|
|
2873
|
+
"button",
|
|
2874
|
+
{
|
|
2875
|
+
onClick: sending || isPoorSource || isDev && !note.trim() ? void 0 : () => void send(),
|
|
2876
|
+
disabled: sending || isPoorSource || isDev && !note.trim(),
|
|
2877
|
+
title: isDev && !note.trim() ? "Add a description first" : void 0,
|
|
2878
|
+
style: `flex:1;all:unset;text-align:center;cursor:${sending || isPoorSource || isDev && !note.trim() ? "default" : "pointer"};padding:11px;font:680 13.5px/1 ${C3.sans};color:${C3.buttonInk};background:${C3.accent};border-radius:10px;box-shadow:0 2px 10px ${C3.accentRing};opacity:${sending || isPoorSource || isDev && !note.trim() ? ".5" : "1"}`
|
|
2879
|
+
},
|
|
2880
|
+
sendButtonLabel
|
|
2881
|
+
),
|
|
2882
|
+
k(
|
|
2883
|
+
"button",
|
|
2884
|
+
{
|
|
2885
|
+
onClick: () => void startPick(),
|
|
2886
|
+
style: `all:unset;cursor:pointer;padding:11px 14px;font:600 13.5px/1 ${C3.sans};color:${C3.sub};background:${C3.surface2};border:1px solid ${C3.line};border-radius:10px`
|
|
2887
|
+
},
|
|
2888
|
+
"Re-pick"
|
|
2889
|
+
)
|
|
2890
|
+
]),
|
|
2891
|
+
// Dev-mode: companion state row (last). When connected, a
|
|
2892
|
+
// subtle "→ claude" indicator. When offline, an actionable
|
|
2893
|
+
// hint with the exact command to fix it.
|
|
2894
|
+
isDev ? k(
|
|
2895
|
+
"div",
|
|
2896
|
+
{
|
|
2897
|
+
style: `margin-top:12px;padding-top:10px;border-top:1px solid ${C3.line};display:flex;align-items:center;gap:8px;font:11.5px/1.3 ${C3.mono}`
|
|
2898
|
+
},
|
|
2899
|
+
companionState === "connected" ? [
|
|
2900
|
+
k("span", {
|
|
2901
|
+
style: `width:7px;height:7px;border-radius:50%;background:${C3.good};box-shadow:0 0 5px ${C3.good};flex:none`
|
|
2902
|
+
}),
|
|
2903
|
+
k(
|
|
2904
|
+
"span",
|
|
2905
|
+
{ style: `color:${C3.sub};flex:1` },
|
|
2906
|
+
`\u2192 ${companionDetail || "claude"}`
|
|
2907
|
+
)
|
|
2908
|
+
] : [
|
|
2909
|
+
k("span", {
|
|
2910
|
+
style: `width:7px;height:7px;border-radius:50%;background:${C3.faint};flex:none`
|
|
2911
|
+
}),
|
|
2912
|
+
k(
|
|
2913
|
+
"span",
|
|
2914
|
+
{ style: `color:${C3.faint};flex:1` },
|
|
2915
|
+
companionState === "connecting" ? "Connecting to companion\u2026" : "Companion offline \u2014 run `claude` and `/insitue:connect`"
|
|
2916
|
+
)
|
|
2917
|
+
]
|
|
2918
|
+
) : null
|
|
2919
|
+
]),
|
|
2920
|
+
k(
|
|
2921
|
+
"div",
|
|
2922
|
+
{
|
|
2923
|
+
style: `display:flex;justify-content:space-between;padding:9px 16px;border-top:1px solid ${C3.line};color:${C3.faint};font-size:11px`
|
|
2924
|
+
},
|
|
2925
|
+
[
|
|
2926
|
+
k("span", {}, isDev ? "InSitue Dev \xB7 pick + describe \u2192 CLI" : ""),
|
|
2927
|
+
k(
|
|
2928
|
+
"span",
|
|
2929
|
+
{ title: `@insitue/sdk@${"0.3.1"}` },
|
|
2930
|
+
`InSitue \xB7 v${"0.3.1"}`
|
|
2931
|
+
)
|
|
2932
|
+
]
|
|
2933
|
+
)
|
|
2934
|
+
]);
|
|
2935
|
+
}
|
|
2936
|
+
function mountCaptureOnly(opts = {}) {
|
|
2937
|
+
installRuntimeCollectors();
|
|
2938
|
+
if (opts.defaultPixelPerfect === true) {
|
|
2939
|
+
setCaptureSettings({ alwaysPixelPerfect: true });
|
|
2940
|
+
}
|
|
2941
|
+
const sink = resolveSink(opts);
|
|
2942
|
+
const host = document.createElement("div");
|
|
2943
|
+
host.id = "insitu-capture-root";
|
|
2944
|
+
host.setAttribute("data-insitu", "");
|
|
2945
|
+
document.body.appendChild(host);
|
|
2946
|
+
const shadow = host.attachShadow({ mode: "open" });
|
|
2947
|
+
const mount = document.createElement("div");
|
|
2948
|
+
shadow.appendChild(mount);
|
|
2949
|
+
R(
|
|
2950
|
+
k(CaptureApp, {
|
|
2951
|
+
sink,
|
|
2952
|
+
...opts.onCapture ? { onCapture: opts.onCapture } : {}
|
|
2953
|
+
}),
|
|
2954
|
+
mount
|
|
2955
|
+
);
|
|
2956
|
+
return () => {
|
|
2957
|
+
R(null, mount);
|
|
2958
|
+
host.remove();
|
|
2959
|
+
};
|
|
2960
|
+
}
|
|
2961
|
+
|
|
2233
2962
|
export {
|
|
2234
|
-
|
|
2235
|
-
R,
|
|
2236
|
-
d2 as d,
|
|
2237
|
-
y2 as y,
|
|
2238
|
-
A2 as A,
|
|
2239
|
-
PROTOCOL_VERSION,
|
|
2240
|
-
IssueTrackerSink,
|
|
2241
|
-
installRuntimeCollectors,
|
|
2242
|
-
runtimeErrorCount,
|
|
2243
|
-
beginPick,
|
|
2244
|
-
getCaptureSettings,
|
|
2245
|
-
setCaptureSettings,
|
|
2246
|
-
onCaptureSettingsChange,
|
|
2247
|
-
onDisplayMediaChange,
|
|
2248
|
-
stopDisplayMedia,
|
|
2249
|
-
retryDisplayMedia,
|
|
2250
|
-
buildBundle
|
|
2963
|
+
mountCaptureOnly
|
|
2251
2964
|
};
|