@feedvalue/core 0.1.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/README.md +155 -0
- package/dist/index.cjs +1207 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +626 -0
- package/dist/index.d.ts +626 -0
- package/dist/index.js +1200 -0
- package/dist/index.js.map +1 -0
- package/dist/umd/index.min.js +138 -0
- package/dist/umd/index.min.js.map +1 -0
- package/package.json +70 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @feedvalue/core - Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Core types for the FeedValue SDK. These types are shared across
|
|
5
|
+
* all framework packages (React, Vue) and the vanilla API.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Widget position on screen
|
|
9
|
+
*/
|
|
10
|
+
type WidgetPosition = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left' | 'center';
|
|
11
|
+
/**
|
|
12
|
+
* Widget theme mode
|
|
13
|
+
*/
|
|
14
|
+
type WidgetTheme = 'light' | 'dark' | 'auto';
|
|
15
|
+
/**
|
|
16
|
+
* Trigger icon type
|
|
17
|
+
*/
|
|
18
|
+
type TriggerIconType = 'none' | 'chat' | 'message' | 'feedback' | 'comment' | 'help' | 'lightbulb';
|
|
19
|
+
/**
|
|
20
|
+
* Custom field types
|
|
21
|
+
*/
|
|
22
|
+
type CustomFieldType = 'text' | 'email' | 'emoji';
|
|
23
|
+
/**
|
|
24
|
+
* Emoji sentiment values
|
|
25
|
+
*/
|
|
26
|
+
type EmojiSentiment = 'angry' | 'disappointed' | 'satisfied' | 'excited';
|
|
27
|
+
/**
|
|
28
|
+
* Custom field definition
|
|
29
|
+
*/
|
|
30
|
+
interface CustomField {
|
|
31
|
+
id: string;
|
|
32
|
+
type: CustomFieldType;
|
|
33
|
+
label: string;
|
|
34
|
+
placeholder?: string;
|
|
35
|
+
required: boolean;
|
|
36
|
+
order: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Widget styling configuration
|
|
40
|
+
*/
|
|
41
|
+
interface WidgetStyling {
|
|
42
|
+
primaryColor: string;
|
|
43
|
+
backgroundColor: string;
|
|
44
|
+
textColor: string;
|
|
45
|
+
buttonTextColor: string;
|
|
46
|
+
borderRadius: string;
|
|
47
|
+
customCSS?: string | undefined;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Widget UI configuration
|
|
51
|
+
*/
|
|
52
|
+
interface WidgetUIConfig {
|
|
53
|
+
position: WidgetPosition;
|
|
54
|
+
triggerText: string;
|
|
55
|
+
triggerIcon: TriggerIconType;
|
|
56
|
+
formTitle: string;
|
|
57
|
+
submitButtonText: string;
|
|
58
|
+
thankYouMessage: string;
|
|
59
|
+
showBranding: boolean;
|
|
60
|
+
customFields?: CustomField[] | undefined;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Full widget configuration (from API)
|
|
64
|
+
*/
|
|
65
|
+
interface WidgetConfig {
|
|
66
|
+
widgetId: string;
|
|
67
|
+
widgetKey: string;
|
|
68
|
+
appId: string;
|
|
69
|
+
config: WidgetUIConfig;
|
|
70
|
+
styling: WidgetStyling;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Options passed to FeedValue.init()
|
|
74
|
+
*/
|
|
75
|
+
interface FeedValueOptions {
|
|
76
|
+
/** Widget ID from FeedValue dashboard */
|
|
77
|
+
widgetId: string;
|
|
78
|
+
/** API base URL (defaults to production) */
|
|
79
|
+
apiBaseUrl?: string | undefined;
|
|
80
|
+
/** Enable debug logging */
|
|
81
|
+
debug?: boolean | undefined;
|
|
82
|
+
/** Initial configuration overrides */
|
|
83
|
+
config?: Partial<FeedValueConfig> | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Headless mode - disables all DOM rendering.
|
|
86
|
+
* Use this when you want full control over the UI.
|
|
87
|
+
* The SDK will still fetch config and provide all API methods
|
|
88
|
+
* (open, close, submit, etc.) but won't render any elements.
|
|
89
|
+
*
|
|
90
|
+
* @default false
|
|
91
|
+
*/
|
|
92
|
+
headless?: boolean | undefined;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Runtime configuration (can be changed after init)
|
|
96
|
+
*/
|
|
97
|
+
interface FeedValueConfig {
|
|
98
|
+
/** Widget theme */
|
|
99
|
+
theme: WidgetTheme;
|
|
100
|
+
/** Widget position override */
|
|
101
|
+
position?: WidgetPosition;
|
|
102
|
+
/** Auto-show widget on init */
|
|
103
|
+
autoShow: boolean;
|
|
104
|
+
/** Enable debug logging */
|
|
105
|
+
debug: boolean;
|
|
106
|
+
/** Locale for internationalization */
|
|
107
|
+
locale: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Widget state (for framework integration)
|
|
111
|
+
* Used by useSyncExternalStore in React and reactive refs in Vue
|
|
112
|
+
*/
|
|
113
|
+
interface FeedValueState {
|
|
114
|
+
/** Widget is ready (config loaded) */
|
|
115
|
+
isReady: boolean;
|
|
116
|
+
/** Modal is open */
|
|
117
|
+
isOpen: boolean;
|
|
118
|
+
/** Widget is visible on page */
|
|
119
|
+
isVisible: boolean;
|
|
120
|
+
/** Current error (if any) */
|
|
121
|
+
error: Error | null;
|
|
122
|
+
/** Feedback submission in progress */
|
|
123
|
+
isSubmitting: boolean;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Feedback submission data
|
|
127
|
+
*/
|
|
128
|
+
interface FeedbackData {
|
|
129
|
+
/** Feedback message content */
|
|
130
|
+
message: string;
|
|
131
|
+
/** Sentiment rating (from emoji field) */
|
|
132
|
+
sentiment?: EmojiSentiment | undefined;
|
|
133
|
+
/** Custom field values */
|
|
134
|
+
customFieldValues?: Record<string, string> | undefined;
|
|
135
|
+
/** Page metadata */
|
|
136
|
+
metadata?: FeedbackMetadata | undefined;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Feedback metadata (auto-collected)
|
|
140
|
+
*/
|
|
141
|
+
interface FeedbackMetadata {
|
|
142
|
+
/** Current page URL */
|
|
143
|
+
page_url: string;
|
|
144
|
+
/** Referrer URL */
|
|
145
|
+
referrer?: string | undefined;
|
|
146
|
+
/** User agent string */
|
|
147
|
+
user_agent?: string | undefined;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Event types emitted by FeedValue
|
|
151
|
+
*/
|
|
152
|
+
interface FeedValueEvents {
|
|
153
|
+
/** Widget is ready (config loaded) */
|
|
154
|
+
ready: () => void;
|
|
155
|
+
/** Modal opened */
|
|
156
|
+
open: () => void;
|
|
157
|
+
/** Modal closed */
|
|
158
|
+
close: () => void;
|
|
159
|
+
/** Feedback submitted successfully */
|
|
160
|
+
submit: (feedback: FeedbackData) => void;
|
|
161
|
+
/** Error occurred */
|
|
162
|
+
error: (error: Error) => void;
|
|
163
|
+
/** State changed (for generic listeners) */
|
|
164
|
+
stateChange: (state: FeedValueState) => void;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Event handler type
|
|
168
|
+
*/
|
|
169
|
+
type EventHandler<K extends keyof FeedValueEvents> = FeedValueEvents[K];
|
|
170
|
+
/**
|
|
171
|
+
* User data for identification
|
|
172
|
+
*/
|
|
173
|
+
interface UserData {
|
|
174
|
+
/** User email */
|
|
175
|
+
email?: string;
|
|
176
|
+
/** User display name */
|
|
177
|
+
name?: string;
|
|
178
|
+
/** Custom user properties */
|
|
179
|
+
[key: string]: string | undefined;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* User traits for identify()
|
|
183
|
+
*/
|
|
184
|
+
interface UserTraits {
|
|
185
|
+
/** User email */
|
|
186
|
+
email?: string;
|
|
187
|
+
/** User display name */
|
|
188
|
+
name?: string;
|
|
189
|
+
/** Company or organization */
|
|
190
|
+
company?: string;
|
|
191
|
+
/** User plan/tier */
|
|
192
|
+
plan?: string;
|
|
193
|
+
/** Custom traits */
|
|
194
|
+
[key: string]: unknown;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* User identification data for API submissions
|
|
198
|
+
* Sent with feedback when identify() or setData() has been called
|
|
199
|
+
*/
|
|
200
|
+
interface SubmissionUserData {
|
|
201
|
+
/** User ID (from identify()) */
|
|
202
|
+
user_id?: string;
|
|
203
|
+
/** User email (from setData or identify traits) */
|
|
204
|
+
email?: string;
|
|
205
|
+
/** User display name (from setData or identify traits) */
|
|
206
|
+
name?: string;
|
|
207
|
+
/** Additional user traits (from identify()) */
|
|
208
|
+
traits?: Record<string, unknown>;
|
|
209
|
+
/** Custom user data (from setData()) */
|
|
210
|
+
custom_data?: Record<string, string>;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* API response for widget config
|
|
214
|
+
*/
|
|
215
|
+
interface ConfigResponse {
|
|
216
|
+
widget_id: string;
|
|
217
|
+
widget_key: string;
|
|
218
|
+
config: Partial<WidgetUIConfig>;
|
|
219
|
+
styling: Partial<WidgetStyling>;
|
|
220
|
+
submission_token?: string;
|
|
221
|
+
token_expires_at?: number;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* API response for feedback submission
|
|
225
|
+
*/
|
|
226
|
+
interface FeedbackResponse {
|
|
227
|
+
success: boolean;
|
|
228
|
+
feedback_id: string;
|
|
229
|
+
message?: string;
|
|
230
|
+
blocked?: boolean;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* FeedValue instance interface
|
|
234
|
+
* This is the public API for the widget
|
|
235
|
+
*/
|
|
236
|
+
interface FeedValueInstance {
|
|
237
|
+
/** Initialize the widget (fetch config, prepare DOM) */
|
|
238
|
+
init(): Promise<void>;
|
|
239
|
+
/** Destroy the widget (cleanup DOM, event listeners) */
|
|
240
|
+
destroy(): void;
|
|
241
|
+
/** Open the feedback modal */
|
|
242
|
+
open(): void;
|
|
243
|
+
/** Close the feedback modal */
|
|
244
|
+
close(): void;
|
|
245
|
+
/** Toggle the feedback modal */
|
|
246
|
+
toggle(): void;
|
|
247
|
+
/** Show the trigger button */
|
|
248
|
+
show(): void;
|
|
249
|
+
/** Hide the trigger button */
|
|
250
|
+
hide(): void;
|
|
251
|
+
/** Check if modal is open */
|
|
252
|
+
isOpen(): boolean;
|
|
253
|
+
/** Check if trigger is visible */
|
|
254
|
+
isVisible(): boolean;
|
|
255
|
+
/** Check if widget is ready */
|
|
256
|
+
isReady(): boolean;
|
|
257
|
+
/** Check if running in headless mode (no DOM rendering) */
|
|
258
|
+
isHeadless(): boolean;
|
|
259
|
+
/** Set user data (email, name, custom fields) */
|
|
260
|
+
setData(data: Partial<UserData>): void;
|
|
261
|
+
/** Identify user with ID and traits */
|
|
262
|
+
identify(userId: string, traits?: UserTraits): void;
|
|
263
|
+
/** Reset user data and state */
|
|
264
|
+
reset(): void;
|
|
265
|
+
/** Programmatically submit feedback */
|
|
266
|
+
submit(feedback: Partial<FeedbackData>): Promise<void>;
|
|
267
|
+
/** Subscribe to an event */
|
|
268
|
+
on<K extends keyof FeedValueEvents>(event: K, callback: EventHandler<K>): void;
|
|
269
|
+
/** Subscribe to an event for a single emission */
|
|
270
|
+
once<K extends keyof FeedValueEvents>(event: K, callback: EventHandler<K>): void;
|
|
271
|
+
/** Unsubscribe from an event */
|
|
272
|
+
off<K extends keyof FeedValueEvents>(event: K, callback?: EventHandler<K>): void;
|
|
273
|
+
/** Returns a promise that resolves when the widget is ready */
|
|
274
|
+
waitUntilReady(): Promise<void>;
|
|
275
|
+
/** Update runtime configuration */
|
|
276
|
+
setConfig(config: Partial<FeedValueConfig>): void;
|
|
277
|
+
/** Get current configuration */
|
|
278
|
+
getConfig(): FeedValueConfig;
|
|
279
|
+
/** Subscribe to state changes */
|
|
280
|
+
subscribe(callback: () => void): () => void;
|
|
281
|
+
/** Get current state snapshot */
|
|
282
|
+
getSnapshot(): FeedValueState;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* @feedvalue/core - FeedValue Class
|
|
287
|
+
*
|
|
288
|
+
* Main FeedValue SDK class. Provides the public API for interacting
|
|
289
|
+
* with the feedback widget.
|
|
290
|
+
*
|
|
291
|
+
* For vanilla JavaScript usage, this class also handles DOM rendering.
|
|
292
|
+
* Framework packages (React, Vue) use this class as a headless core.
|
|
293
|
+
*/
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* FeedValue SDK
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* ```ts
|
|
300
|
+
* // Initialize
|
|
301
|
+
* const feedvalue = FeedValue.init({ widgetId: 'abc123' });
|
|
302
|
+
*
|
|
303
|
+
* // Control
|
|
304
|
+
* feedvalue.open();
|
|
305
|
+
* feedvalue.close();
|
|
306
|
+
*
|
|
307
|
+
* // User data
|
|
308
|
+
* feedvalue.setData({ email: 'user@example.com' });
|
|
309
|
+
* feedvalue.identify('user-123', { plan: 'pro' });
|
|
310
|
+
*
|
|
311
|
+
* // Events
|
|
312
|
+
* feedvalue.on('submit', (feedback) => {
|
|
313
|
+
* console.log('Feedback submitted:', feedback);
|
|
314
|
+
* });
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
declare class FeedValue implements FeedValueInstance {
|
|
318
|
+
private readonly widgetId;
|
|
319
|
+
private readonly apiClient;
|
|
320
|
+
private readonly emitter;
|
|
321
|
+
private readonly headless;
|
|
322
|
+
private config;
|
|
323
|
+
private widgetConfig;
|
|
324
|
+
private state;
|
|
325
|
+
private stateSubscribers;
|
|
326
|
+
private stateSnapshot;
|
|
327
|
+
private _userData;
|
|
328
|
+
private _userId;
|
|
329
|
+
private _userTraits;
|
|
330
|
+
private triggerButton;
|
|
331
|
+
private modal;
|
|
332
|
+
private overlay;
|
|
333
|
+
private stylesInjected;
|
|
334
|
+
private autoCloseTimeout;
|
|
335
|
+
/**
|
|
336
|
+
* Create a new FeedValue instance
|
|
337
|
+
* Use FeedValue.init() for public API
|
|
338
|
+
*/
|
|
339
|
+
private constructor();
|
|
340
|
+
/**
|
|
341
|
+
* Initialize FeedValue
|
|
342
|
+
* Returns existing instance if already initialized for this widgetId
|
|
343
|
+
*/
|
|
344
|
+
static init(options: FeedValueOptions): FeedValue;
|
|
345
|
+
/**
|
|
346
|
+
* Get existing instance by widgetId
|
|
347
|
+
*/
|
|
348
|
+
static getInstance(widgetId: string): FeedValue | undefined;
|
|
349
|
+
/**
|
|
350
|
+
* Initialize the widget
|
|
351
|
+
*/
|
|
352
|
+
init(): Promise<void>;
|
|
353
|
+
/**
|
|
354
|
+
* Destroy the widget
|
|
355
|
+
*/
|
|
356
|
+
destroy(): void;
|
|
357
|
+
open(): void;
|
|
358
|
+
close(): void;
|
|
359
|
+
toggle(): void;
|
|
360
|
+
show(): void;
|
|
361
|
+
hide(): void;
|
|
362
|
+
isOpen(): boolean;
|
|
363
|
+
isVisible(): boolean;
|
|
364
|
+
isReady(): boolean;
|
|
365
|
+
isHeadless(): boolean;
|
|
366
|
+
setData(data: Partial<UserData>): void;
|
|
367
|
+
identify(userId: string, traits?: UserTraits): void;
|
|
368
|
+
reset(): void;
|
|
369
|
+
/**
|
|
370
|
+
* Get current user data (for debugging/testing)
|
|
371
|
+
*/
|
|
372
|
+
getUserData(): {
|
|
373
|
+
userId: string | null;
|
|
374
|
+
data: UserData;
|
|
375
|
+
traits: UserTraits;
|
|
376
|
+
};
|
|
377
|
+
submit(feedback: Partial<FeedbackData>): Promise<void>;
|
|
378
|
+
/**
|
|
379
|
+
* Build user data object for API submission
|
|
380
|
+
* Combines data from identify() and setData() calls
|
|
381
|
+
*/
|
|
382
|
+
private buildSubmissionUserData;
|
|
383
|
+
/**
|
|
384
|
+
* Validate feedback data before submission
|
|
385
|
+
* @throws Error if validation fails
|
|
386
|
+
*/
|
|
387
|
+
private validateFeedback;
|
|
388
|
+
on<K extends keyof FeedValueEvents>(event: K, callback: EventHandler<K>): void;
|
|
389
|
+
/**
|
|
390
|
+
* Subscribe to an event for a single emission.
|
|
391
|
+
* The handler will be automatically removed after the first call.
|
|
392
|
+
*/
|
|
393
|
+
once<K extends keyof FeedValueEvents>(event: K, callback: EventHandler<K>): void;
|
|
394
|
+
off<K extends keyof FeedValueEvents>(event: K, callback?: EventHandler<K>): void;
|
|
395
|
+
/**
|
|
396
|
+
* Returns a promise that resolves when the widget is ready.
|
|
397
|
+
* Useful for programmatic initialization flows.
|
|
398
|
+
*
|
|
399
|
+
* @throws {Error} If initialization fails
|
|
400
|
+
*/
|
|
401
|
+
waitUntilReady(): Promise<void>;
|
|
402
|
+
setConfig(config: Partial<FeedValueConfig>): void;
|
|
403
|
+
getConfig(): FeedValueConfig;
|
|
404
|
+
/**
|
|
405
|
+
* Get widget configuration (from API)
|
|
406
|
+
*/
|
|
407
|
+
getWidgetConfig(): WidgetConfig | null;
|
|
408
|
+
/**
|
|
409
|
+
* Subscribe to state changes
|
|
410
|
+
* Used by React's useSyncExternalStore
|
|
411
|
+
*/
|
|
412
|
+
subscribe(callback: () => void): () => void;
|
|
413
|
+
/**
|
|
414
|
+
* Get current state snapshot
|
|
415
|
+
* Used by React's useSyncExternalStore
|
|
416
|
+
*/
|
|
417
|
+
getSnapshot(): FeedValueState;
|
|
418
|
+
/**
|
|
419
|
+
* Update state and notify subscribers
|
|
420
|
+
*/
|
|
421
|
+
private updateState;
|
|
422
|
+
/**
|
|
423
|
+
* Render widget DOM elements (for vanilla usage)
|
|
424
|
+
*/
|
|
425
|
+
private renderWidget;
|
|
426
|
+
/**
|
|
427
|
+
* Sanitize CSS to block potentially dangerous patterns
|
|
428
|
+
* Prevents CSS injection attacks via url(), @import, and other vectors
|
|
429
|
+
*/
|
|
430
|
+
private sanitizeCSS;
|
|
431
|
+
/**
|
|
432
|
+
* Inject CSS styles
|
|
433
|
+
*/
|
|
434
|
+
private injectStyles;
|
|
435
|
+
/**
|
|
436
|
+
* Get base CSS styles
|
|
437
|
+
*/
|
|
438
|
+
private getBaseStyles;
|
|
439
|
+
/**
|
|
440
|
+
* Get trigger button position styles
|
|
441
|
+
*/
|
|
442
|
+
private getPositionStyles;
|
|
443
|
+
/**
|
|
444
|
+
* Get modal position styles
|
|
445
|
+
*/
|
|
446
|
+
private getModalPositionStyles;
|
|
447
|
+
/**
|
|
448
|
+
* Render trigger button using safe DOM methods
|
|
449
|
+
*/
|
|
450
|
+
private renderTrigger;
|
|
451
|
+
/**
|
|
452
|
+
* Render modal using safe DOM methods (no innerHTML)
|
|
453
|
+
*/
|
|
454
|
+
private renderModal;
|
|
455
|
+
/**
|
|
456
|
+
* Handle form submission
|
|
457
|
+
*/
|
|
458
|
+
private handleFormSubmit;
|
|
459
|
+
/**
|
|
460
|
+
* Show error message (safe - uses textContent)
|
|
461
|
+
*/
|
|
462
|
+
private showError;
|
|
463
|
+
/**
|
|
464
|
+
* Show success message using safe DOM methods
|
|
465
|
+
*/
|
|
466
|
+
private showSuccess;
|
|
467
|
+
/**
|
|
468
|
+
* Reset form to initial state
|
|
469
|
+
*/
|
|
470
|
+
private resetForm;
|
|
471
|
+
/**
|
|
472
|
+
* Debug logging
|
|
473
|
+
*/
|
|
474
|
+
private log;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* @feedvalue/core - Type-Safe Event Emitter
|
|
479
|
+
*
|
|
480
|
+
* A minimal, type-safe event emitter for FeedValue events.
|
|
481
|
+
* Provides compile-time type checking for event names and handlers.
|
|
482
|
+
*/
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Type-safe event emitter for FeedValue events
|
|
486
|
+
*
|
|
487
|
+
* @example
|
|
488
|
+
* ```ts
|
|
489
|
+
* const emitter = new TypedEventEmitter();
|
|
490
|
+
*
|
|
491
|
+
* emitter.on('ready', () => console.log('Ready!'));
|
|
492
|
+
* emitter.on('submit', (feedback) => console.log('Submitted:', feedback));
|
|
493
|
+
*
|
|
494
|
+
* emitter.emit('ready');
|
|
495
|
+
* emitter.emit('submit', { message: 'Great app!' });
|
|
496
|
+
* ```
|
|
497
|
+
*/
|
|
498
|
+
declare class TypedEventEmitter {
|
|
499
|
+
private listeners;
|
|
500
|
+
/**
|
|
501
|
+
* Subscribe to an event
|
|
502
|
+
*
|
|
503
|
+
* @param event - Event name
|
|
504
|
+
* @param handler - Event handler function
|
|
505
|
+
*/
|
|
506
|
+
on<K extends keyof FeedValueEvents>(event: K, handler: EventHandler<K>): void;
|
|
507
|
+
/**
|
|
508
|
+
* Subscribe to an event for a single emission.
|
|
509
|
+
* The handler will be automatically removed after the first call.
|
|
510
|
+
*
|
|
511
|
+
* @param event - Event name
|
|
512
|
+
* @param handler - Event handler function
|
|
513
|
+
*/
|
|
514
|
+
once<K extends keyof FeedValueEvents>(event: K, handler: EventHandler<K>): void;
|
|
515
|
+
/**
|
|
516
|
+
* Unsubscribe from an event
|
|
517
|
+
*
|
|
518
|
+
* @param event - Event name
|
|
519
|
+
* @param handler - Optional handler to remove (removes all if not provided)
|
|
520
|
+
*/
|
|
521
|
+
off<K extends keyof FeedValueEvents>(event: K, handler?: EventHandler<K>): void;
|
|
522
|
+
/**
|
|
523
|
+
* Emit an event to all subscribers
|
|
524
|
+
*
|
|
525
|
+
* @param event - Event name
|
|
526
|
+
* @param args - Arguments to pass to handlers
|
|
527
|
+
*/
|
|
528
|
+
emit<K extends keyof FeedValueEvents>(event: K, ...args: Parameters<EventHandler<K>>): void;
|
|
529
|
+
/**
|
|
530
|
+
* Remove all event listeners
|
|
531
|
+
*/
|
|
532
|
+
removeAllListeners(): void;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* @feedvalue/core - API Client
|
|
537
|
+
*
|
|
538
|
+
* Handles all communication with the FeedValue API.
|
|
539
|
+
* Includes request deduplication, caching, and error handling.
|
|
540
|
+
*/
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Default API base URL
|
|
544
|
+
*/
|
|
545
|
+
declare const DEFAULT_API_BASE_URL = "https://api.feedvalue.com";
|
|
546
|
+
/**
|
|
547
|
+
* API client for FeedValue
|
|
548
|
+
*/
|
|
549
|
+
declare class ApiClient {
|
|
550
|
+
private baseUrl;
|
|
551
|
+
private debug;
|
|
552
|
+
private pendingRequests;
|
|
553
|
+
private configCache;
|
|
554
|
+
private submissionToken;
|
|
555
|
+
private tokenExpiresAt;
|
|
556
|
+
private fingerprint;
|
|
557
|
+
constructor(baseUrl?: string, debug?: boolean);
|
|
558
|
+
/**
|
|
559
|
+
* Validate widget ID to prevent path injection attacks
|
|
560
|
+
* @throws Error if widget ID is invalid
|
|
561
|
+
*/
|
|
562
|
+
private validateWidgetId;
|
|
563
|
+
/**
|
|
564
|
+
* Set client fingerprint for anti-abuse protection
|
|
565
|
+
*/
|
|
566
|
+
setFingerprint(fingerprint: string): void;
|
|
567
|
+
/**
|
|
568
|
+
* Get client fingerprint
|
|
569
|
+
*/
|
|
570
|
+
getFingerprint(): string | null;
|
|
571
|
+
/**
|
|
572
|
+
* Check if submission token is valid
|
|
573
|
+
*/
|
|
574
|
+
hasValidToken(): boolean;
|
|
575
|
+
/**
|
|
576
|
+
* Fetch widget configuration
|
|
577
|
+
* Uses caching and request deduplication
|
|
578
|
+
*/
|
|
579
|
+
fetchConfig(widgetId: string): Promise<ConfigResponse>;
|
|
580
|
+
/**
|
|
581
|
+
* Actually fetch config from API
|
|
582
|
+
*/
|
|
583
|
+
private doFetchConfig;
|
|
584
|
+
/**
|
|
585
|
+
* Submit feedback with optional user data
|
|
586
|
+
*/
|
|
587
|
+
submitFeedback(widgetId: string, feedback: FeedbackData, userData?: SubmissionUserData): Promise<FeedbackResponse>;
|
|
588
|
+
/**
|
|
589
|
+
* Parse error from response
|
|
590
|
+
*/
|
|
591
|
+
private parseError;
|
|
592
|
+
/**
|
|
593
|
+
* Clear all caches
|
|
594
|
+
*/
|
|
595
|
+
clearCache(): void;
|
|
596
|
+
/**
|
|
597
|
+
* Debug logging
|
|
598
|
+
*/
|
|
599
|
+
private log;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Simple fingerprint generation for anti-abuse protection.
|
|
604
|
+
* Uses a session-based UUID stored in sessionStorage.
|
|
605
|
+
*
|
|
606
|
+
* This replaces the previous complex fingerprinting system (canvas, WebGL, audio)
|
|
607
|
+
* which was overkill for an MVP feedback widget and raised privacy concerns.
|
|
608
|
+
*/
|
|
609
|
+
/**
|
|
610
|
+
* Generate or retrieve a session fingerprint.
|
|
611
|
+
*
|
|
612
|
+
* The fingerprint is:
|
|
613
|
+
* - Generated once per browser session using crypto.randomUUID()
|
|
614
|
+
* - Stored in sessionStorage for consistency within a session
|
|
615
|
+
* - Automatically cleared when the browser tab/window is closed
|
|
616
|
+
*
|
|
617
|
+
* @returns A unique fingerprint string for the current session
|
|
618
|
+
*/
|
|
619
|
+
declare function generateFingerprint(): string;
|
|
620
|
+
/**
|
|
621
|
+
* Clear the stored fingerprint.
|
|
622
|
+
* Useful for testing or when user requests data reset.
|
|
623
|
+
*/
|
|
624
|
+
declare function clearFingerprint(): void;
|
|
625
|
+
|
|
626
|
+
export { ApiClient, type ConfigResponse, type CustomField, type CustomFieldType, DEFAULT_API_BASE_URL, type EmojiSentiment, type EventHandler, FeedValue, type FeedValueConfig, type FeedValueEvents, type FeedValueInstance, type FeedValueOptions, type FeedValueState, type FeedbackData, type FeedbackMetadata, type FeedbackResponse, type SubmissionUserData, type TriggerIconType, TypedEventEmitter, type UserData, type UserTraits, type WidgetConfig, type WidgetPosition, type WidgetStyling, type WidgetTheme, type WidgetUIConfig, clearFingerprint, generateFingerprint };
|