@bugport.ai/widget 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/README.md +157 -0
- package/dist/index.cjs +8478 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +645 -0
- package/dist/index.d.ts +645 -0
- package/dist/index.js +8382 -0
- package/dist/index.js.map +1 -0
- package/package.json +81 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,645 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { BugPortReplayPayload, ResolvedReplayConfig, ReplayRecorder, BugPortReplayConfig } from '@bugport/capture-core';
|
|
3
|
+
export { BUGPORT_EXCLUDE_SELECTOR, BugPortReplayConfig, BugPortReplayPayload, DEFAULT_REDACT_HEADERS, DEFAULT_REDACT_PATTERNS, REPLAY_EVENT_TYPE, ReplayBuffer, ReplayEvent, ReplayRecorder, ResolvedReplayConfig, buildReplayPayload, createRedactor, isReplayEnabled, normalizeReplayConfig, redactBody, redactHeaders, redactString, redactUrl } from '@bugport/capture-core';
|
|
4
|
+
|
|
5
|
+
/** Intent the author attaches to a piece of feedback. */
|
|
6
|
+
type AnnotationIntent = "fix" | "change" | "question" | "approve";
|
|
7
|
+
/** How severe / blocking a piece of feedback is. */
|
|
8
|
+
type AnnotationSeverity = "blocking" | "important" | "suggestion";
|
|
9
|
+
/** Lifecycle position of an annotation. */
|
|
10
|
+
type AnnotationStatus = "pending" | "acknowledged" | "resolved" | "dismissed";
|
|
11
|
+
/**
|
|
12
|
+
* Axis-aligned rectangle expressed in CSS pixels. Reused for bounding boxes,
|
|
13
|
+
* placement geometry, and the original/current rects of a rearrange action.
|
|
14
|
+
*/
|
|
15
|
+
type Rect = {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Structured payload carried by `kind: "placement"` annotations, describing a
|
|
23
|
+
* component the author wants dropped onto the page.
|
|
24
|
+
*/
|
|
25
|
+
type PlacementDetails = {
|
|
26
|
+
componentType: string;
|
|
27
|
+
width: number;
|
|
28
|
+
height: number;
|
|
29
|
+
scrollY: number;
|
|
30
|
+
text?: string;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Structured payload carried by `kind: "rearrange"` annotations, capturing
|
|
34
|
+
* where an existing element started and where it was moved to.
|
|
35
|
+
*/
|
|
36
|
+
type RearrangeDetails = {
|
|
37
|
+
selector: string;
|
|
38
|
+
label: string;
|
|
39
|
+
tagName: string;
|
|
40
|
+
originalRect: Rect;
|
|
41
|
+
currentRect: Rect;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* The central feedback shape. Exactly seven fields are required — `id`, `x`,
|
|
45
|
+
* `y`, `comment`, `element`, `elementPath`, and `timestamp`. Everything else is
|
|
46
|
+
* optional and may be populated as the annotation gains DOM/React context, is
|
|
47
|
+
* specialised by `kind`, or is synced to the server.
|
|
48
|
+
*/
|
|
49
|
+
type Annotation = {
|
|
50
|
+
id: string;
|
|
51
|
+
/** Horizontal position as a percentage of the viewport width. */
|
|
52
|
+
x: number;
|
|
53
|
+
/**
|
|
54
|
+
* Vertical position in pixels — measured from the top of the document
|
|
55
|
+
* (absolute), or from the top of the viewport when `isFixed` is set.
|
|
56
|
+
*/
|
|
57
|
+
y: number;
|
|
58
|
+
comment: string;
|
|
59
|
+
element: string;
|
|
60
|
+
elementPath: string;
|
|
61
|
+
timestamp: number;
|
|
62
|
+
selectedText?: string;
|
|
63
|
+
boundingBox?: Rect;
|
|
64
|
+
nearbyText?: string;
|
|
65
|
+
cssClasses?: string;
|
|
66
|
+
nearbyElements?: string;
|
|
67
|
+
computedStyles?: string;
|
|
68
|
+
fullPath?: string;
|
|
69
|
+
accessibility?: string;
|
|
70
|
+
/** True when the annotation was produced by a drag selection. */
|
|
71
|
+
isMultiSelect?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* True when the target element uses fixed/sticky positioning, in which case
|
|
74
|
+
* the marker is pinned to the viewport rather than the document.
|
|
75
|
+
*/
|
|
76
|
+
isFixed?: boolean;
|
|
77
|
+
/** React component hierarchy string, e.g. "<App> <Dashboard> <Button>". */
|
|
78
|
+
reactComponents?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Source path derived from React's `_debugSource` (dev mode only),
|
|
81
|
+
* e.g. "src/Button.tsx:42".
|
|
82
|
+
*/
|
|
83
|
+
sourceFile?: string;
|
|
84
|
+
/** Index of a linked drawing stroke, when one exists. */
|
|
85
|
+
drawingIndex?: number;
|
|
86
|
+
/** Per-element boxes used to highlight a multi-select on hover. */
|
|
87
|
+
elementBoundingBoxes?: Rect[];
|
|
88
|
+
/** Annotation flavour. Consumers treat an absent value as "feedback". */
|
|
89
|
+
kind?: "feedback" | "placement" | "rearrange";
|
|
90
|
+
/** Present for placement-kind annotations. */
|
|
91
|
+
placement?: PlacementDetails;
|
|
92
|
+
/** Present for rearrange-kind annotations. */
|
|
93
|
+
rearrange?: RearrangeDetails;
|
|
94
|
+
sessionId?: string;
|
|
95
|
+
url?: string;
|
|
96
|
+
intent?: AnnotationIntent;
|
|
97
|
+
severity?: AnnotationSeverity;
|
|
98
|
+
status?: AnnotationStatus;
|
|
99
|
+
createdAt?: string;
|
|
100
|
+
updatedAt?: string;
|
|
101
|
+
resolvedAt?: string;
|
|
102
|
+
resolvedBy?: "human" | "agent";
|
|
103
|
+
authorId?: string;
|
|
104
|
+
/**
|
|
105
|
+
* Local-only bookkeeping: the Session ID this annotation has been synced to.
|
|
106
|
+
* Never transmitted to the server. The leading underscore is part of the
|
|
107
|
+
* contract.
|
|
108
|
+
*/
|
|
109
|
+
_syncedTo?: string;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/** Console levels the collector can wrap. */
|
|
113
|
+
type BugPortConsoleLevel = "log" | "info" | "warn" | "error" | "debug";
|
|
114
|
+
/** A captured `console.*` call. */
|
|
115
|
+
type BugPortConsoleEvent = {
|
|
116
|
+
id: string;
|
|
117
|
+
type: "console";
|
|
118
|
+
level: BugPortConsoleLevel;
|
|
119
|
+
/** ISO 8601 timestamp. */
|
|
120
|
+
timestamp: string;
|
|
121
|
+
/** Safely-serialised arguments (circular-safe, size-capped). */
|
|
122
|
+
args: unknown[];
|
|
123
|
+
/** Human-readable, redacted single-line message derived from `args`. */
|
|
124
|
+
message: string;
|
|
125
|
+
};
|
|
126
|
+
/** A captured `window.onerror` or `unhandledrejection`. */
|
|
127
|
+
type BugPortRuntimeErrorEvent = {
|
|
128
|
+
id: string;
|
|
129
|
+
type: "runtime_error" | "unhandled_rejection";
|
|
130
|
+
/** ISO 8601 timestamp. */
|
|
131
|
+
timestamp: string;
|
|
132
|
+
message: string;
|
|
133
|
+
stack?: string;
|
|
134
|
+
source?: string;
|
|
135
|
+
line?: number;
|
|
136
|
+
column?: number;
|
|
137
|
+
};
|
|
138
|
+
/** A captured `fetch` or `XMLHttpRequest`. */
|
|
139
|
+
type BugPortNetworkEvent = {
|
|
140
|
+
id: string;
|
|
141
|
+
type: "network";
|
|
142
|
+
transport: "fetch" | "xhr";
|
|
143
|
+
/** ISO 8601 timestamp of when the request started. */
|
|
144
|
+
timestamp: string;
|
|
145
|
+
method: string;
|
|
146
|
+
url: string;
|
|
147
|
+
status?: number;
|
|
148
|
+
statusText?: string;
|
|
149
|
+
durationMs?: number;
|
|
150
|
+
requestHeaders?: Record<string, string>;
|
|
151
|
+
responseHeaders?: Record<string, string>;
|
|
152
|
+
requestBodyPreview?: string;
|
|
153
|
+
responseBodyPreview?: string;
|
|
154
|
+
responseBodyTruncated?: boolean;
|
|
155
|
+
error?: string;
|
|
156
|
+
};
|
|
157
|
+
/** Discriminated union of every diagnostic event the collector can emit. */
|
|
158
|
+
type BugPortDiagnosticEvent = BugPortConsoleEvent | BugPortRuntimeErrorEvent | BugPortNetworkEvent;
|
|
159
|
+
/**
|
|
160
|
+
* App-owner configuration for diagnostics capture. Every field is optional;
|
|
161
|
+
* sensible privacy-preserving defaults are applied by `normalizeDiagnosticsConfig`.
|
|
162
|
+
*/
|
|
163
|
+
type BugPortDiagnosticsConfig = {
|
|
164
|
+
/** Master switch. When false (the default), nothing is instrumented. */
|
|
165
|
+
enabled?: boolean;
|
|
166
|
+
console?: boolean;
|
|
167
|
+
runtimeErrors?: boolean;
|
|
168
|
+
/** Convenience switch enabling both fetch + xhr when their flags are unset. */
|
|
169
|
+
network?: boolean;
|
|
170
|
+
fetch?: boolean;
|
|
171
|
+
xhr?: boolean;
|
|
172
|
+
requestBodies?: boolean;
|
|
173
|
+
responseBodies?: boolean;
|
|
174
|
+
/** Show end-user toggles in the report form (default true when enabled). */
|
|
175
|
+
userControlled?: boolean;
|
|
176
|
+
defaultAttachConsole?: boolean;
|
|
177
|
+
defaultAttachNetwork?: boolean;
|
|
178
|
+
defaultAttachRuntimeErrors?: boolean;
|
|
179
|
+
maxEvents?: number;
|
|
180
|
+
maxConsoleEvents?: number;
|
|
181
|
+
maxNetworkEvents?: number;
|
|
182
|
+
maxRuntimeErrorEvents?: number;
|
|
183
|
+
maxBodySizeBytes?: number;
|
|
184
|
+
allowedUrls?: Array<string | RegExp>;
|
|
185
|
+
deniedUrls?: Array<string | RegExp>;
|
|
186
|
+
/** Extra header names (case-insensitive) to redact, merged with defaults. */
|
|
187
|
+
redactHeaders?: string[];
|
|
188
|
+
/** Extra value patterns to redact from strings, merged with defaults. */
|
|
189
|
+
redactPatterns?: RegExp[];
|
|
190
|
+
/**
|
|
191
|
+
* Final per-event hook. Return a (possibly mutated) event to keep it, or
|
|
192
|
+
* `null` to drop it entirely. Runs after redaction, before storage.
|
|
193
|
+
*/
|
|
194
|
+
beforeSendDiagnostic?: (event: BugPortDiagnosticEvent) => BugPortDiagnosticEvent | null;
|
|
195
|
+
};
|
|
196
|
+
/** Fully-resolved config with all defaults applied. */
|
|
197
|
+
type ResolvedDiagnosticsConfig = {
|
|
198
|
+
enabled: boolean;
|
|
199
|
+
console: boolean;
|
|
200
|
+
runtimeErrors: boolean;
|
|
201
|
+
fetch: boolean;
|
|
202
|
+
xhr: boolean;
|
|
203
|
+
requestBodies: boolean;
|
|
204
|
+
responseBodies: boolean;
|
|
205
|
+
userControlled: boolean;
|
|
206
|
+
defaultAttachConsole: boolean;
|
|
207
|
+
defaultAttachNetwork: boolean;
|
|
208
|
+
defaultAttachRuntimeErrors: boolean;
|
|
209
|
+
maxConsoleEvents: number;
|
|
210
|
+
maxNetworkEvents: number;
|
|
211
|
+
maxRuntimeErrorEvents: number;
|
|
212
|
+
maxBodySizeBytes: number;
|
|
213
|
+
allowedUrls: Array<string | RegExp>;
|
|
214
|
+
deniedUrls: Array<string | RegExp>;
|
|
215
|
+
redactHeaders: string[];
|
|
216
|
+
redactPatterns: RegExp[];
|
|
217
|
+
beforeSendDiagnostic?: (event: BugPortDiagnosticEvent) => BugPortDiagnosticEvent | null;
|
|
218
|
+
};
|
|
219
|
+
/** What the user has consented to attach for a given submission. */
|
|
220
|
+
type DiagnosticsConsent = {
|
|
221
|
+
console: boolean;
|
|
222
|
+
network: boolean;
|
|
223
|
+
runtimeErrors: boolean;
|
|
224
|
+
};
|
|
225
|
+
/** Diagnostics block carried on the widget submission payload. */
|
|
226
|
+
type BugPortDiagnosticsPayload = {
|
|
227
|
+
console?: BugPortConsoleEvent[];
|
|
228
|
+
runtimeErrors?: BugPortRuntimeErrorEvent[];
|
|
229
|
+
network?: BugPortNetworkEvent[];
|
|
230
|
+
/** ISO 8601 timestamp of when the snapshot was taken. */
|
|
231
|
+
capturedAt: string;
|
|
232
|
+
userConsent: DiagnosticsConsent;
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
declare class DiagnosticsCollector {
|
|
236
|
+
private readonly config;
|
|
237
|
+
private readonly redactor;
|
|
238
|
+
private readonly consoleBuffer;
|
|
239
|
+
private readonly runtimeBuffer;
|
|
240
|
+
private readonly networkBuffer;
|
|
241
|
+
private installed;
|
|
242
|
+
private originalConsole;
|
|
243
|
+
private originalFetch;
|
|
244
|
+
private originalXhrOpen;
|
|
245
|
+
private originalXhrSend;
|
|
246
|
+
private originalXhrSetHeader;
|
|
247
|
+
private errorHandler;
|
|
248
|
+
private rejectionHandler;
|
|
249
|
+
private readonly xhrState;
|
|
250
|
+
constructor(config: ResolvedDiagnosticsConfig);
|
|
251
|
+
/** Install configured instrumentation. Safe to call once; no-ops on SSR. */
|
|
252
|
+
install(): void;
|
|
253
|
+
/** Restore every patched global. Idempotent. */
|
|
254
|
+
uninstall(): void;
|
|
255
|
+
/** Push an event through the optional `beforeSendDiagnostic` hook + buffer. */
|
|
256
|
+
private emit;
|
|
257
|
+
private installConsole;
|
|
258
|
+
private captureConsole;
|
|
259
|
+
private installRuntimeErrors;
|
|
260
|
+
private shouldCaptureUrl;
|
|
261
|
+
/** Cap + flag a textual body to the configured byte budget. */
|
|
262
|
+
private capBody;
|
|
263
|
+
/** Extract a safe, redacted request body preview from a fetch/xhr body. */
|
|
264
|
+
private previewRequestBody;
|
|
265
|
+
private installFetch;
|
|
266
|
+
private captureFetchResponse;
|
|
267
|
+
private installXhr;
|
|
268
|
+
private attachXhrListeners;
|
|
269
|
+
getConsoleEvents(): BugPortConsoleEvent[];
|
|
270
|
+
getRuntimeErrorEvents(): BugPortRuntimeErrorEvent[];
|
|
271
|
+
getNetworkEvents(): BugPortNetworkEvent[];
|
|
272
|
+
clear(): void;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/** axe impact taxonomy, kept verbatim (no severity mapping client-side). */
|
|
276
|
+
declare const AXE_IMPACTS: readonly ["critical", "serious", "moderate", "minor"];
|
|
277
|
+
type AxeImpact = (typeof AXE_IMPACTS)[number];
|
|
278
|
+
type A11yScanSummary = {
|
|
279
|
+
violations: number;
|
|
280
|
+
incomplete: number;
|
|
281
|
+
impactCounts: Record<AxeImpact, number>;
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
type A11yScanStatus = "idle" | "running" | "done" | "error";
|
|
285
|
+
/** Controlled prop bundle the settings panel renders the scan section from. */
|
|
286
|
+
type A11yScanControls = {
|
|
287
|
+
status: A11yScanStatus;
|
|
288
|
+
summary: A11yScanSummary | null;
|
|
289
|
+
findings: {
|
|
290
|
+
new: number;
|
|
291
|
+
persisting: number;
|
|
292
|
+
} | null;
|
|
293
|
+
error: string | null;
|
|
294
|
+
onScan: () => void;
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
type WcagLevel = "A" | "AA" | "AAA";
|
|
298
|
+
type WcagCriterionOption = {
|
|
299
|
+
/** Success-criterion id, e.g. "1.4.3". */
|
|
300
|
+
id: string;
|
|
301
|
+
name: string;
|
|
302
|
+
level: Exclude<WcagLevel, "AAA">;
|
|
303
|
+
};
|
|
304
|
+
type WcagPourGroup = {
|
|
305
|
+
/** POUR principle letter: P | O | U | R. */
|
|
306
|
+
principle: string;
|
|
307
|
+
label: string;
|
|
308
|
+
criteria: WcagCriterionOption[];
|
|
309
|
+
};
|
|
310
|
+
declare const WCAG_LEVELS: readonly WcagLevel[];
|
|
311
|
+
/** WCAG 2.2 Level A + AA success criteria grouped by POUR principle. */
|
|
312
|
+
declare const WCAG_CRITERIA_BY_POUR: readonly WcagPourGroup[];
|
|
313
|
+
/** Level for an embedded (A/AA) criterion id; undefined for free-text ids. */
|
|
314
|
+
declare function levelForCriterion(id: string): WcagLevel | undefined;
|
|
315
|
+
|
|
316
|
+
/** Scripted annotation used by demo mode. */
|
|
317
|
+
type DemoAnnotation = {
|
|
318
|
+
selector: string;
|
|
319
|
+
comment: string;
|
|
320
|
+
selectedText?: string;
|
|
321
|
+
};
|
|
322
|
+
/** Captured screenshot attached to a submission. */
|
|
323
|
+
type BugportSubmissionScreenshot = {
|
|
324
|
+
dataUrl: string;
|
|
325
|
+
mimeType: string;
|
|
326
|
+
width: number;
|
|
327
|
+
height: number;
|
|
328
|
+
capturedAt: number;
|
|
329
|
+
};
|
|
330
|
+
/** Payload handed to onSubmitPayload. */
|
|
331
|
+
type BugportSubmissionPayload = {
|
|
332
|
+
title?: string;
|
|
333
|
+
description?: string;
|
|
334
|
+
output: string;
|
|
335
|
+
annotations: Annotation[];
|
|
336
|
+
screenshot?: BugportSubmissionScreenshot;
|
|
337
|
+
/**
|
|
338
|
+
* Optional in-page diagnostics, present only when the app owner enabled
|
|
339
|
+
* capture and the user consented to attach at least one source.
|
|
340
|
+
*/
|
|
341
|
+
diagnostics?: BugPortDiagnosticsPayload;
|
|
342
|
+
/**
|
|
343
|
+
* Optional session replay, present only when the app owner enabled replay
|
|
344
|
+
* capture and the user consented to attach it.
|
|
345
|
+
*/
|
|
346
|
+
replay?: BugPortReplayPayload;
|
|
347
|
+
/**
|
|
348
|
+
* Optional WCAG success criterion picked in the report form's collapsed
|
|
349
|
+
* "Accessibility (WCAG)" section, e.g. "1.4.3".
|
|
350
|
+
*/
|
|
351
|
+
wcagCriterion?: string;
|
|
352
|
+
/** Conformance level of the picked criterion: A | AA | AAA. */
|
|
353
|
+
wcagLevel?: WcagLevel;
|
|
354
|
+
};
|
|
355
|
+
/** Full prop surface of the feedback toolbar. */
|
|
356
|
+
type PageFeedbackToolbarCSSProps = {
|
|
357
|
+
demoAnnotations?: DemoAnnotation[];
|
|
358
|
+
demoDelay?: number;
|
|
359
|
+
enableDemoMode?: boolean;
|
|
360
|
+
onAnnotationAdd?: (annotation: Annotation) => void;
|
|
361
|
+
onAnnotationDelete?: (annotation: Annotation) => void;
|
|
362
|
+
onAnnotationUpdate?: (annotation: Annotation) => void;
|
|
363
|
+
onAnnotationsClear?: (annotations: Annotation[]) => void;
|
|
364
|
+
onCopy?: (markdown: string) => void;
|
|
365
|
+
onSubmit?: (output: string, annotations: Annotation[]) => void | boolean | Promise<void | boolean>;
|
|
366
|
+
onSubmitPayload?: (payload: BugportSubmissionPayload) => void | boolean | Promise<void | boolean>;
|
|
367
|
+
projectKey?: string;
|
|
368
|
+
publicKey?: string;
|
|
369
|
+
copyToClipboard?: boolean;
|
|
370
|
+
className?: string;
|
|
371
|
+
/** Resolved diagnostics config (controls which user toggles are shown). */
|
|
372
|
+
diagnosticsConfig?: ResolvedDiagnosticsConfig;
|
|
373
|
+
/** Live diagnostics collector to snapshot from at submit time. */
|
|
374
|
+
diagnosticsCollector?: DiagnosticsCollector | null;
|
|
375
|
+
/** Resolved replay config (controls whether the replay toggle is shown). */
|
|
376
|
+
replayConfig?: ResolvedReplayConfig;
|
|
377
|
+
/** Live replay recorder to snapshot from at submit time. */
|
|
378
|
+
replayRecorder?: ReplayRecorder | null;
|
|
379
|
+
/**
|
|
380
|
+
* Staff-gated accessibility-scan controls (Widget Mode A). When absent the
|
|
381
|
+
* scan section is never rendered — the gate lives in the package entry.
|
|
382
|
+
*/
|
|
383
|
+
a11yScan?: A11yScanControls;
|
|
384
|
+
};
|
|
385
|
+
/** Public alias for {@link PageFeedbackToolbarCSSProps}. */
|
|
386
|
+
type BugportWidgetProps = PageFeedbackToolbarCSSProps;
|
|
387
|
+
/**
|
|
388
|
+
* Main feedback toolbar. Renders via a portal into document.body and returns
|
|
389
|
+
* null until mounted, or whenever the toolbar has been permanently hidden.
|
|
390
|
+
*/
|
|
391
|
+
declare function PageFeedbackToolbarCSS(props?: PageFeedbackToolbarCSSProps): React.ReactPortal | null;
|
|
392
|
+
|
|
393
|
+
type WidgetReporter = {
|
|
394
|
+
id?: string;
|
|
395
|
+
email?: string;
|
|
396
|
+
name?: string;
|
|
397
|
+
/**
|
|
398
|
+
* Embedder-supplied role hint (e.g. "qa", "staff", "admin", "internal").
|
|
399
|
+
* Gates staff-only widget UX such as the accessibility scan action. This is
|
|
400
|
+
* a client-side hint only — it is never treated as an identity claim and is
|
|
401
|
+
* not sent to the server; the API enforces rate limits, not roles.
|
|
402
|
+
*/
|
|
403
|
+
role?: string;
|
|
404
|
+
};
|
|
405
|
+
type BugPortSubmissionResult = {
|
|
406
|
+
bugId: string;
|
|
407
|
+
dashboardUrl: string;
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
/** Public prop contract for the CSS annotation popup. */
|
|
411
|
+
interface AnnotationPopupCSSProps {
|
|
412
|
+
/** Element name to display in header */
|
|
413
|
+
element: string;
|
|
414
|
+
/** Optional timestamp display (e.g., "@ 1.23s" for animation feedback) */
|
|
415
|
+
timestamp?: string;
|
|
416
|
+
/** Optional selected/highlighted text */
|
|
417
|
+
selectedText?: string;
|
|
418
|
+
/** Placeholder text for the textarea */
|
|
419
|
+
placeholder?: string;
|
|
420
|
+
/** Initial value for textarea (for edit mode) */
|
|
421
|
+
initialValue?: string;
|
|
422
|
+
/** Label for submit button (default: "Add") */
|
|
423
|
+
submitLabel?: string;
|
|
424
|
+
/** Called when annotation is submitted with text */
|
|
425
|
+
onSubmit: (text: string) => void;
|
|
426
|
+
/** Called when popup is cancelled/dismissed */
|
|
427
|
+
onCancel: () => void;
|
|
428
|
+
/** Called when delete button is clicked (only shown if provided) */
|
|
429
|
+
onDelete?: () => void;
|
|
430
|
+
/** Position styles (left, top) */
|
|
431
|
+
style?: React.CSSProperties;
|
|
432
|
+
/** Custom color for submit button and textarea focus (hex) */
|
|
433
|
+
accentColor?: string;
|
|
434
|
+
/** External exit state (parent controls exit animation) */
|
|
435
|
+
isExiting?: boolean;
|
|
436
|
+
/** Light mode styling */
|
|
437
|
+
lightMode?: boolean;
|
|
438
|
+
/** Computed styles for the selected element */
|
|
439
|
+
computedStyles?: Record<string, string>;
|
|
440
|
+
}
|
|
441
|
+
/** Imperative surface that parents can drive through a ref. */
|
|
442
|
+
interface AnnotationPopupCSSHandle {
|
|
443
|
+
/** Shake the popup (e.g., when user clicks outside) */
|
|
444
|
+
shake: () => void;
|
|
445
|
+
}
|
|
446
|
+
declare const AnnotationPopupCSS: react.ForwardRefExoticComponent<AnnotationPopupCSSProps & react.RefAttributes<AnnotationPopupCSSHandle>>;
|
|
447
|
+
|
|
448
|
+
declare const IconClose: ({ size }: {
|
|
449
|
+
size?: number;
|
|
450
|
+
}) => react.JSX.Element;
|
|
451
|
+
declare const IconPlus: ({ size }: {
|
|
452
|
+
size?: number;
|
|
453
|
+
}) => react.JSX.Element;
|
|
454
|
+
declare const IconCheck: ({ size }: {
|
|
455
|
+
size?: number;
|
|
456
|
+
}) => react.JSX.Element;
|
|
457
|
+
declare const IconCheckSmall: ({ size }: {
|
|
458
|
+
size?: number;
|
|
459
|
+
}) => react.JSX.Element;
|
|
460
|
+
declare const IconListSparkle: ({ size, style, }: {
|
|
461
|
+
size?: number;
|
|
462
|
+
style?: React.CSSProperties;
|
|
463
|
+
}) => react.JSX.Element;
|
|
464
|
+
declare const IconBugPortGlyph: ({ size, }: {
|
|
465
|
+
size?: number;
|
|
466
|
+
}) => react.JSX.Element;
|
|
467
|
+
declare const IconHelp: ({ size, ...props }: {
|
|
468
|
+
size?: number;
|
|
469
|
+
} & React.SVGProps<SVGSVGElement>) => react.JSX.Element;
|
|
470
|
+
declare const IconCheckSmallAnimated: ({ size }: {
|
|
471
|
+
size?: number;
|
|
472
|
+
}) => react.JSX.Element;
|
|
473
|
+
declare const IconCopyAlt: ({ size }: {
|
|
474
|
+
size?: number;
|
|
475
|
+
}) => react.JSX.Element;
|
|
476
|
+
declare const IconCamera: ({ size }: {
|
|
477
|
+
size?: number;
|
|
478
|
+
}) => react.JSX.Element;
|
|
479
|
+
declare const IconCopyAnimated: ({ size, copied, tint, }: {
|
|
480
|
+
size?: number;
|
|
481
|
+
copied?: boolean;
|
|
482
|
+
tint?: string;
|
|
483
|
+
}) => react.JSX.Element;
|
|
484
|
+
declare const IconSendArrow: ({ size, state, }: {
|
|
485
|
+
size?: number;
|
|
486
|
+
state?: "idle" | "sending" | "sent" | "failed";
|
|
487
|
+
}) => react.JSX.Element;
|
|
488
|
+
declare const IconSendAnimated: ({ size, sent, }: {
|
|
489
|
+
size?: number;
|
|
490
|
+
sent?: boolean;
|
|
491
|
+
}) => react.JSX.Element;
|
|
492
|
+
declare const IconEye: ({ size }: {
|
|
493
|
+
size?: number;
|
|
494
|
+
}) => react.JSX.Element;
|
|
495
|
+
declare const IconEyeAlt: ({ size }: {
|
|
496
|
+
size?: number;
|
|
497
|
+
}) => react.JSX.Element;
|
|
498
|
+
declare const IconEyeClosed: ({ size }: {
|
|
499
|
+
size?: number;
|
|
500
|
+
}) => react.JSX.Element;
|
|
501
|
+
declare const IconEyeAnimated: ({ size, isOpen, }: {
|
|
502
|
+
size?: number;
|
|
503
|
+
isOpen?: boolean;
|
|
504
|
+
}) => react.JSX.Element;
|
|
505
|
+
declare const IconPausePlayAnimated: ({ size, isPaused, }: {
|
|
506
|
+
size?: number;
|
|
507
|
+
isPaused?: boolean;
|
|
508
|
+
}) => react.JSX.Element;
|
|
509
|
+
declare const IconEyeMinus: ({ size }: {
|
|
510
|
+
size?: number;
|
|
511
|
+
}) => react.JSX.Element;
|
|
512
|
+
declare const IconGear: ({ size }: {
|
|
513
|
+
size?: number;
|
|
514
|
+
}) => react.JSX.Element;
|
|
515
|
+
declare const IconPauseAlt: ({ size }: {
|
|
516
|
+
size?: number;
|
|
517
|
+
}) => react.JSX.Element;
|
|
518
|
+
declare const IconPause: ({ size }: {
|
|
519
|
+
size?: number;
|
|
520
|
+
}) => react.JSX.Element;
|
|
521
|
+
declare const IconPlayAlt: ({ size }: {
|
|
522
|
+
size?: number;
|
|
523
|
+
}) => react.JSX.Element;
|
|
524
|
+
declare const IconTrashAlt: ({ size }: {
|
|
525
|
+
size?: number;
|
|
526
|
+
}) => react.JSX.Element;
|
|
527
|
+
declare const IconChatEllipsis: ({ size, style, }: {
|
|
528
|
+
size?: number;
|
|
529
|
+
style?: React.CSSProperties;
|
|
530
|
+
}) => react.JSX.Element;
|
|
531
|
+
declare const IconCheckmark: ({ size }: {
|
|
532
|
+
size?: number;
|
|
533
|
+
}) => react.JSX.Element;
|
|
534
|
+
declare const IconCheckmarkLarge: ({ size }: {
|
|
535
|
+
size?: number;
|
|
536
|
+
}) => react.JSX.Element;
|
|
537
|
+
declare const IconCheckmarkCircle: ({ size }: {
|
|
538
|
+
size?: number;
|
|
539
|
+
}) => react.JSX.Element;
|
|
540
|
+
declare const IconXmark: ({ size }: {
|
|
541
|
+
size?: number;
|
|
542
|
+
}) => react.JSX.Element;
|
|
543
|
+
declare const IconXmarkLarge: ({ size }: {
|
|
544
|
+
size?: number;
|
|
545
|
+
}) => react.JSX.Element;
|
|
546
|
+
declare const IconSun: ({ size }: {
|
|
547
|
+
size?: number;
|
|
548
|
+
}) => react.JSX.Element;
|
|
549
|
+
declare const IconMoon: ({ size }: {
|
|
550
|
+
size?: number;
|
|
551
|
+
}) => react.JSX.Element;
|
|
552
|
+
declare const IconEdit: ({ size }: {
|
|
553
|
+
size?: number;
|
|
554
|
+
}) => react.JSX.Element;
|
|
555
|
+
declare const IconTrash: ({ size }: {
|
|
556
|
+
size?: number;
|
|
557
|
+
}) => react.JSX.Element;
|
|
558
|
+
declare const IconChevronLeft: ({ size }: {
|
|
559
|
+
size?: number;
|
|
560
|
+
}) => react.JSX.Element;
|
|
561
|
+
declare const IconChevronRight: ({ size }: {
|
|
562
|
+
size?: number;
|
|
563
|
+
}) => react.JSX.Element;
|
|
564
|
+
declare const IconLayout: ({ size }: {
|
|
565
|
+
size?: number;
|
|
566
|
+
}) => react.JSX.Element;
|
|
567
|
+
|
|
568
|
+
declare function closestCrossingShadow(element: Element, selector: string): Element | null;
|
|
569
|
+
declare function isInShadowDOM(element: Element): boolean;
|
|
570
|
+
declare function getShadowHost(element: Element): Element | null;
|
|
571
|
+
declare function getElementPath(target: HTMLElement, maxDepth?: number): string;
|
|
572
|
+
declare function identifyElement(target: HTMLElement): {
|
|
573
|
+
name: string;
|
|
574
|
+
path: string;
|
|
575
|
+
};
|
|
576
|
+
declare function getNearbyText(element: HTMLElement): string;
|
|
577
|
+
declare function identifyAnimationElement(target: HTMLElement): string;
|
|
578
|
+
declare function getElementClasses(target: HTMLElement): string;
|
|
579
|
+
|
|
580
|
+
declare function getStorageKey(pathname: string): string;
|
|
581
|
+
declare function loadAnnotations<T = Annotation>(pathname: string): T[];
|
|
582
|
+
declare function saveAnnotations<T = Annotation>(pathname: string, annotations: T[]): void;
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Role hints accepted as "staff" for showing the accessibility-scan action.
|
|
586
|
+
* Mixes BugPort's workspace-role names (owner / admin / qa_tester) with the
|
|
587
|
+
* generic vocabulary embedders are likely to pass (qa / staff / internal).
|
|
588
|
+
* Matching is case-insensitive and whitespace-tolerant.
|
|
589
|
+
*/
|
|
590
|
+
declare const STAFF_SCAN_ROLES: readonly string[];
|
|
591
|
+
/** True when the embedder-supplied role hint indicates a staff/QA user. */
|
|
592
|
+
declare function isStaffRole(role: string | null | undefined): boolean;
|
|
593
|
+
|
|
594
|
+
declare function normalizeDiagnosticsConfig(config: BugPortDiagnosticsConfig | undefined): ResolvedDiagnosticsConfig;
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Snapshot the collector buffers into a submission payload, including only the
|
|
598
|
+
* sources the user has consented to. Returns `undefined` when nothing is to be
|
|
599
|
+
* attached, keeping the submission byte-for-byte identical to a pre-diagnostics
|
|
600
|
+
* report.
|
|
601
|
+
*/
|
|
602
|
+
declare function buildDiagnosticsPayload(collector: DiagnosticsCollector | null | undefined, consent: DiagnosticsConsent): BugPortDiagnosticsPayload | undefined;
|
|
603
|
+
|
|
604
|
+
type BugPortWidgetProps = Omit<PageFeedbackToolbarCSSProps, "onSubmitPayload" | "diagnosticsConfig" | "diagnosticsCollector" | "replayConfig" | "replayRecorder" | "a11yScan"> & {
|
|
605
|
+
projectKey?: string;
|
|
606
|
+
publicKey?: string;
|
|
607
|
+
environment?: string;
|
|
608
|
+
apiBaseUrl?: string;
|
|
609
|
+
/**
|
|
610
|
+
* The BugPort project id. Required only for the staff-gated accessibility
|
|
611
|
+
* scan (the client-scans endpoint verifies it against the widget key).
|
|
612
|
+
*/
|
|
613
|
+
projectId?: string;
|
|
614
|
+
user?: WidgetReporter;
|
|
615
|
+
/** Optional in-page diagnostics capture configuration. */
|
|
616
|
+
diagnostics?: BugPortDiagnosticsConfig;
|
|
617
|
+
/** Optional session-replay capture configuration. */
|
|
618
|
+
replay?: BugPortReplayConfig;
|
|
619
|
+
/**
|
|
620
|
+
* Opt-in offline queue. When true, submissions that fail because the browser
|
|
621
|
+
* is offline are persisted (IndexedDB) and retried automatically on reconnect
|
|
622
|
+
* and on the next widget mount. Off by default.
|
|
623
|
+
*/
|
|
624
|
+
offlineQueue?: boolean;
|
|
625
|
+
onSubmitted?: (result: BugPortSubmissionResult) => void;
|
|
626
|
+
onError?: (error: Error) => void;
|
|
627
|
+
onSubmitPayload?: (payload: BugportSubmissionPayload) => void | boolean | Promise<void | boolean>;
|
|
628
|
+
};
|
|
629
|
+
declare function BugPortWidget({ projectKey, publicKey, environment, apiBaseUrl, projectId, user, diagnostics, replay, offlineQueue, onSubmitted, onError, onSubmitPayload, ...props }: BugPortWidgetProps): react.JSX.Element;
|
|
630
|
+
declare const BugportWidget: typeof BugPortWidget;
|
|
631
|
+
type BugPortWidgetHandle = {
|
|
632
|
+
destroy: () => void;
|
|
633
|
+
};
|
|
634
|
+
declare function initBugPortWidget(props: BugPortWidgetProps & {
|
|
635
|
+
target?: HTMLElement;
|
|
636
|
+
}): BugPortWidgetHandle;
|
|
637
|
+
declare global {
|
|
638
|
+
interface Window {
|
|
639
|
+
BugPort?: {
|
|
640
|
+
init: typeof initBugPortWidget;
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
export { type A11yScanControls, type A11yScanStatus, type A11yScanSummary, type Annotation, AnnotationPopupCSS, type AnnotationPopupCSSHandle, type AnnotationPopupCSSProps, type BugPortConsoleEvent, type BugPortConsoleLevel, type BugPortDiagnosticEvent, type BugPortDiagnosticsConfig, type BugPortDiagnosticsPayload, type BugPortNetworkEvent, type BugPortRuntimeErrorEvent, type BugPortSubmissionResult, BugPortWidget, type BugPortWidgetHandle, type BugPortWidgetProps, type BugportSubmissionPayload, type BugportSubmissionScreenshot, BugportWidget, type BugportWidgetProps, type DemoAnnotation, DiagnosticsCollector, type DiagnosticsConsent, IconBugPortGlyph, IconCamera, IconChatEllipsis, IconCheck, IconCheckSmall, IconCheckSmallAnimated, IconCheckmark, IconCheckmarkCircle, IconCheckmarkLarge, IconChevronLeft, IconChevronRight, IconClose, IconCopyAlt, IconCopyAnimated, IconEdit, IconEye, IconEyeAlt, IconEyeAnimated, IconEyeClosed, IconEyeMinus, IconGear, IconHelp, IconLayout, IconListSparkle, IconMoon, IconPause, IconPauseAlt, IconPausePlayAnimated, IconPlayAlt, IconPlus, IconSendAnimated, IconSendArrow, IconSun, IconTrash, IconTrashAlt, IconXmark, IconXmarkLarge, PageFeedbackToolbarCSS, type PageFeedbackToolbarCSSProps, type ResolvedDiagnosticsConfig, STAFF_SCAN_ROLES, WCAG_CRITERIA_BY_POUR, WCAG_LEVELS, type WcagCriterionOption, type WcagLevel, type WcagPourGroup, type WidgetReporter, buildDiagnosticsPayload, closestCrossingShadow, getElementClasses, getElementPath, getNearbyText, getShadowHost, getStorageKey, identifyAnimationElement, identifyElement, initBugPortWidget, isInShadowDOM, isStaffRole, levelForCriterion, loadAnnotations, normalizeDiagnosticsConfig, saveAnnotations };
|