@feedvalue/core 0.1.9 → 0.1.10

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,108 @@ 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
+ * Map of negative reaction options for each template.
168
+ * Used to determine when to show follow-up input when followUpTrigger is 'negative'.
169
+ *
170
+ * @example
171
+ * ```ts
172
+ * import { NEGATIVE_OPTIONS_MAP, ReactionTemplate } from '@feedvalue/core';
173
+ *
174
+ * const template: ReactionTemplate = 'thumbs';
175
+ * const isNegative = NEGATIVE_OPTIONS_MAP[template].includes('not_helpful'); // true
176
+ * ```
177
+ */
178
+ declare const NEGATIVE_OPTIONS_MAP: Record<ReactionTemplate, string[]>;
179
+ /**
180
+ * Single reaction option
181
+ */
182
+ interface ReactionOption {
183
+ /** Display label for the option */
184
+ label: string;
185
+ /** Value submitted when selected (lowercase alphanumeric with underscores/hyphens) */
186
+ value: string;
187
+ /** Icon name (Lucide icon) or emoji character */
188
+ icon: string;
189
+ /** Whether to show follow-up text input after selection */
190
+ showFollowUp: boolean;
191
+ /** Placeholder text for follow-up input (if showFollowUp is true) */
192
+ followUpPlaceholder?: string;
193
+ }
194
+ /**
195
+ * Reaction widget configuration
196
+ */
197
+ interface ReactionConfig {
198
+ /** Prebuilt template (if set, options are ignored) */
199
+ template?: ReactionTemplate;
200
+ /** Custom reaction options (required if template is null) */
201
+ options?: ReactionOption[];
202
+ /** Label for follow-up text input */
203
+ followUpLabel: string;
204
+ /** Submit button text for follow-up */
205
+ submitText: string;
206
+ /** Message shown after submission */
207
+ thankYouMessage: string;
208
+ /** Whether to show text labels next to icons */
209
+ showLabels?: boolean;
210
+ /** Button size: 'sm', 'md', or 'lg' */
211
+ buttonSize?: ButtonSize;
212
+ /** When to show follow-up input: 'negative' (default), 'all', or 'none' */
213
+ followUpTrigger?: FollowUpTrigger;
214
+ }
215
+ /**
216
+ * Reaction submission data
217
+ */
218
+ interface ReactionData {
219
+ /** Selected reaction option value */
220
+ value: string;
221
+ /** Optional follow-up text */
222
+ followUp?: string;
223
+ /** Page metadata */
224
+ metadata?: ReactionMetadata;
225
+ }
226
+ /**
227
+ * Reaction metadata (auto-collected)
228
+ */
229
+ interface ReactionMetadata {
230
+ /** Current page URL */
231
+ page_url: string;
232
+ /** Session ID for tracking */
233
+ session_id?: string;
234
+ /** User agent string */
235
+ user_agent?: string;
236
+ }
237
+ /**
238
+ * Reaction submission state (for hooks/components)
239
+ */
240
+ interface ReactionState {
241
+ /** Available reaction options */
242
+ options: ReactionOption[] | null;
243
+ /** Currently submitting */
244
+ isSubmitting: boolean;
245
+ /** Successfully submitted value (null if not yet submitted) */
246
+ submitted: string | null;
247
+ /** Error if submission failed */
248
+ error: Error | null;
249
+ /** Option value requiring follow-up input (null if none) */
250
+ showFollowUp: string | null;
251
+ }
149
252
  /**
150
253
  * Event types emitted by FeedValue
151
254
  */
@@ -162,6 +265,18 @@ interface FeedValueEvents {
162
265
  error: (error: Error) => void;
163
266
  /** State changed (for generic listeners) */
164
267
  stateChange: (state: FeedValueState) => void;
268
+ /** Reaction clicked (before submission) */
269
+ react: (data: {
270
+ value: string;
271
+ hasFollowUp: boolean;
272
+ }) => void;
273
+ /** Reaction submitted successfully */
274
+ reactSubmit: (data: {
275
+ value: string;
276
+ followUp?: string;
277
+ }) => void;
278
+ /** Reaction submission error */
279
+ reactError: (error: Error) => void;
165
280
  }
