@feedvalue/core 0.1.9 → 0.1.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/index.d.cts CHANGED
@@ -66,7 +66,8 @@ interface WidgetConfig {
66
66
  widgetId: string;
67
67
  widgetKey: string;
68
68
  appId: string;
69
- config: WidgetUIConfig;
69
+ type: WidgetType;
70
+ config: WidgetUIConfig & Partial<ReactionConfig>;
70
71
  styling: WidgetStyling;
71
72
  }
72
73
  /**
@@ -146,6 +147,135 @@ interface FeedbackMetadata {
146
147
  /** User agent string */
147
148
  user_agent?: string | undefined;
148
149
  }
150
+ /**
151
+ * Widget type - feedback (modal form) or reaction (inline buttons)
152
+ */
153
+ type WidgetType = 'feedback' | 'reaction';
154
+ /**
155
+ * Reaction template presets
156
+ */
157
+ type ReactionTemplate = 'thumbs' | 'helpful' | 'emoji' | 'rating';
158
+ /**
159
+ * Button size options
160
+ */
161
+ type ButtonSize = 'sm' | 'md' | 'lg';
162
+ /**
163
+ * Follow-up trigger options
164
+ */
165
+ type FollowUpTrigger = 'negative' | 'all' | 'none';
166
+ /**
167
+ * Border radius options for reaction buttons
168
+ */
169
+ type ReactionBorderRadius = 'full' | 'lg' | 'md' | 'sm' | 'none';
170
+ /**
171
+ * Border width options for reaction buttons
172
+ */
173
+ type ReactionBorderWidth = '0' | '1' | '2' | '3' | '4';
174
+ /**
175
+ * Reaction widget styling configuration
176
+ */
177
+ interface ReactionStyling {
178
+ /** Primary/accent color (hex) */
179
+ primaryColor?: string;
180
+ /** Button background color (hex) */
181
+ backgroundColor?: string;
182
+ /** Text color (hex) */
183
+ textColor?: string;
184
+ /** Button label text color (hex) */
185
+ buttonTextColor?: string;
186
+ /** Border color (hex) */
187
+ borderColor?: string;
188
+ /** Border width preset */
189
+ borderWidth?: ReactionBorderWidth;
190
+ /** Border radius preset */
191
+ borderRadius?: ReactionBorderRadius;
192
+ }
193
+ /**
194
+ * Map of negative reaction options for each template.
195
+ * Used to determine when to show follow-up input when followUpTrigger is 'negative'.
196
+ *
197
+ * @example
198
+ * ```ts
199
+ * import { NEGATIVE_OPTIONS_MAP, ReactionTemplate } from '@feedvalue/core';
200
+ *
201
+ * const template: ReactionTemplate = 'thumbs';
202
+ * const isNegative = NEGATIVE_OPTIONS_MAP[template].includes('not_helpful'); // true
203
+ * ```
204
+ */
205
+ declare const NEGATIVE_OPTIONS_MAP: Record<ReactionTemplate, string[]>;
206
+ /**
207
+ * Single reaction option
208
+ */
209
+ interface ReactionOption {
210
+ /** Display label for the option */
211
+ label: string;
212
+ /** Value submitted when selected (lowercase alphanumeric with underscores/hyphens) */
213
+ value: string;
214
+ /** Icon name (Lucide icon) or emoji character */
215
+ icon: string;
216
+ /** Whether to show follow-up text input after selection */
217
+ showFollowUp: boolean;
218
+ /** Placeholder text for follow-up input (if showFollowUp is true) */
219
+ followUpPlaceholder?: string;
220
+ }
221
+ /**
222
+ * Reaction widget configuration
223
+ */
224
+ interface ReactionConfig {
225
+ /** Prebuilt template (if set, options are ignored) */
226
+ template?: ReactionTemplate;
227
+ /** Custom reaction options (required if template is null) */
228
+ options?: ReactionOption[];
229
+ /** Label for follow-up text input */
230
+ followUpLabel: string;
231
+ /** Submit button text for follow-up */
232
+ submitText: string;
233
+ /** Message shown after submission */
234
+ thankYouMessage: string;
235
+ /** Whether to show text labels next to icons */
236
+ showLabels?: boolean;
237
+ /** Button size: 'sm', 'md', or 'lg' */
238
+ buttonSize?: ButtonSize;
239
+ /** When to show follow-up input: 'negative' (default), 'all', or 'none' */
240
+ followUpTrigger?: FollowUpTrigger;
241
+ }
242
+ /**
243
+ * Reaction submission data
244
+ */
245
+ interface ReactionData {
246
+ /** Selected reaction option value */
247
+ value: string;
248
+ /** Optional follow-up text */
249
+ followUp?: string;
250
+ /** Page metadata */
251
+ metadata?: ReactionMetadata;
252
+ }
253
+ /**
254
+ * Reaction metadata (auto-collected)
255
+ */
256
+ interface ReactionMetadata {
257
+ /** Current page URL */
258
+ page_url: string;
259
+ /** Session ID for tracking */
260
+ session_id?: string;
261
+ /** User agent string */
262
+ user_agent?: string;
263
+ }
264
+ /**
265
+ * Reaction submission state (for hooks/components)
266
+ */
267
+ interface ReactionState {
268
+ /** Available reaction options */
269
+ options: ReactionOption[] | null;
270
+ /** Currently submitting */
271
+ isSubmitting: boolean;
272
+ /** Successfully submitted value (null if not yet submitted) */
273
+ submitted: string | null;
274
+ /** Error if submission failed */
275
+ error: Error | null;
276
+ /** Option value requiring follow-up input (null if none) */
277
+ showFollowUp: string | null;
278
+ }
149
279
  /**
150
280
  * Event types emitted by FeedValue
151
281
  */
