@qaiddev/thumbs-embed 1.0.9 → 1.0.11
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/console-capture.d.ts +20 -0
- package/dist/dom-utils.d.ts +37 -0
- package/dist/element-selector.d.ts +33 -0
- package/dist/embed.d.ts +109 -0
- package/dist/icons.d.ts +6 -0
- package/dist/index.d.ts +38 -411
- package/dist/modal-positioning.d.ts +46 -0
- package/dist/network-capture.d.ts +13 -0
- package/dist/qaid.js +254 -209
- package/dist/qaid.js.map +1 -1
- package/dist/qaid.umd.cjs +6 -6
- package/dist/qaid.umd.cjs.map +1 -1
- package/dist/screenshot-dom.d.ts +27 -0
- package/dist/screenshot.d.ts +17 -0
- package/dist/styles.d.ts +44 -0
- package/dist/types.d.ts +237 -0
- package/dist/video-capture.d.ts +34 -0
- package/package.json +2 -3
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Console capture utilities
|
|
3
|
+
*/
|
|
4
|
+
import type { ConsoleError } from "./types";
|
|
5
|
+
export interface ConsoleCapture {
|
|
6
|
+
errors: ConsoleError[];
|
|
7
|
+
restore: () => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Wrap console methods to capture messages
|
|
11
|
+
*/
|
|
12
|
+
export declare function captureConsoleErrors(onError?: (error: ConsoleError) => void): ConsoleCapture;
|
|
13
|
+
/**
|
|
14
|
+
* Add an error to the captured errors array
|
|
15
|
+
*/
|
|
16
|
+
export declare function addError(errors: ConsoleError[], error: ConsoleError): void;
|
|
17
|
+
/**
|
|
18
|
+
* Format console error for display
|
|
19
|
+
*/
|
|
20
|
+
export declare function formatError(error: ConsoleError): string;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM utility functions
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Create an element with attributes and optional children
|
|
6
|
+
*/
|
|
7
|
+
export declare function createElement<K extends keyof HTMLElementTagNameMap>(tag: K, attrs?: Record<string, string>, children?: (Node | string)[]): HTMLElementTagNameMap[K];
|
|
8
|
+
/**
|
|
9
|
+
* Check if viewport width indicates mobile device
|
|
10
|
+
*/
|
|
11
|
+
export declare function isMobileViewport(breakpoint?: number): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Get element at point, temporarily hiding shadow hosts so elementFromPoint
|
|
14
|
+
* sees through to the page elements underneath.
|
|
15
|
+
* Uses visibility:hidden which skips the element in elementFromPoint without
|
|
16
|
+
* triggering reflow.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getElementAtPointUnderOverlay(x: number, y: number, hosts: HTMLElement[]): Element | null;
|
|
19
|
+
/**
|
|
20
|
+
* Check if an element is part of the feedback embed
|
|
21
|
+
* With shadow DOM, embed elements are inside shadow hosts marked with
|
|
22
|
+
* data-qaid-embed or data-qaid-embed-overlay
|
|
23
|
+
*/
|
|
24
|
+
export declare function isEmbedElement(element: Element | null): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Get element bounds with optional padding
|
|
27
|
+
*/
|
|
28
|
+
export declare function getElementBounds(element: Element, padding?: number): {
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
width: number;
|
|
32
|
+
height: number;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Remove all elements with a specific class
|
|
36
|
+
*/
|
|
37
|
+
export declare function removeAllByClass(className: string): void;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Element selector generation utilities
|
|
3
|
+
*/
|
|
4
|
+
/** Data attributes to look for (in priority order) */
|
|
5
|
+
export declare const DATA_ATTRS: string[];
|
|
6
|
+
export interface ElementInfo {
|
|
7
|
+
selector: string;
|
|
8
|
+
text: string;
|
|
9
|
+
dataAttr: string | null;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Find the first matching data attribute on an element or its ancestors
|
|
13
|
+
*/
|
|
14
|
+
export declare function findDataAttribute(element: Element, stopAt?: Element): string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Get truncated text content from an element
|
|
17
|
+
*/
|
|
18
|
+
export declare function getTruncatedText(element: Element, maxLength?: number): string;
|
|
19
|
+
/**
|
|
20
|
+
* Generate an nth-child path from body to the element
|
|
21
|
+
* This is always a valid CSS selector and uniquely identifies the element
|
|
22
|
+
* Exported for testing
|
|
23
|
+
*/
|
|
24
|
+
export declare function generateNthChildPath(element: Element): string;
|
|
25
|
+
/**
|
|
26
|
+
* Generate a selector string for an element
|
|
27
|
+
* Priority: data attribute > ID > nth-child path
|
|
28
|
+
*/
|
|
29
|
+
export declare function generateSelector(element: Element): string;
|
|
30
|
+
/**
|
|
31
|
+
* Generate complete element info for feedback
|
|
32
|
+
*/
|
|
33
|
+
export declare function generateElementInfo(element: Element): ElementInfo;
|
package/dist/embed.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { FeedbackConfig } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* QaidFeedback - Standalone feedback collection embed
|
|
4
|
+
*/
|
|
5
|
+
export declare class QaidFeedback {
|
|
6
|
+
private config;
|
|
7
|
+
private state;
|
|
8
|
+
private feedbackData;
|
|
9
|
+
private selectedBounds;
|
|
10
|
+
private feedbackId;
|
|
11
|
+
private mousePos;
|
|
12
|
+
private isMobile;
|
|
13
|
+
private visitorId;
|
|
14
|
+
private consoleCapture;
|
|
15
|
+
private videoRecorder;
|
|
16
|
+
private networkCapture;
|
|
17
|
+
private recordedBlob;
|
|
18
|
+
private recordingIndicator;
|
|
19
|
+
private videoPreview;
|
|
20
|
+
private isRecording;
|
|
21
|
+
private isSendingVideo;
|
|
22
|
+
private shadowHost;
|
|
23
|
+
private shadowRoot;
|
|
24
|
+
private overlayShadowHost;
|
|
25
|
+
private overlayShadowRoot;
|
|
26
|
+
private buttonsContainer;
|
|
27
|
+
private isUserProvidedContainer;
|
|
28
|
+
private overlayContainer;
|
|
29
|
+
private captureLayer;
|
|
30
|
+
private crosshairH;
|
|
31
|
+
private crosshairV;
|
|
32
|
+
private scope;
|
|
33
|
+
private highlightBox;
|
|
34
|
+
private marker;
|
|
35
|
+
private modalContainer;
|
|
36
|
+
private backdrop;
|
|
37
|
+
private dismissBtn;
|
|
38
|
+
private cssVars;
|
|
39
|
+
private boundKeyDown;
|
|
40
|
+
private boundMouseMove;
|
|
41
|
+
private boundClick;
|
|
42
|
+
private boundResize;
|
|
43
|
+
private destroyed;
|
|
44
|
+
private domObserver;
|
|
45
|
+
private boundBeforeSwap;
|
|
46
|
+
constructor(config: FeedbackConfig);
|
|
47
|
+
private applyVars;
|
|
48
|
+
private init;
|
|
49
|
+
/**
|
|
50
|
+
* Watch for the shadow hosts being removed from the DOM by framework
|
|
51
|
+
* client-side navigation (e.g. Astro View Transitions swapping <body>
|
|
52
|
+
* contents, or any SPA router that replaces DOM subtrees). If the host
|
|
53
|
+
* is disconnected and destroy() wasn't called, re-append it.
|
|
54
|
+
*
|
|
55
|
+
* Also hooks into Astro's `astro:before-swap` when available, which
|
|
56
|
+
* lets us carry elements into the new document before the swap happens
|
|
57
|
+
* (avoids a flash of the widget disappearing and reappearing).
|
|
58
|
+
*/
|
|
59
|
+
private observeDom;
|
|
60
|
+
private checkMobile;
|
|
61
|
+
private handleResize;
|
|
62
|
+
private createEmbed;
|
|
63
|
+
/**
|
|
64
|
+
* Lazily create a separate overlay shadow host on document.body.
|
|
65
|
+
* This host contains all full-page elements (targeting overlay, marker,
|
|
66
|
+
* backdrop, modal, recording indicator, video preview) so they escape
|
|
67
|
+
* clip-path / transform containing blocks in user containers.
|
|
68
|
+
*/
|
|
69
|
+
private ensureOverlayHost;
|
|
70
|
+
private tooltipElement;
|
|
71
|
+
private showTooltip;
|
|
72
|
+
private hideTooltip;
|
|
73
|
+
private handleDismiss;
|
|
74
|
+
private handleThumbClick;
|
|
75
|
+
private submitDirectFeedback;
|
|
76
|
+
private startTargeting;
|
|
77
|
+
private createTargetingOverlay;
|
|
78
|
+
private handleKeyDown;
|
|
79
|
+
private handleMouseMove;
|
|
80
|
+
private handleClick;
|
|
81
|
+
private cancelTargeting;
|
|
82
|
+
private removeTargetingOverlay;
|
|
83
|
+
private showSelectedMarker;
|
|
84
|
+
private hideSelectedMarker;
|
|
85
|
+
private submitFeedback;
|
|
86
|
+
private showModal;
|
|
87
|
+
private showBottomSheet;
|
|
88
|
+
private showPositionedModal;
|
|
89
|
+
private getModalContent;
|
|
90
|
+
private setupModalInteractions;
|
|
91
|
+
private submitMessage;
|
|
92
|
+
private closeModal;
|
|
93
|
+
private startRecording;
|
|
94
|
+
private stopRecording;
|
|
95
|
+
private showRecordingIndicator;
|
|
96
|
+
private updateRecordingTimer;
|
|
97
|
+
private formatTime;
|
|
98
|
+
private removeRecordingIndicator;
|
|
99
|
+
private showRecordingPreview;
|
|
100
|
+
private cancelRecordingPreview;
|
|
101
|
+
private removeVideoPreview;
|
|
102
|
+
private submitVideoFeedback;
|
|
103
|
+
private cleanupRecording;
|
|
104
|
+
private setButtonsDisabled;
|
|
105
|
+
/**
|
|
106
|
+
* Destroy the embed and clean up all resources
|
|
107
|
+
*/
|
|
108
|
+
destroy(): void;
|
|
109
|
+
}
|
package/dist/icons.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG icon strings for thumbs up/down buttons
|
|
3
|
+
*/
|
|
4
|
+
export declare const THUMBS_UP_ICON = "<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"qaid-icon\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M14 10h4.764a2 2 0 011.789 2.894l-3.5 7A2 2 0 0115.263 21h-4.017c-.163 0-.326-.02-.485-.06L7 20m7-10V5a2 2 0 00-2-2h-.095c-.5 0-.905.405-.905.905 0 .714-.211 1.412-.608 2.006L7 11v9m7-10h-2M7 20H5a2 2 0 01-2-2v-6a2 2 0 012-2h2.5\"/>\n</svg>";
|
|
5
|
+
export declare const THUMBS_DOWN_ICON = "<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"qaid-icon\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M10 14H5.236a2 2 0 01-1.789-2.894l3.5-7A2 2 0 018.737 3h4.018a2 2 0 01.485.06l3.76.94m-7 10v5a2 2 0 002 2h.095c.5 0 .905-.405.905-.905 0-.714.211-1.412.608-2.006L17 13V4m-7 10h2m5-10h2a2 2 0 012 2v6a2 2 0 01-2 2h-2.5\"/>\n</svg>";
|
|
6
|
+
export declare const RECORD_ICON = "<svg xmlns=\"http://www.w3.org/2000/svg\" class=\"qaid-icon\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15.75 10.5l4.72-4.72a.75.75 0 011.28.53v11.38a.75.75 0 01-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25h-9A2.25 2.25 0 002.25 7.5v9a2.25 2.25 0 002.25 2.25z\"/>\n</svg>";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,411 +1,38 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
*
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
*
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Element bounds for server-side screenshot fallback
|
|
41
|
-
*/
|
|
42
|
-
declare interface ElementBounds {
|
|
43
|
-
x: number;
|
|
44
|
-
y: number;
|
|
45
|
-
width: number;
|
|
46
|
-
height: number;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Configuration options for the QaidFeedback
|
|
51
|
-
*/
|
|
52
|
-
export declare interface FeedbackConfig {
|
|
53
|
-
/** Required: API endpoint URL for submitting feedback */
|
|
54
|
-
endpoint: string;
|
|
55
|
-
/** API key for authenticating with the feedback service */
|
|
56
|
-
apiKey?: string;
|
|
57
|
-
/** CSS selector for user-provided container element. If not provided, creates fixed-position container */
|
|
58
|
-
container?: string;
|
|
59
|
-
/** Custom CSS class to apply to thumb buttons. When provided, default button styles are not applied */
|
|
60
|
-
buttonClass?: string;
|
|
61
|
-
/** Button layout direction. Default: 'horizontal' */
|
|
62
|
-
direction?: "horizontal" | "vertical";
|
|
63
|
-
/** Position of the feedback buttons. Default: 'bottom-right'. Ignored if container is provided */
|
|
64
|
-
position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
|
|
65
|
-
/** Offset from edge in pixels. Default: { x: 16, y: 16 } */
|
|
66
|
-
offset?: {
|
|
67
|
-
x?: number;
|
|
68
|
-
y?: number;
|
|
69
|
-
};
|
|
70
|
-
/** z-index for the embed elements. Default: 50 */
|
|
71
|
-
zIndex?: number;
|
|
72
|
-
/** When true, skip element targeting and go directly to feedback modal. Default: false */
|
|
73
|
-
skipTargeting?: boolean;
|
|
74
|
-
/** Custom colors for feedback types */
|
|
75
|
-
colors?: {
|
|
76
|
-
/** Color for positive feedback. Default: rgb(0, 200, 83) */
|
|
77
|
-
positive?: string;
|
|
78
|
-
/** Color for negative feedback. Default: rgb(255, 0, 0) */
|
|
79
|
-
negative?: string;
|
|
80
|
-
/** Color for selected element marker. Default: #6366f1 */
|
|
81
|
-
marker?: string;
|
|
82
|
-
};
|
|
83
|
-
/** Button size. Default: 'medium' (48px). Small: 36px, Large: 64px */
|
|
84
|
-
buttonSize?: "small" | "medium" | "large";
|
|
85
|
-
/** Custom text labels */
|
|
86
|
-
text?: {
|
|
87
|
-
/** Tooltip text for buttons */
|
|
88
|
-
tooltip?: string;
|
|
89
|
-
/** Modal title */
|
|
90
|
-
modalTitle?: string;
|
|
91
|
-
/** Modal subtitle */
|
|
92
|
-
modalSubtitle?: string;
|
|
93
|
-
/** Textarea placeholder */
|
|
94
|
-
placeholder?: string;
|
|
95
|
-
/** Submit button text */
|
|
96
|
-
submitButton?: string;
|
|
97
|
-
/** Skip button text */
|
|
98
|
-
skipButton?: string;
|
|
99
|
-
};
|
|
100
|
-
/** Modal width in pixels. Default: 400 */
|
|
101
|
-
modalWidth?: number;
|
|
102
|
-
/** Backdrop opacity (0-1). Default: 0.3 */
|
|
103
|
-
backdropOpacity?: number;
|
|
104
|
-
/** Font family for text elements. Default: system-ui, -apple-system, sans-serif */
|
|
105
|
-
fontFamily?: string;
|
|
106
|
-
/** Base font size in pixels. Default: 16 */
|
|
107
|
-
fontSize?: number;
|
|
108
|
-
/** Enable screenshot capture with feedback. Default: false */
|
|
109
|
-
captureScreenshot?: boolean;
|
|
110
|
-
/** Enable video recording button. Default: false */
|
|
111
|
-
captureVideo?: boolean;
|
|
112
|
-
/** Video recording options */
|
|
113
|
-
videoOptions?: {
|
|
114
|
-
/** Max recording duration in seconds. Default: 15 */
|
|
115
|
-
maxDuration?: number;
|
|
116
|
-
};
|
|
117
|
-
/** Custom SVG string for record button icon */
|
|
118
|
-
recordIcon?: string;
|
|
119
|
-
/** When true, buttons are hidden until hovered. Default: false */
|
|
120
|
-
incognito?: boolean;
|
|
121
|
-
/** Custom SVG string for positive feedback button icon */
|
|
122
|
-
positiveIcon?: string;
|
|
123
|
-
/** Custom SVG string for negative feedback button icon */
|
|
124
|
-
negativeIcon?: string;
|
|
125
|
-
/** When true, hide thumbs up/down buttons (only show video button if enabled). Default: false */
|
|
126
|
-
hideThumbs?: boolean;
|
|
127
|
-
/** Custom CSS to inject into the embed's shadow root for theming */
|
|
128
|
-
css?: string;
|
|
129
|
-
/** Screenshot capture method. "dom" uses html2canvas (no permission), "permission" uses Screen Capture API. Default: "permission" */
|
|
130
|
-
screenshotMethod?: "dom" | "permission";
|
|
131
|
-
/** Screenshot options */
|
|
132
|
-
screenshotOptions?: {
|
|
133
|
-
/** Quality of WebP compression (0-1). Default: 1.0 */
|
|
134
|
-
quality?: number;
|
|
135
|
-
/** Max width of the screenshot. Default: 1280 */
|
|
136
|
-
maxWidth?: number;
|
|
137
|
-
/** Max height of the screenshot. Default: 800 */
|
|
138
|
-
maxHeight?: number;
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Current feedback data being collected
|
|
144
|
-
*/
|
|
145
|
-
export declare interface FeedbackData {
|
|
146
|
-
feedbackType: "up" | "down" | null;
|
|
147
|
-
elementSelector: string | null;
|
|
148
|
-
elementText: string | null;
|
|
149
|
-
consoleErrors: ConsoleError[];
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Payload for updating feedback with a message
|
|
154
|
-
*/
|
|
155
|
-
export declare interface FeedbackMessagePayload {
|
|
156
|
-
message: string | null;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Payload sent to the feedback API
|
|
161
|
-
*/
|
|
162
|
-
export declare interface FeedbackPayload {
|
|
163
|
-
feedbackType: "up" | "down";
|
|
164
|
-
pageUrl: string;
|
|
165
|
-
/** API key for authenticating with the feedback service */
|
|
166
|
-
apiKey?: string;
|
|
167
|
-
elementSelector: string | null;
|
|
168
|
-
elementText: string | null;
|
|
169
|
-
consoleErrors: ConsoleError[];
|
|
170
|
-
screenWidth: number;
|
|
171
|
-
screenHeight: number;
|
|
172
|
-
clickX: number;
|
|
173
|
-
clickY: number;
|
|
174
|
-
scrollX: number;
|
|
175
|
-
scrollY: number;
|
|
176
|
-
/** Base64-encoded screenshot image (WebP) */
|
|
177
|
-
screenshot: string | null;
|
|
178
|
-
/** Random UUID stored in visitor's localStorage (for anonymous feedback) */
|
|
179
|
-
visitorId: string;
|
|
180
|
-
/** Element bounds for server-side screenshot fallback when client screenshot fails */
|
|
181
|
-
elementBounds?: ElementBounds | null;
|
|
182
|
-
/** User agent string for server-side rendering consistency */
|
|
183
|
-
userAgent?: string;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Response from the feedback API
|
|
188
|
-
*/
|
|
189
|
-
export declare interface FeedbackResponse {
|
|
190
|
-
id: number;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Detect the best supported MIME type for recording
|
|
195
|
-
*/
|
|
196
|
-
export declare function getSupportedMimeType(): string;
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Check if DOM screenshot capture is supported
|
|
200
|
-
* Requires canvas and basic DOM APIs
|
|
201
|
-
*/
|
|
202
|
-
export declare function isDomScreenshotSupported(): boolean;
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Check if video recording is supported in this browser
|
|
206
|
-
*/
|
|
207
|
-
export declare function isVideoRecordingSupported(): boolean;
|
|
208
|
-
|
|
209
|
-
export declare interface NetworkCapture {
|
|
210
|
-
errors: NetworkError[];
|
|
211
|
-
restore: () => void;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Network error captured during the session
|
|
216
|
-
*/
|
|
217
|
-
export declare interface NetworkError {
|
|
218
|
-
url: string;
|
|
219
|
-
method: string;
|
|
220
|
-
status: number;
|
|
221
|
-
statusText: string;
|
|
222
|
-
requestBody?: string;
|
|
223
|
-
responseBody?: string;
|
|
224
|
-
timestamp: number;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* QaidFeedback - Standalone feedback collection embed
|
|
229
|
-
*/
|
|
230
|
-
export declare class QaidFeedback {
|
|
231
|
-
private config;
|
|
232
|
-
private state;
|
|
233
|
-
private feedbackData;
|
|
234
|
-
private selectedBounds;
|
|
235
|
-
private feedbackId;
|
|
236
|
-
private mousePos;
|
|
237
|
-
private isMobile;
|
|
238
|
-
private visitorId;
|
|
239
|
-
private consoleCapture;
|
|
240
|
-
private videoRecorder;
|
|
241
|
-
private networkCapture;
|
|
242
|
-
private recordedBlob;
|
|
243
|
-
private recordingIndicator;
|
|
244
|
-
private videoPreview;
|
|
245
|
-
private isRecording;
|
|
246
|
-
private isSendingVideo;
|
|
247
|
-
private shadowHost;
|
|
248
|
-
private shadowRoot;
|
|
249
|
-
private overlayShadowHost;
|
|
250
|
-
private overlayShadowRoot;
|
|
251
|
-
private buttonsContainer;
|
|
252
|
-
private isUserProvidedContainer;
|
|
253
|
-
private overlayContainer;
|
|
254
|
-
private captureLayer;
|
|
255
|
-
private crosshairH;
|
|
256
|
-
private crosshairV;
|
|
257
|
-
private scope;
|
|
258
|
-
private highlightBox;
|
|
259
|
-
private marker;
|
|
260
|
-
private modalContainer;
|
|
261
|
-
private backdrop;
|
|
262
|
-
private cssVars;
|
|
263
|
-
private boundKeyDown;
|
|
264
|
-
private boundMouseMove;
|
|
265
|
-
private boundClick;
|
|
266
|
-
private boundResize;
|
|
267
|
-
constructor(config: FeedbackConfig);
|
|
268
|
-
private applyVars;
|
|
269
|
-
private init;
|
|
270
|
-
private checkMobile;
|
|
271
|
-
private handleResize;
|
|
272
|
-
private createEmbed;
|
|
273
|
-
/**
|
|
274
|
-
* Lazily create a separate overlay shadow host on document.body.
|
|
275
|
-
* This host contains all full-page elements (targeting overlay, marker,
|
|
276
|
-
* backdrop, modal, recording indicator, video preview) so they escape
|
|
277
|
-
* clip-path / transform containing blocks in user containers.
|
|
278
|
-
*/
|
|
279
|
-
private ensureOverlayHost;
|
|
280
|
-
private tooltipElement;
|
|
281
|
-
private showTooltip;
|
|
282
|
-
private hideTooltip;
|
|
283
|
-
private handleThumbClick;
|
|
284
|
-
private submitDirectFeedback;
|
|
285
|
-
private startTargeting;
|
|
286
|
-
private createTargetingOverlay;
|
|
287
|
-
private handleKeyDown;
|
|
288
|
-
private handleMouseMove;
|
|
289
|
-
private handleClick;
|
|
290
|
-
private cancelTargeting;
|
|
291
|
-
private removeTargetingOverlay;
|
|
292
|
-
private showSelectedMarker;
|
|
293
|
-
private hideSelectedMarker;
|
|
294
|
-
private submitFeedback;
|
|
295
|
-
private showModal;
|
|
296
|
-
private showBottomSheet;
|
|
297
|
-
private showPositionedModal;
|
|
298
|
-
private getModalContent;
|
|
299
|
-
private setupModalInteractions;
|
|
300
|
-
private submitMessage;
|
|
301
|
-
private closeModal;
|
|
302
|
-
private startRecording;
|
|
303
|
-
private stopRecording;
|
|
304
|
-
private showRecordingIndicator;
|
|
305
|
-
private updateRecordingTimer;
|
|
306
|
-
private formatTime;
|
|
307
|
-
private removeRecordingIndicator;
|
|
308
|
-
private showRecordingPreview;
|
|
309
|
-
private cancelRecordingPreview;
|
|
310
|
-
private removeVideoPreview;
|
|
311
|
-
private submitVideoFeedback;
|
|
312
|
-
private cleanupRecording;
|
|
313
|
-
private setButtonsDisabled;
|
|
314
|
-
/**
|
|
315
|
-
* Destroy the embed and clean up all resources
|
|
316
|
-
*/
|
|
317
|
-
destroy(): void;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* Fully resolved configuration with all defaults applied
|
|
322
|
-
* Used internally by the embed after processing user config
|
|
323
|
-
*/
|
|
324
|
-
export declare interface ResolvedFeedbackConfig {
|
|
325
|
-
endpoint: string;
|
|
326
|
-
apiKey: string;
|
|
327
|
-
container: string;
|
|
328
|
-
buttonClass: string;
|
|
329
|
-
direction: "horizontal" | "vertical";
|
|
330
|
-
position: "bottom-right" | "bottom-left" | "top-right" | "top-left";
|
|
331
|
-
offset: {
|
|
332
|
-
x: number;
|
|
333
|
-
y: number;
|
|
334
|
-
};
|
|
335
|
-
zIndex: number;
|
|
336
|
-
skipTargeting: boolean;
|
|
337
|
-
colors: {
|
|
338
|
-
positive: string;
|
|
339
|
-
negative: string;
|
|
340
|
-
marker: string;
|
|
341
|
-
};
|
|
342
|
-
buttonSize: "small" | "medium" | "large";
|
|
343
|
-
text: {
|
|
344
|
-
tooltip: string;
|
|
345
|
-
modalTitle: string;
|
|
346
|
-
modalSubtitle: string;
|
|
347
|
-
placeholder: string;
|
|
348
|
-
submitButton: string;
|
|
349
|
-
skipButton: string;
|
|
350
|
-
};
|
|
351
|
-
modalWidth: number;
|
|
352
|
-
backdropOpacity: number;
|
|
353
|
-
fontFamily: string;
|
|
354
|
-
fontSize: number;
|
|
355
|
-
captureScreenshot: boolean;
|
|
356
|
-
screenshotMethod: "dom" | "permission";
|
|
357
|
-
screenshotOptions: {
|
|
358
|
-
quality: number;
|
|
359
|
-
maxWidth: number;
|
|
360
|
-
maxHeight: number;
|
|
361
|
-
};
|
|
362
|
-
incognito: boolean;
|
|
363
|
-
positiveIcon: string;
|
|
364
|
-
negativeIcon: string;
|
|
365
|
-
hideThumbs: boolean;
|
|
366
|
-
css: string;
|
|
367
|
-
captureVideo: boolean;
|
|
368
|
-
videoOptions: {
|
|
369
|
-
maxDuration: number;
|
|
370
|
-
};
|
|
371
|
-
recordIcon: string;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
/**
|
|
375
|
-
* Bounds of the selected element
|
|
376
|
-
*/
|
|
377
|
-
export declare interface SelectedBounds {
|
|
378
|
-
x: number;
|
|
379
|
-
y: number;
|
|
380
|
-
width: number;
|
|
381
|
-
height: number;
|
|
382
|
-
clickX: number;
|
|
383
|
-
clickY: number;
|
|
384
|
-
visible: boolean;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
export declare interface VideoRecorder {
|
|
388
|
-
/** Start recording. Requests getDisplayMedia if not already started. */
|
|
389
|
-
start(): Promise<void>;
|
|
390
|
-
/** Stop recording and return the video blob. */
|
|
391
|
-
stop(): Promise<Blob>;
|
|
392
|
-
/** Register a callback for each second tick (receives seconds elapsed). */
|
|
393
|
-
onTick(callback: (elapsed: number) => void): void;
|
|
394
|
-
/** Register a callback for when recording stops (e.g., browser stop button, max duration). */
|
|
395
|
-
onStop(callback: (blob: Blob | null) => void): void;
|
|
396
|
-
/** Clean up all resources. */
|
|
397
|
-
destroy(): void;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* Video capture utilities
|
|
402
|
-
* Uses getDisplayMedia + MediaRecorder for screen recording
|
|
403
|
-
*/
|
|
404
|
-
export declare interface VideoRecorderOptions {
|
|
405
|
-
/** Max recording duration in seconds. Default: 15 */
|
|
406
|
-
maxDuration?: number;
|
|
407
|
-
/** Video bitrate in bps. Default: 800000 (800kbps) */
|
|
408
|
-
videoBitsPerSecond?: number;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
export { }
|
|
1
|
+
/**
|
|
2
|
+
* @qaiddev/thumbs-embed - Standalone Feedback Embed
|
|
3
|
+
*
|
|
4
|
+
* A zero-dependency feedback embed with element targeting.
|
|
5
|
+
*
|
|
6
|
+
* Usage via ES module:
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { QaidFeedback } from '@qaiddev/thumbs-embed';
|
|
9
|
+
*
|
|
10
|
+
* const embed = new QaidFeedback({
|
|
11
|
+
* endpoint: '/api/feedback'
|
|
12
|
+
* });
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Usage via script tag:
|
|
16
|
+
* ```html
|
|
17
|
+
* <script src="feedback.umd.cjs" data-endpoint="/api/feedback"></script>
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* Or manually initialize:
|
|
21
|
+
* ```html
|
|
22
|
+
* <script src="feedback.umd.cjs"></script>
|
|
23
|
+
* <script>
|
|
24
|
+
* const embed = new QaidFeedback.QaidFeedback({
|
|
25
|
+
* endpoint: '/api/feedback'
|
|
26
|
+
* });
|
|
27
|
+
* </script>
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
import { QaidFeedback } from "./embed";
|
|
31
|
+
export { QaidFeedback };
|
|
32
|
+
export type { FeedbackConfig, ResolvedFeedbackConfig, ConsoleError, NetworkError, FeedbackData, SelectedBounds, FeedbackPayload, FeedbackResponse, FeedbackMessagePayload, } from "./types";
|
|
33
|
+
export { captureNetworkErrors } from "./network-capture";
|
|
34
|
+
export type { NetworkCapture } from "./network-capture";
|
|
35
|
+
export { createVideoRecorder, isVideoRecordingSupported, getSupportedMimeType } from "./video-capture";
|
|
36
|
+
export type { VideoRecorder, VideoRecorderOptions } from "./video-capture";
|
|
37
|
+
export { captureDomScreenshot, isDomScreenshotSupported } from "./screenshot-dom";
|
|
38
|
+
export type { DomScreenshotOptions } from "./screenshot-dom";
|