166
281
  /**
167
282
  * Event handler type
@@ -215,7 +330,8 @@ interface SubmissionUserData {
215
330
  interface ConfigResponse {
216
331
  widget_id: string;
217
332
  widget_key: string;
218
- config: Partial<WidgetUIConfig>;
333
+ type: WidgetType;
334
+ config: Partial<WidgetUIConfig & ReactionConfig>;
219
335
  styling: Partial<WidgetStyling>;
220
336
  submission_token?: string;
221
337
  token_expires_at?: number;
@@ -229,6 +345,16 @@ interface FeedbackResponse {
229
345
  message?: string;
230
346
  blocked?: boolean;
231
347
  }
348
+ /**
349
+ * API response for reaction submission
350
+ */
351
+ interface ReactionResponse {
352
+ success: boolean;
353
+ submission_id: string | null;
354
+ message: string;
355
+ blocked: boolean;
356
+ block_reason?: string;
357
+ }
232
358
  /**
233
359
  * FeedValue instance interface
234
360
  * This is the public API for the widget
@@ -264,6 +390,27 @@ interface FeedValueInstance {
264
390
  reset(): void;
265
391
  /** Programmatically submit feedback */
266
392
  submit(feedback: Partial<FeedbackData>): Promise<void>;
393
+ /**
394
+ * Get reaction options from widget config.
395
+ * Returns null if widget is not a reaction type.
396
+ */
397
+ getReactionOptions(): ReactionOption[] | null;
398
+ /**
399
+ * Submit a reaction.
400
+ * @param value - Selected reaction option value
401
+ * @param options - Optional follow-up text
402
+ */
403
+ react(value: string, options?: {
404
+ followUp?: string;
405
+ }): Promise<void>;
406
+ /**
407
+ * Check if widget is a reaction type
408
+ */
409
+ isReaction(): boolean;
410
+ /**
411
+ * Get widget type ('feedback' or 'reaction')
412
+ */
413
+ getWidgetType(): WidgetType;
267
414
  /** Subscribe to an event */
268
415
  on<K extends keyof FeedValueEvents>(event: K, callback: EventHandler<K>): void;
269
416
  /** Subscribe to an event for a single emission */