@@ -162,6 +292,18 @@ interface FeedValueEvents {
162
292
  error: (error: Error) => void;
163
293
  /** State changed (for generic listeners) */
164
294
  stateChange: (state: FeedValueState) => void;
295
+ /** Reaction clicked (before submission) */
296
+ react: (data: {
297
+ value: string;
298
+ hasFollowUp: boolean;
299
+ }) => void;
300
+ /** Reaction submitted successfully */
301
+ reactSubmit: (data: {
302
+ value: string;
303
+ followUp?: string;
304
+ }) => void;
305
+ /** Reaction submission error */
306
+ reactError: (error: Error) => void;
165
307
  }
166
308
  /**
167
309
  * Event handler type
@@ -215,7 +357,8 @@ interface SubmissionUserData {
215
357
  interface ConfigResponse {
216
358
  widget_id: string;
217
359
  widget_key: string;
218
- config: Partial<WidgetUIConfig>;
360
+ type: WidgetType;
361
+ config: Partial<WidgetUIConfig & ReactionConfig>;
219
362
  styling: Partial<WidgetStyling>;
220
363
  submission_token?: string;
221
364
  token_expires_at?: number;
@@ -229,6 +372,16 @@ interface FeedbackResponse {
229
372
  message?: string;
230
373
  blocked?: boolean;
231
374
  }
375
+ /**
376
+ * API response for reaction submission
377
+ */
378
+ interface ReactionResponse {
379
+ success: boolean;
380
+ submission_id: string | null;
381
+ message: string;
382
+ blocked: boolean;
383
+ block_reason?: string;
384
+ }
232
385
  /**
233
386
  * FeedValue instance interface
234
387
  * This is the public API for the widget
@@ -264,6 +417,27 @@ interface FeedValueInstance {
264
417
  reset(): void;
265
418
  /** Programmatically submit feedback */
266
419
  submit(feedback: Partial<FeedbackData>): Promise<void>;
420
+ /**
421
+ * Get reaction options from widget config.
422
+ * Returns null if widget is not a reaction type.
423
+ */
424
+ getReactionOptions(): ReactionOption[] | null;
425
+ /**
426
+ * Submit a reaction.
427
+ * @param value - Selected reaction option value
428
+ * @param options - Optional follow-up text
429
+ */
430
+ react(value: string, options?: {
431
+ followUp?: string;
432
+ }): Promise<void>;
433
+ /**
434
+ * Check if widget is a reaction type
435
+ */
436
+ isReaction(): boolean;
437
+ /**
438
+ * Get widget type ('feedback' or 'reaction')
439
+ */
440
+ getWidgetType(): WidgetType;
267
441
  /** Subscribe to an event */
268
442
  on<K extends keyof FeedValueEvents>(event: K, callback: EventHandler<K>): void;
269
443
  /** Subscribe to an event for a single emission */
