@insitue/sdk 0.1.14 → 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/dist/index.d.ts CHANGED
@@ -1,49 +1,76 @@
1
1
  import { IssueDraft, CaptureBundle } from '@insitue/capture-core';
2
- export { InSitueOptions, mountInSitue } from './overlay.js';
2
+ import { CaptureSink } from './capture-only.js';
3
3
  export { CaptureOnlyOptions, mountCaptureOnly } from './capture-only.js';
4
4
 
5
- interface InSitueProps {
6
- /** Companion loopback port (default 5747). */
7
- port?: number;
8
- }
9
- declare function InSitue({ port }: InSitueProps): null;
10
5
  interface InSitueCaptureProps {
11
6
  /**
12
7
  * Publishable project key (e.g. `pk_…`). When set, captures POST
13
8
  * to the InSitue cloud automatically. Origin-pinned + quota-gated
14
- * server-side, so safe to ship in your production bundle.
9
+ * server-side, so safe to ship in your production bundle. Auto-
10
+ * selects `sink: { kind: "cloud" }` unless `sink` is set
11
+ * explicitly.
15
12
  */
16
13
  projectKey?: string;
17
- /** Override the ingest endpoint (default = InSitue cloud). */
14
+ /** Override the ingest endpoint (cloud sink). */
18
15
  endpoint?: string;
19
16
  /**
20
- * Take over delivery yourself. Wins over `projectKey`. Default
21
- * (neither set): console + JSON download + `window.__insitu_capture__`.
17
+ * Take over delivery yourself. Wins over `projectKey` AND
18
+ * `sink`. Default (none set + no companion reachable): console +
19
+ * JSON download + `window.__insitu_capture__`.
22
20
  */
23
21
  onCapture?: (draft: IssueDraft, bundle: CaptureBundle) => void;
22
+ /**
23
+ * Explicit sink override. Most callers leave this undefined and
24
+ * rely on auto-detection (projectKey → cloud, otherwise →
25
+ * companion).
26
+ */
27
+ sink?: CaptureSink;
24
28
  /**
25
29
  * Default the user's "Always pixel-perfect screenshots" setting
26
- * to `true` on mount — every capture uses the `getDisplayMedia`
27
- * OS-compositor path, paying a one-time tab-share permission per
28
- * session in exchange for screenshots that are pixel-accurate
29
- * across any content (next/image, video, canvas, cross-origin).
30
+ * to `true` on mount — every capture uses `getDisplayMedia`,
31
+ * paying a one-time tab-share permission per session in exchange
32
+ * for screenshots that are pixel-accurate across any content
33
+ * (next/image, video, canvas, cross-origin).
30
34
  *
31
- * Recommended for dev / dogfood, where capture quality matters
32
- * more than the permission UX. Not the default — production
33
- * end-users shouldn't see a permission dialog they didn't ask for.
35
+ * Recommended for dev / dogfood; not for production end-users.
34
36
  */
35
37
  defaultPixelPerfect?: boolean;
36
38
  }
37
39
  /**
38
- * `<InSitueCapture />` the prod capture-only path. UNLIKE
39
- * `<InSitue />` it does NOT bail in a production build: capture-only
40
- * is exactly what prod runs (no companion to refuse). It never touches
41
- * fs/agent/WS; the same bundle just flows to the configured sink.
40
+ * The canonical InSitue widget. Use this for both prod (with
41
+ * `projectKey`) and dev (without). One mount, one component, the
42
+ * UI and theme adapt to the sink.
43
+ */
44
+ declare function InSitueCapture({ projectKey, endpoint, onCapture, sink, defaultPixelPerfect, }: InSitueCaptureProps): null;
45
+ interface InSitueProps {
46
+ /**
47
+ * Companion loopback port (default 5747). Only meaningful when
48
+ * not also passing `projectKey` — when `projectKey` is set, the
49
+ * widget ships to the cloud sink and this is ignored.
50
+ */
51
+ port?: number;
52
+ }
53
+ /**
54
+ * `<InSitue />` — backward-compat dev alias.
55
+ *
56
+ * Equivalent to `<InSitueCapture sink={{ kind: "companion", port }} />`.
57
+ * Kept so existing `<InSitue />` mounts (callers that imported the
58
+ * pre-0.3.0 chat overlay) keep compiling. The behaviour is the
59
+ * unified widget, NOT the removed chat overlay — the in-overlay
60
+ * thread, diff display, and SESSION history are gone in 0.3.0.
61
+ *
62
+ * For new code, prefer `<InSitueCapture />`.
63
+ */
64
+ declare function InSitue({ port }: InSitueProps): null;
65
+
66
+ /**
67
+ * `@insitue/sdk` — the InSitue capture widget for browser apps.
42
68
  *
43
- * The simplest path: set `projectKey` and the SDK POSTs captures to
44
- * the InSitue cloud automatically.
69
+ * One component, two sinks. `<InSitueCapture />` is the canonical
70
+ * mount; `<InSitue />` is a backward-compat dev alias (companion
71
+ * sink). The chat-style overlay that existed pre-0.3.0 has been
72
+ * removed in favour of the unified widget.
45
73
  */