@@ -381,6 +528,31 @@ declare class FeedValue implements FeedValueInstance {
381
528
  * Combines data from identify() and setData() calls
382
529
  */
383
530
  private buildSubmissionUserData;
531
+ /**
532
+ * Get reaction options from widget config.
533
+ * Returns null if widget is not a reaction type.
534
+ */
535
+ getReactionOptions(): ReactionOption[] | null;
536
+ /**
537
+ * Get predefined options for a reaction template
538
+ */
539
+ private getTemplateOptions;
540
+ /**
541
+ * Submit a reaction.
542
+ * @param value - Selected reaction option value
543
+ * @param options - Optional follow-up text
544
+ */
545
+ react(value: string, options?: {
546
+ followUp?: string;
547
+ }): Promise<void>;
548
+ /**
549
+ * Check if widget is a reaction type
550
+ */
551
+ isReaction(): boolean;
552
+ /**
553
+ * Get widget type ('feedback' or 'reaction')
554
+ */
555
+ getWidgetType(): WidgetType;
384
556
  /**
385
557
  * Validate feedback data before submission
386
558
  * @throws Error if validation fails
@@ -604,6 +776,10 @@ declare class ApiClient {
604
776
  * Submit feedback with optional user data
605
777
  */
606
778
  submitFeedback(widgetId: string, feedback: FeedbackData, userData?: SubmissionUserData): Promise<FeedbackResponse>;
779
+ /**
780
+ * Submit reaction
781
+ */
782
+ submitReaction(widgetId: string, reaction: ReactionData): Promise<ReactionResponse>;
607
783
  /**
608
784
  * Parse error from response
609
785
  */
@@ -645,4 +821,4 @@ declare function generateFingerprint(): string;
645
821
  */
646
822
  declare function clearFingerprint(): void;
647
823
 
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 };
824
+ 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 ReactionConfig, type ReactionData, type ReactionMetadata, type ReactionOption, type ReactionResponse, type ReactionState, 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,108 @@ 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
+ * Map of negative reaction options for each template.
168
+ * Used to determine when to show follow-up input when followUpTrigger is 'negative'.
169
+ *
170
+ * @example
171
+ * ```ts
172
+ * import { NEGATIVE_OPTIONS_MAP, ReactionTemplate } from '@feedvalue/core';
173
+ *
174
+ * const template: ReactionTemplate = 'thumbs';
175
+ * const isNegative = NEGATIVE_OPTIONS_MAP[template].includes('not_helpful'); // true
176
+ * ```
177
+ */
178
+ declare const NEGATIVE_OPTIONS_MAP: Record<ReactionTemplate, string[]>;
179
+ /**
180
+ * Single reaction option
181
+ */
182
+ interface ReactionOption {
183
+ /** Display label for the option */
184
+ label: string;
185
+ /** Value submitted when selected (lowercase alphanumeric with underscores/hyphens) */
186
+ value: string;
187
+ /** Icon name (Lucide icon) or emoji character */
188
+ icon: string;
189
+ /** Whether to show follow-up text input after selection */
190
+ showFollowUp: boolean;
191
+ /** Placeholder text for follow-up input (if showFollowUp is true) */
192
+ followUpPlaceholder?: string;
193
+ }
194
+ /**
195
+ * Reaction widget configuration
196
+ */
197
+ interface ReactionConfig {
198
+ /** Prebuilt template (if set, options are ignored) */
199
+ template?: ReactionTemplate;
200
+ /** Custom reaction options (required if template is null) */
201
+ options?: ReactionOption[];
202
+ /** Label for follow-up text input */
203
+ followUpLabel: string;
204
+ /** Submit button text for follow-up */
205
+ submitText: string;
206
+ /** Message shown after submission */
207
+ thankYouMessage: string;
208
+ /** Whether to show text labels next to icons */
209
+ showLabels?: boolean;
210
+ /** Button size: 'sm', 'md', or 'lg' */
211
+ buttonSize?: ButtonSize;
212
+ /** When to show follow-up input: 'negative' (default), 'all', or 'none' */
213
+ followUpTrigger?: FollowUpTrigger;
214
+ }
215
+ /**
216
+ * Reaction submission data
217
+ */
218
+ interface ReactionData {
219
+ /** Selected reaction option value */
220
+ value: string;
221
+ /** Optional follow-up text */
222
+ followUp?: string;
223
+ /** Page metadata */
224
+ metadata?: ReactionMetadata;
225
+ }
226
+ /**
227
+ * Reaction metadata (auto-collected)
228
+ */
229
+ interface ReactionMetadata {
230
+ /** Current page URL */
231
+ page_url: string;
232
+ /** Session ID for tracking */
233
+ session_id?: string;
234
+ /** User agent string */
235
+ user_agent?: string;
236
+ }
237
+ /**
238
+ * Reaction submission state (for hooks/components)
239
+ */
240
+ interface ReactionState {
241
+ /** Available reaction options */
242
+ options: ReactionOption[] | null;
243
+ /** Currently submitting */
244
+ isSubmitting: boolean;
245
+ /** Successfully submitted value (null if not yet submitted) */
246
+ submitted: string | null;
247
+ /** Error if submission failed */
248
+ error: Error | null;
249
+ /** Option value requiring follow-up input (null if none) */
250
+ showFollowUp: string | null;
251
+ }
149
252
  /**
150
253
  * Event types emitted by FeedValue
151
254
  */
@@ -162,6 +265,18 @@ interface FeedValueEvents {
162
265
  error: (error: Error) => void;
163
266
  /** State changed (for generic listeners) */
164
267
  stateChange: (state: FeedValueState) => void;
268
+ /** Reaction clicked (before submission) */
269
+ react: (data: {
270
+ value: string;
271
+ hasFollowUp: boolean;
272
+ }) => void;
273
+ /** Reaction submitted successfully */
274
+ reactSubmit: (data: {
275
+ value: string;
276
+ followUp?: string;
277
+ }) => void;
278
+ /** Reaction submission error */
279
+ reactError: (error: Error) => void;
165
280
  }