@@ -381,6 +555,31 @@ declare class FeedValue implements FeedValueInstance {
381
555
  * Combines data from identify() and setData() calls
382
556
  */
383
557
  private buildSubmissionUserData;
558
+ /**
559
+ * Get reaction options from widget config.
560
+ * Returns null if widget is not a reaction type.
561
+ */
562
+ getReactionOptions(): ReactionOption[] | null;
563
+ /**
564
+ * Get predefined options for a reaction template
565
+ */
566
+ private getTemplateOptions;
567
+ /**
568
+ * Submit a reaction.
569
+ * @param value - Selected reaction option value
570
+ * @param options - Optional follow-up text
571
+ */
572
+ react(value: string, options?: {
573
+ followUp?: string;
574
+ }): Promise<void>;
575
+ /**
576
+ * Check if widget is a reaction type
577
+ */
578
+ isReaction(): boolean;
579
+ /**
580
+ * Get widget type ('feedback' or 'reaction')
581
+ */
582
+ getWidgetType(): WidgetType;
384
583
  /**
385
584
  * Validate feedback data before submission
386
585
  * @throws Error if validation fails
@@ -604,6 +803,10 @@ declare class ApiClient {
604
803
  * Submit feedback with optional user data
605
804
  */
606
805
  submitFeedback(widgetId: string, feedback: FeedbackData, userData?: SubmissionUserData): Promise<FeedbackResponse>;
806
+ /**
807
+ * Submit reaction
808
+ */
809
+ submitReaction(widgetId: string, reaction: ReactionData): Promise<ReactionResponse>;
607
810
  /**
608
811
  * Parse error from response
609
812
  */
@@ -645,4 +848,4 @@ declare function generateFingerprint(): string;
645
848
  */
646
849
  declare function clearFingerprint(): void;
647
850
 
648
- 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 };
851
+ export { ApiClient, type ButtonSize, 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 FollowUpTrigger, NEGATIVE_OPTIONS_MAP, type ReactionBorderRadius, type ReactionBorderWidth, type ReactionConfig, type ReactionData, type ReactionMetadata, type ReactionOption, type ReactionResponse, type ReactionState, type ReactionStyling, type ReactionTemplate, type SubmissionUserData, type TriggerIconType, TypedEventEmitter, type UserData, type UserTraits, type WidgetConfig, type WidgetPosition, type WidgetStyling, type WidgetTheme, type WidgetType, type WidgetUIConfig, clearFingerprint, generateFingerprint };
package/dist/index.d.ts CHANGED
@@ -66,7 +66,8 @@ interface WidgetConfig {
66
66
  widgetId: string;
67
67
  widgetKey: string;
68
68
  appId: string;
69
- config: WidgetUIConfig;
69
+ type: WidgetType;
70
+ config: WidgetUIConfig & Partial<ReactionConfig>;
70
71
  styling: WidgetStyling;
71
72
  }
72
73
  /**
@@ -146,6 +147,135 @@ interface FeedbackMetadata {
146
147
  /** User agent string */
147
148
  user_agent?: string | undefined;
148
149
  }