46
- declare function InSitueCapture({ projectKey, endpoint, onCapture, defaultPixelPerfect, }: InSitueCaptureProps): null;
47
74
 
48
75
  /** Build-time-inlined version of `@insitue/sdk` (from package.json).
49
76
  * Exposed so the host app can self-verify which SDK build is loaded
@@ -51,4 +78,4 @@ declare function InSitueCapture({ projectKey, endpoint, onCapture, defaultPixelP
51
78
  * the capture widget footer so a screenshot proves the build. */
52
79
  declare const SDK_VERSION: string;
53
80
 
54
- export { InSitue, InSitueCapture, type InSitueCaptureProps, type InSitueProps, SDK_VERSION };
81
+ export { CaptureSink, InSitue, InSitueCapture, type InSitueCaptureProps, type InSitueProps, SDK_VERSION };
package/dist/index.js CHANGED
@@ -1,45 +1,47 @@
1
1
  import {
2
2
  mountCaptureOnly
3
- } from "./chunk-7EQRP6O4.js";
4
- import {
5
- mountInSitue
6
- } from "./chunk-QTG3I7DC.js";
7
- import "./chunk-HECY6THB.js";
3
+ } from "./chunk-BCKDBCPG.js";
8
4
 
9
5
  // src/InSitue.tsx
10
6
  import { useEffect } from "react";