166
281
  /**
167
282
  * Event handler type
@@ -215,7 +330,8 @@ interface SubmissionUserData {
215
330
  interface ConfigResponse {
216
331
  widget_id: string;
217
332
  widget_key: string;
218
- config: Partial<WidgetUIConfig>;
333
+ type: WidgetType;
334
+ config: Partial<WidgetUIConfig & ReactionConfig>;
219
335
  styling: Partial<WidgetStyling>;
220
336
  submission_token?: string;
221
337
  token_expires_at?: number;
@@ -229,6 +345,16 @@ interface FeedbackResponse {
229
345
  message?: string;
230
346
  blocked?: boolean;
231
347
  }
348
+ /**
349
+ * API response for reaction submission
350
+ */
351
+ interface ReactionResponse {
352
+ success: boolean;
353
+ submission_id: string | null;
354
+ message: string;
355
+ blocked: boolean;
356
+ block_reason?: string;
357
+ }
232
358
  /**
233
359
  * FeedValue instance interface
234
360
  * This is the public API for the widget
@@ -264,6 +390,27 @@ interface FeedValueInstance {
264
390
  reset(): void;
265
391
  /** Programmatically submit feedback */
266
392
  submit(feedback: Partial<FeedbackData>): Promise<void>;
393
+ /**
394
+ * Get reaction options from widget config.
395
+ * Returns null if widget is not a reaction type.
396
+ */
397
+ getReactionOptions(): ReactionOption[] | null;
398
+ /**
399
+ * Submit a reaction.
400
+ * @param value - Selected reaction option value
401
+ * @param options - Optional follow-up text
402
+ */
403
+ react(value: string, options?: {
404
+ followUp?: string;
405
+ }): Promise<void>;
406
+ /**
407
+ * Check if widget is a reaction type
408
+ */
409
+ isReaction(): boolean;
410
+ /**
411
+ * Get widget type ('feedback' or 'reaction')
412
+ */
413
+ getWidgetType(): WidgetType;
267
414
  /** Subscribe to an event */
268
415
  on<K extends keyof FeedValueEvents>(event: K, callback: EventHandler<K>): void;
269
416
  /** Subscribe to an event for a single emission */
@@ -381,6 +528,31 @@ declare class FeedValue implements FeedValueInstance {
381
528
  * Combines data from identify() and setData() calls
382
529
  */
383
530
  private buildSubmissionUserData;
531
+ /**
532
+ * Get reaction options from widget config.
533
+ * Returns null if widget is not a reaction type.
534
+ */
535
+ getReactionOptions(): ReactionOption[] | null;
536
+ /**
537
+ * Get predefined options for a reaction template
538
+ */
539
+ private getTemplateOptions;
540
+ /**
541
+ * Submit a reaction.
542
+ * @param value - Selected reaction option value
543
+ * @param options - Optional follow-up text
544
+ */
545
+ react(value: string, options?: {
546
+ followUp?: string;
547
+ }): Promise<void>;
548
+ /**
549
+ * Check if widget is a reaction type
550
+ */
551
+ isReaction(): boolean;
552
+ /**
553
+ * Get widget type ('feedback' or 'reaction')
554
+ */
555
+ getWidgetType(): WidgetType;
384
556
  /**
385
557
  * Validate feedback data before submission
386
558
  * @throws Error if validation fails
@@ -604,6 +776,10 @@ declare class ApiClient {
604
776
  * Submit feedback with optional user data
605
777
  */
606
778
  submitFeedback(widgetId: string, feedback: FeedbackData, userData?: SubmissionUserData): Promise<FeedbackResponse>;
779
+ /**
780
+ * Submit reaction
781
+ */
782
+ submitReaction(widgetId: string, reaction: ReactionData): Promise<ReactionResponse>;
607
783
  /**
608
784
  * Parse error from response
609
785
  */
@@ -645,4 +821,4 @@ declare function generateFingerprint(): string;
645
821
  */
646
822
  declare function clearFingerprint(): void;
647
823
 
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 };
824
+ 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 ReactionConfig, type ReactionData, type ReactionMetadata, type ReactionOption, type ReactionResponse, type ReactionState, 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 };