150
+ /**
151
+ * Widget type - feedback (modal form) or reaction (inline buttons)
152
+ */
153
+ type WidgetType = 'feedback' | 'reaction';
154
+ /**
155
+ * Reaction template presets
156
+ */
157
+ type ReactionTemplate = 'thumbs' | 'helpful' | 'emoji' | 'rating';
158
+ /**
159
+ * Button size options
160
+ */
161
+ type ButtonSize = 'sm' | 'md' | 'lg';
162
+ /**
163
+ * Follow-up trigger options
164
+ */
165
+ type FollowUpTrigger = 'negative' | 'all' | 'none';
166
+ /**
167
+ * Border radius options for reaction buttons
168
+ */
169
+ type ReactionBorderRadius = 'full' | 'lg' | 'md' | 'sm' | 'none';
170
+ /**
171
+ * Border width options for reaction buttons
172
+ */
173
+ type ReactionBorderWidth = '0' | '1' | '2' | '3' | '4';
174
+ /**
175
+ * Reaction widget styling configuration
176
+ */
177
+ interface ReactionStyling {
178
+ /** Primary/accent color (hex) */
179
+ primaryColor?: string;
180
+ /** Button background color (hex) */
181
+ backgroundColor?: string;
182
+ /** Text color (hex) */
183
+ textColor?: string;
184
+ /** Button label text color (hex) */
185
+ buttonTextColor?: string;
186
+ /** Border color (hex) */
187
+ borderColor?: string;
188
+ /** Border width preset */
189
+ borderWidth?: ReactionBorderWidth;
190
+ /** Border radius preset */
191
+ borderRadius?: ReactionBorderRadius;
192
+ }
193
+ /**
194
+ * Map of negative reaction options for each template.
195
+ * Used to determine when to show follow-up input when followUpTrigger is 'negative'.
196
+ *
197
+ * @example
198
+ * ```ts
199
+ * import { NEGATIVE_OPTIONS_MAP, ReactionTemplate } from '@feedvalue/core';
200
+ *
201
+ * const template: ReactionTemplate = 'thumbs';
202
+ * const isNegative = NEGATIVE_OPTIONS_MAP[template].includes('not_helpful'); // true
203
+ * ```
204
+ */
205
+ declare const NEGATIVE_OPTIONS_MAP: Record<ReactionTemplate, string[]>;
206
+ /**
207
+ * Single reaction option
208
+ */
209
+ interface ReactionOption {
210
+ /** Display label for the option */
211
+ label: string;
212
+ /** Value submitted when selected (lowercase alphanumeric with underscores/hyphens) */
213
+ value: string;
214
+ /** Icon name (Lucide icon) or emoji character */
215
+ icon: string;
216
+ /** Whether to show follow-up text input after selection */
217
+ showFollowUp: boolean;
218
+ /** Placeholder text for follow-up input (if showFollowUp is true) */
219
+ followUpPlaceholder?: string;
220
+ }
221
+ /**
222
+ * Reaction widget configuration
223
+ */
224
+ interface ReactionConfig {
225
+ /** Prebuilt template (if set, options are ignored) */
226
+ template?: ReactionTemplate;
227
+ /** Custom reaction options (required if template is null) */
228
+ options?: ReactionOption[];
229
+ /** Label for follow-up text input */
230
+ followUpLabel: string;
231
+ /** Submit button text for follow-up */
232
+ submitText: string;
233
+ /** Message shown after submission */
234
+ thankYouMessage: string;
235
+ /** Whether to show text labels next to icons */
236
+ showLabels?: boolean;
237
+ /** Button size: 'sm', 'md', or 'lg' */
238
+ buttonSize?: ButtonSize;
239
+ /** When to show follow-up input: 'negative' (default), 'all', or 'none' */
240
+ followUpTrigger?: FollowUpTrigger;
241
+ }
242
+ /**
243
+ * Reaction submission data
244
+ */
245
+ interface ReactionData {
246
+ /** Selected reaction option value */
247
+ value: string;
248
+ /** Optional follow-up text */
249
+ followUp?: string;
250
+ /** Page metadata */
251
+ metadata?: ReactionMetadata;
252
+ }
253
+ /**
254
+ * Reaction metadata (auto-collected)
255
+ */
256
+ interface ReactionMetadata {
257
+ /** Current page URL */
258
+ page_url: string;
259
+ /** Session ID for tracking */
260
+ session_id?: string;
261
+ /** User agent string */
262
+ user_agent?: string;
263
+ }
264
+ /**
265
+ * Reaction submission state (for hooks/components)
266
+ */
267
+ interface ReactionState {
268
+ /** Available reaction options */
269
+ options: ReactionOption[] | null;
270
+ /** Currently submitting */
271
+ isSubmitting: boolean;
272
+ /** Successfully submitted value (null if not yet submitted) */
273
+ submitted: string | null;
274
+ /** Error if submission failed */
275
+ error: Error | null;
276
+ /** Option value requiring follow-up input (null if none) */
277
+ showFollowUp: string | null;
278
+ }
149
279
  /**
150
280
  * Event types emitted by FeedValue
151
281
  */
@@ -162,6 +292,18 @@ interface FeedValueEvents {
162
292
  error: (error: Error) => void;
163
293
  /** State changed (for generic listeners) */
164
294
  stateChange: (state: FeedValueState) => void;
295
+ /** Reaction clicked (before submission) */
296
+ react: (data: {
297
+ value: string;
298
+ hasFollowUp: boolean;
299
+ }) => void;
300
+ /** Reaction submitted successfully */
301
+ reactSubmit: (data: {
302
+ value: string;
303
+ followUp?: string;
304
+ }) => void;
305
+ /** Reaction submission error */
306
+ reactError: (error: Error) => void;
165
307
  }