11
- function InSitue({ port }) {
7
+ function InSitueCapture({
8
+ projectKey,
9
+ endpoint,
10
+ onCapture,
11
+ sink,
12
+ defaultPixelPerfect
13
+ }) {
12
14
  useEffect(() => {
13
- const nodeEnv = typeof process !== "undefined" ? process.env?.NODE_ENV : void 0;
14
- if (nodeEnv === "production") return;
15
15
  let active = true;
16
16
  let dispose;
17
- void import("./overlay.js").then((m) => {
18
- if (active) dispose = m.mountInSitue(port === void 0 ? {} : { port });
17
+ void import("./capture-only.js").then((m) => {
18
+ if (active) {
19
+ dispose = m.mountCaptureOnly({
20
+ ...projectKey ? { projectKey } : {},
21
+ ...endpoint ? { endpoint } : {},
22
+ ...onCapture ? { onCapture } : {},
23
+ ...sink ? { sink } : {},
24
+ ...defaultPixelPerfect === true ? { defaultPixelPerfect } : {}
25
+ });
26
+ }
19
27
  });
20
28
  return () => {
21
29
  active = false;
22
30
  dispose?.();
23
31
  };
24
- }, [port]);
32
+ }, [projectKey, endpoint, onCapture, sink, defaultPixelPerfect]);
25
33
  return null;
26
34
  }
27
- function InSitueCapture({
28
- projectKey,
29
- endpoint,
30
- onCapture,
31
- defaultPixelPerfect
32
- }) {
35
+ function InSitue({ port }) {
33
36
  useEffect(() => {
37
+ const nodeEnv = typeof process !== "undefined" ? process.env?.NODE_ENV : void 0;
38
+ if (nodeEnv === "production") return;
34
39
  let active = true;
35
40
  let dispose;
36
41
  void import("./capture-only.js").then((m) => {
37
42
  if (active) {
38
43
  dispose = m.mountCaptureOnly({
39
- projectKey,
40
- endpoint,
41
- onCapture,
42
- defaultPixelPerfect
44
+ sink: port === void 0 ? { kind: "companion" } : { kind: "companion", port }
43
45
  });
44
46
  }
45
47
  });
@@ -47,16 +49,15 @@ function InSitueCapture({
47
49
  active = false;
48
50
  dispose?.();
49
51
  };
50
- }, [projectKey, endpoint, onCapture, defaultPixelPerfect]);
52
+ }, [port]);
51
53
  return null;
52
54
  }
53
55
 
54
56
  // src/index.ts
55
- var SDK_VERSION = "0.1.14";
57
+ var SDK_VERSION = "0.3.1";
56
58
  export {
57
59
  InSitue,
58
60
  InSitueCapture,
59
61
  SDK_VERSION,
60
- mountCaptureOnly,
61
- mountInSitue
62
+ mountCaptureOnly
62
63
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@insitue/sdk",
3
- "version": "0.1.14",
3
+ "version": "0.3.1",
4
4
  "description": "InSitue capture SDK — drop one snippet into your deployed app; your users point at a bug, InSitue opens a verified pull request.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -13,11 +13,6 @@
13
13
  "import": "./dist/index.js",
14
14
  "default": "./dist/index.js"
15
15
  },
16
- "./overlay": {
17
- "types": "./dist/overlay.d.ts",
18
- "import": "./dist/overlay.js",
19
- "default": "./dist/overlay.js"
20
- },
21
16
  "./capture-only": {
22
17
  "types": "./dist/capture-only.d.ts",
23
18
  "import": "./dist/capture-only.js",
@@ -56,7 +51,7 @@
56
51
  "tsup": "^8.3.5",
57
52
  "typescript": "^5.6.3",
58
53
  "vitest": "^3.2.4",
59
- "@insitue/capture-core": "0.0.0"
54
+ "@insitue/capture-core": "0.2.0"
60
55
  },
61
56
  "repository": {
62
57
  "type": "git",
@@ -1,400 +0,0 @@
1
- import {
2
- IssueTrackerSink,
3
- R,
4
- beginPick,
5
- buildBundle,
6
- d,
7
- installRuntimeCollectors,
8
- k,
9
- onDisplayMediaChange,
10
- retryDisplayMedia,
11
- setCaptureSettings,
12
- stopDisplayMedia,
13
- y
14
- } from "./chunk-HECY6THB.js";
15
-
16
- // src/capture-only.ts
17
- var DEFAULT_INGEST = "https://www.insitue.com/api/v1/capture";
18
- async function postCapture(endpoint, projectKey, draft) {
19
- try {
20
- await fetch(endpoint, {
21
- method: "POST",
22
- headers: {
23
- "content-type": "application/json",
24
- "x-insitue-key": projectKey
25
- },
26
- body: JSON.stringify({
27
- bundle: draft.bundle,
28
- note: draft.bundle.userNote ?? null,
29
- projectKey
30
- // belt + braces — header is the contract, body is the fallback
31
- }),
32
- credentials: "omit",
33
- keepalive: true
34
- });
35
- } catch {
36
- }
37
- }
38
- var C = {
39
- ink: "#16161a",
40
- sub: "#6b6c77",
41
- faint: "#9a9aa4",
42
- line: "#e9e9ee",
43
- surface: "#ffffff",
44
- surface2: "#f6f6f9",
45
- accent: "linear-gradient(180deg,#6b63ff,#5751e6)",
46
- accentRing: "rgba(91,91,240,.30)",
47
- green: "#117a52",
48
- sans: '-apple-system,BlinkMacSystemFont,"Segoe UI",Inter,Roboto,"Helvetica Neue",Arial,sans-serif',
49
- mono: 'ui-monospace,"SF Mono",SFMono-Regular,Menlo,monospace',
50
- shadow: "0 12px 40px rgba(20,20,35,.16),0 2px 8px rgba(20,20,35,.08)"
51
- };
52
- function defaultDeliver(draft) {
53
- globalThis.__insitu_capture__ = {
54
- title: draft.title,
55
- body: draft.body,
56
- bundle: draft.bundle
57
- };
58
- console.info("[insitue] capture:", draft.title);
59
- try {
60
- const blob = new Blob([JSON.stringify(draft, null, 2)], {
61
- type: "application/json"
62
- });
63
- const a = document.createElement("a");
64
- a.href = URL.createObjectURL(blob);
65
- a.download = `insitue-capture-${Date.now()}.json`;
66
- a.click();
67
- URL.revokeObjectURL(a.href);
68
- } catch {
69
- }
70
- }
71
- function CaptureOnlyApp(props) {
72
- const [phase, setPhase] = d("idle");
73
- const [bundle, setBundle] = d(null);
74
- const [note, setNote] = d("");
75
- const [tabCaptureActive, setTabCaptureActive] = d(false);
76
- const [tabCaptureDenied, setTabCaptureDenied] = d(false);
77
- y(() => {
78
- return onDisplayMediaChange((active, reason) => {
79
- setTabCaptureActive(active);
80
- if (reason === "denied") setTabCaptureDenied(true);
81
- if (reason === "granted") setTabCaptureDenied(false);
82
- });
83
- }, []);
84
- const retryWithPixelPerfect = async () => {
85
- if (!bundle?.target?.selector) {
86
- await retryDisplayMedia();
87
- return;
88
- }
89
- const granted = await retryDisplayMedia();
90
- if (granted) {
91
- setPhase("picking");
92
- const sel = await beginPick("element").catch(() => null);
93
- if (sel) {
94
- setBundle(await buildBundle(sel));
95
- setPhase("compose");
96
- } else {
97
- setPhase("compose");
98
- }
99
- }
100
- };
101
- const sink = new IssueTrackerSink(async (draft) => {
102
- globalThis.__insitu_capture__ = {
103
- title: draft.title,
104
- body: draft.body,
105
- bundle: draft.bundle
106
- };
107
- if (props.onCapture) {
108
- props.onCapture(draft, draft.bundle);
109
- } else if (props.projectKey) {
110
- await postCapture(
111
- props.endpoint ?? DEFAULT_INGEST,
112
- props.projectKey,
113
- draft
114
- );
115
- } else {
116
- defaultDeliver(draft);
117
- }
118
- });
119
- y(() => {
120
- if (phase !== "sent") return;
121
- const t2 = setTimeout(() => {
122
- setPhase("idle");
123
- setBundle(null);
124
- setNote("");
125
- }, 2400);
126
- return () => clearTimeout(t2);
127
- }, [phase]);
128
- const startPick = async () => {
129
- setPhase("picking");
130
- try {
131
- const sel = await beginPick("element");
132
- if (!sel) {
133
- setPhase("idle");
134
- return;
135
- }
136
- setBundle(await buildBundle(sel));
137
- setPhase("compose");
138
- } catch {
139
- setPhase("idle");
140
- }
141
- };
142
- const send = async () => {
143
- if (!bundle) return;
144
- setPhase("sending");
145
- const withNote = note.trim() ? { ...bundle, userNote: note.trim() } : bundle;
146
- try {
147
- await sink.submit(withNote);
148
- } finally {
149
- setPhase("sent");
150
- }
151
- };
152
- const reset = () => {
153
- setPhase("idle");
154
- setBundle(null);
155
- setNote("");
156
- };
157
- const dot = k("span", {
158
- style: `width:9px;height:9px;border-radius:3px;background:${C.accent};box-shadow:0 1px 4px ${C.accentRing}`
159
- });
160
- if (phase === "idle" || phase === "picking") {
161
- const picking = phase === "picking";
162
- return k(
163
- "button",
164
- {
165
- onClick: picking ? void 0 : () => void startPick(),
166
- 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 ${C.sans};color:${C.ink};background:${C.surface};border:1px solid ${C.line};border-radius:999px;box-shadow:${C.shadow};letter-spacing:-.01em`
167
- },
168
- picking ? [
169
- k("span", {
170
- style: `width:9px;height:9px;border-radius:50%;background:#5751e6;animation:ipulse 1.1s ${"ease-in-out"} infinite`
171
- }),
172
- k("span", { style: `color:${C.sub}` }, "Click the broken element"),
173
- k("span", { style: `color:${C.faint}` }, "\xB7 Esc to cancel"),
174
- k(
175
- "style",
176
- {},
177
- "@keyframes ipulse{0%,100%{opacity:.35}50%{opacity:1}}"
178
- )
179
- ] : [dot, "Report a problem"]
180
- );
181
- }
182
- const t = bundle?.target;
183
- const targetLabel = t?.componentStack?.[0]?.name ?? t?.selector?.split(">").pop()?.trim() ?? "selection";
184
- const card = (children) => k(
185
- "div",
186
- {
187
- style: `position:fixed;bottom:20px;right:20px;z-index:2147483000;width:344px;font:14px/1.55 ${C.sans};color:${C.ink};background:${C.surface};border:1px solid ${C.line};border-radius:16px;box-shadow:${C.shadow};overflow:hidden`
188
- },
189
- children
190
- );
191
- if (phase === "sent") {
192
- return card([
193
- k(
194
- "div",
195
- { style: "padding:30px 22px;text-align:center" },
196
- [
197
- k(
198
- "div",
199
- {
200
- style: `width:46px;height:46px;border-radius:50%;margin:0 auto 12px;display:flex;align-items:center;justify-content:center;color:#fff;font-size:22px;background:${C.accent};box-shadow:0 6px 18px ${C.accentRing}`
201
- },
202
- "\u2713"
203
- ),
204
- k(
205
- "div",
206
- { style: "font-weight:680;font-size:15px;letter-spacing:-.01em" },
207
- "Report sent"
208
- ),
209
- k(
210
- "div",
211
- { style: `color:${C.sub};margin-top:5px;font-size:13px` },
212
- "The team has everything to reproduce and fix this \u2014 no follow-up needed."
213
- )
214
- ]
215
- )
216
- ]);
217
- }
218
- const sending = phase === "sending";
219
- return card([
220
- k(
221
- "div",
222
- {
223
- style: `display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid ${C.line}`
224
- },
225
- [
226
- k(
227
- "div",
228
- { style: "display:flex;align-items:center;gap:8px;font-weight:680;letter-spacing:-.01em" },
229
- [dot, "Report a problem"]
230
- ),
231
- k(
232
- "button",
233
- {
234
- onClick: reset,
235
- style: `all:unset;cursor:pointer;color:${C.faint};font-size:16px;line-height:1;padding:2px 4px`
236
- },
237
- "\u2715"
238
- )
239
- ]
240
- ),
241
- k("div", { style: "padding:16px" }, [
242
- k(
243
- "div",
244
- {
245
- style: `display:flex;align-items:center;gap:8px;padding:9px 11px;background:${C.surface2};border:1px solid ${C.line};border-radius:10px;font:12px/1.3 ${C.mono};color:${C.sub};margin-bottom:12px`
246
- },
247
- [
248
- k("span", { style: `color:#5751e6` }, "\u25CE"),
249
- k(
250
- "span",
251
- {
252
- style: "overflow:hidden;text-overflow:ellipsis;white-space:nowrap"
253
- },
254
- `${targetLabel}${t?.source ? ` \xB7 ${t.source.file.split("/").pop()}` : ""}`
255
- )
256
- ]
257
- ),
258
- bundle?.screenshot ? k("img", {
259
- src: bundle.screenshot.dataUrl,
260
- style: `width:100%;max-height:120px;object-fit:cover;border:1px solid ${C.line};border-radius:10px;margin-bottom:12px`
261
- }) : bundle?.screenshotUnavailable ? k(
262
- "div",
263
- {
264
- style: `font-size:12px;color:${C.faint};background:${C.surface2};border:1px solid ${C.line};border-radius:10px;padding:10px;margin-bottom:12px;word-break:break-word`
265
- },
266
- // Surface the actual reason inline — helps diagnose
267
- // when a capture lands empty without expecting it.
268
- `Screenshot unavailable \u2014 ${bundle.screenshotUnavailable}`
269
- ) : null,
270
- // Nudge: the screenshot is structurally OK but some content
271
- // couldn't be embedded (non-CORS img / video / canvas). Offer
272
- // a one-tap upgrade to pixel-perfect mode + re-pick.
273
- bundle?.screenshot?.qualityNote && !tabCaptureActive ? k(
274
- "div",
275
- {
276
- style: `display:flex;align-items:center;gap:8px;padding:9px 11px;background:#fff7ed;border:1px solid #fbd9b1;color:#8a4b00;border-radius:10px;font-size:12px;margin-bottom:12px`
277
- },
278
- [
279
- k(
280
- "span",
281
- { style: "flex:1" },
282
- "Some content didn't capture cleanly. Enable tab capture for a pixel-perfect screenshot."
283
- ),
284
- k(
285
- "button",
286
- {
287
- onClick: () => void retryWithPixelPerfect(),
288
- style: `all:unset;cursor:pointer;color:#5751e6;font-weight:600;padding:2px 8px;border:1px solid #c5c2ff;border-radius:6px;background:#fff`
289
- },
290
- "Enable"
291
- )
292
- ]
293
- ) : null,
294
- // Active badge — tells the user why the browser's red "tab
295
- // sharing" indicator is on + lets them stop it.
296
- tabCaptureActive ? k(
297
- "div",
298
- {
299
- style: `display:flex;align-items:center;gap:8px;padding:7px 11px;background:#ecfdf5;border:1px solid #b6e6cf;color:#117a52;border-radius:10px;font-size:11.5px;margin-bottom:12px`
300
- },
301
- [
302
- k("span", {
303
- style: "width:8px;height:8px;border-radius:50%;background:#117a52;box-shadow:0 0 6px #117a52"
304
- }),
305
- k(
306
- "span",
307
- { style: "flex:1" },
308
- "Tab capture active \u2014 screenshots are pixel-perfect."
309
- ),
310
- k(
311
- "button",
312
- {
313
- onClick: () => stopDisplayMedia("user"),
314
- style: `all:unset;cursor:pointer;color:#117a52;font-weight:600;padding:2px 6px`
315
- },
316
- "Stop"
317
- )
318
- ]
319
- ) : null,
320
- k("textarea", {
321
- value: note,
322
- rows: 3,
323
- placeholder: "What's wrong? (optional but helps)",
324
- disabled: sending,
325
- onInput: (e) => setNote(e.target.value),
326
- style: `width:100%;box-sizing:border-box;font:14px/1.5 ${C.sans};color:${C.ink};background:${C.surface};border:1px solid #d8d8de;border-radius:10px;padding:10px 12px;resize:none;outline:none`
327
- }),
328
- k("div", { style: "display:flex;gap:8px;margin-top:12px" }, [
329
- k(
330
- "button",
331
- {
332
- onClick: sending ? void 0 : () => void send(),
333
- disabled: sending,
334
- style: `flex:1;all:unset;text-align:center;cursor:${sending ? "default" : "pointer"};padding:11px;font:680 13.5px/1 ${C.sans};color:#fff;background:${C.accent};border-radius:10px;box-shadow:0 2px 10px ${C.accentRing};opacity:${sending ? ".7" : "1"}`
335
- },
336
- sending ? "Sending\u2026" : "Send report"
337
- ),
338
- k(
339
- "button",
340
- {
341
- onClick: () => void startPick(),
342
- style: `all:unset;cursor:pointer;padding:11px 14px;font:600 13.5px/1 ${C.sans};color:${C.sub};background:${C.surface2};border:1px solid ${C.line};border-radius:10px`
343
- },
344
- "Re-pick"
345
- )
346
- ])
347
- ]),
348
- k(
349
- "div",
350
- {
351
- style: `display:flex;justify-content:space-between;padding:9px 16px;border-top:1px solid ${C.line};color:${C.faint};font-size:11px`
352
- },
353
- [
354
- // No "Secrets scrubbed" badge — the redaction is narrow
355
- // (regex on attr-names + console.log args; see
356
- // packages/sdk/src/runtime.ts safeArg, capture-core/dom.ts
357
- // serializeNode). Visible password VALUES, URL query
358
- // params, and any text rendered in the screenshot pixels
359
- // are NOT scrubbed — claiming otherwise misleads reporters
360
- // about what's safe to capture. If we ever build real
361
- // form-value redaction the badge can come back.
362
- k("span", {}, ""),
363
- k(
364
- "span",
365
- { title: `@insitue/sdk@${"0.1.14"}` },
366
- `InSitue \xB7 v${"0.1.14"}`
367
- )
368
- ]
369
- )
370
- ]);
371
- }
372
- function mountCaptureOnly(opts = {}) {
373
- installRuntimeCollectors();
374
- if (opts.defaultPixelPerfect === true) {
375
- setCaptureSettings({ alwaysPixelPerfect: true });
376
- }
377
- const host = document.createElement("div");
378
- host.id = "insitu-capture-root";
379
- host.setAttribute("data-insitu", "");
380
- document.body.appendChild(host);
381
- const shadow = host.attachShadow({ mode: "open" });
382
- const mount = document.createElement("div");
383
- shadow.appendChild(mount);
384
- R(
385
- k(CaptureOnlyApp, {
386
- projectKey: opts.projectKey,
387
- endpoint: opts.endpoint,
388
- onCapture: opts.onCapture
389
- }),
390
- mount
391
- );
392
- return () => {
393
- R(null, mount);
394
- host.remove();
395
- };
396
- }
397
-
398
- export {
399
- mountCaptureOnly
400
- };