166
308
  /**
167
309
  * Event handler type
@@ -215,7 +357,8 @@ interface SubmissionUserData {
215
357
  interface ConfigResponse {
216
358
  widget_id: string;
217
359
  widget_key: string;
218
- config: Partial<WidgetUIConfig>;
360
+ type: WidgetType;
361
+ config: Partial<WidgetUIConfig & ReactionConfig>;
219
362
  styling: Partial<WidgetStyling>;
220
363
  submission_token?: string;
221
364
  token_expires_at?: number;
@@ -229,6 +372,16 @@ interface FeedbackResponse {
229
372
  message?: string;
230
373
  blocked?: boolean;
231
374
  }
375
+ /**
376
+ * API response for reaction submission
377
+ */
378
+ interface ReactionResponse {
379
+ success: boolean;
380
+ submission_id: string | null;
381
+ message: string;
382
+ blocked: boolean;
383
+ block_reason?: string;
384
+ }
232
385
  /**
233
386
  * FeedValue instance interface
234
387
  * This is the public API for the widget
@@ -264,6 +417,27 @@ interface FeedValueInstance {
264
417
  reset(): void;
265
418
  /** Programmatically submit feedback */
266
419
  submit(feedback: Partial<FeedbackData>): Promise<void>;
420
+ /**
421
+ * Get reaction options from widget config.
422
+ * Returns null if widget is not a reaction type.
423
+ */
424
+ getReactionOptions(): ReactionOption[] | null;
425
+ /**
426
+ * Submit a reaction.
427
+ * @param value - Selected reaction option value
428
+ * @param options - Optional follow-up text
429
+ */
430
+ react(value: string, options?: {
431
+ followUp?: string;
432
+ }): Promise<void>;
433
+ /**
434
+ * Check if widget is a reaction type
435
+ */
436
+ isReaction(): boolean;
437
+ /**
438
+ * Get widget type ('feedback' or 'reaction')
439
+ */
440
+ getWidgetType(): WidgetType;
267
441
  /** Subscribe to an event */
268
442
  on<K extends keyof FeedValueEvents>(event: K, callback: EventHandler<K>): void;
269
443
  /** Subscribe to an event for a single emission */
@@ -381,6 +555,31 @@ declare class FeedValue implements FeedValueInstance {
381
555
  * Combines data from identify() and setData() calls
382
556
  */
383
557
  private buildSubmissionUserData;
558
+ /**
559
+ * Get reaction options from widget config.
560
+ * Returns null if widget is not a reaction type.
561
+ */
562
+ getReactionOptions(): ReactionOption[] | null;
563
+ /**
564
+ * Get predefined options for a reaction template
565
+ */
566
+ private getTemplateOptions;
567
+ /**
568
+ * Submit a reaction.
569
+ * @param value - Selected reaction option value
570
+ * @param options - Optional follow-up text
571
+ */
572
+ react(value: string, options?: {
573
+ followUp?: string;
574
+ }): Promise<void>;
575
+ /**
576
+ * Check if widget is a reaction type
577
+ */
578
+ isReaction(): boolean;
579
+ /**
580
+ * Get widget type ('feedback' or 'reaction')
581
+ */
582
+ getWidgetType(): WidgetType;
384
583
  /**
385
584
  * Validate feedback data before submission
386
585
  * @throws Error if validation fails
@@ -604,6 +803,10 @@ declare class ApiClient {
604
803
  * Submit feedback with optional user data
605
804
  */
606
805
  submitFeedback(widgetId: string, feedback: FeedbackData, userData?: SubmissionUserData): Promise<FeedbackResponse>;
806
+ /**
807
+ * Submit reaction
808
+ */
809
+ submitReaction(widgetId: string, reaction: ReactionData): Promise<ReactionResponse>;
607
810
  /**
608
811
  * Parse error from response
609
812
  */
@@ -645,4 +848,4 @@ declare function generateFingerprint(): string;
645
848
  */
646
849
  declare function clearFingerprint(): void;
647
850
 
648
- 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 };
851
+ export { ApiClient, type ButtonSize, 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 FollowUpTrigger, NEGATIVE_OPTIONS_MAP, type ReactionBorderRadius, type ReactionBorderWidth, type ReactionConfig, type ReactionData, type ReactionMetadata, type ReactionOption, type ReactionResponse, type ReactionState, type ReactionStyling, type ReactionTemplate, type SubmissionUserData, type TriggerIconType, TypedEventEmitter, type UserData, type UserTraits, type WidgetConfig, type WidgetPosition, type WidgetStyling, type WidgetTheme, type WidgetType, type WidgetUIConfig, clearFingerprint, generateFingerprint };