@kelet-ai/feedback-ui 1.1.1 → 1.1.4

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 CHANGED
@@ -23,16 +23,16 @@ npx shadcn add https://feedback-ui.kelet.ai/r/vote-feedback.json
23
23
  ```
24
24
 
25
25
  ```tsx
26
- import { ShadcnVoteFeedback } from '@/components/ui/vote-feedback';
26
+ import { ShadcnVoteFeedback } from "@/components/ui/vote-feedback"
27
27
 
28
28
  function App() {
29
29
  return (
30
30
  <ShadcnVoteFeedback
31
31
  session_id="my-feature"
32
- onFeedback={feedback => console.log(feedback)}
32
+ onFeedback={(feedback) => console.log(feedback)}
33
33
  variant="outline"
34
34
  />
35
- );
35
+ )
36
36
  }
37
37
  ```
38
38
 
@@ -89,16 +89,16 @@ npm install @kelet-ai/feedback-ui
89
89
  Users explicitly vote and provide comments:
90
90
 
91
91
  ```tsx
92
- import { VoteFeedback } from '@kelet-ai/feedback-ui';
92
+ import { VoteFeedback } from "@kelet-ai/feedback-ui"
93
93
 
94
- <VoteFeedback.Root onFeedback={handleFeedback} session_id="ai-response">
94
+ ;<VoteFeedback.Root onFeedback={handleFeedback} session_id="ai-response">
95
95
  <VoteFeedback.UpvoteButton>👍 Helpful</VoteFeedback.UpvoteButton>
96
96
  <VoteFeedback.DownvoteButton>👎 Not helpful</VoteFeedback.DownvoteButton>
97
97
  <VoteFeedback.Popover>
98
98
  <VoteFeedback.Textarea placeholder="How can we improve?" />
99
99
  <VoteFeedback.SubmitButton>Send feedback</VoteFeedback.SubmitButton>
100
100
  </VoteFeedback.Popover>
101
- </VoteFeedback.Root>;
101
+ </VoteFeedback.Root>
102
102
  ```
103
103
 
104
104
  ### **Pattern 2: Implicit State Tracking**
@@ -106,22 +106,22 @@ import { VoteFeedback } from '@kelet-ai/feedback-ui';
106
106
  Capture user behavior automatically by using a drop-in replacement for useState:
107
107
 
108
108
  ```tsx
109
- import { useFeedbackState } from '@kelet-ai/feedback-ui';
109
+ import { useFeedbackState } from "@kelet-ai/feedback-ui"
110
110
 
111
111
  function ContentEditor() {
112
112
  // Drop-in useState replacement that tracks changes
113
113
  const [content, setContent] = useFeedbackState(
114
- 'Start writing...',
115
- 'content-editor'
116
- );
114
+ "Start writing...",
115
+ "content-editor"
116
+ )
117
117
 
118
118
  return (
119
119
  <textarea
120
120
  value={content}
121
- onChange={e => setContent(e.target.value)}
121
+ onChange={(e) => setContent(e.target.value)}
122
122
  placeholder="Edit this content..."
123
123
  />
124
- );
124
+ )
125
125
  // 🎯 Automatically sends feedback when user stops editing!
126
126
  }
127
127
  ```
@@ -131,17 +131,17 @@ function ContentEditor() {
131
131
  For advanced state management with automatic trigger tracking, by using a drop-in replacement for useReducer:
132
132
 
133
133
  ```tsx
134
- import { useFeedbackReducer } from '@kelet-ai/feedback-ui';
134
+ import { useFeedbackReducer } from "@kelet-ai/feedback-ui"
135
135
 
136
136
  function TodoApp() {
137
- const [todos, dispatch] = useFeedbackReducer(todoReducer, [], 'todo-app');
137
+ const [todos, dispatch] = useFeedbackReducer(todoReducer, [], "todo-app")
138
138
 
139
139
  return (
140
- <button onClick={() => dispatch({ type: 'ADD_TODO', text: 'New task' })}>
140
+ <button onClick={() => dispatch({ type: "ADD_TODO", text: "New task" })}>
141
141
  Add Todo
142
142
  </button>
143
143
  // 🎯 Automatically sends feedback with trigger_name: 'ADD_TODO'
144
- );
144
+ )
145
145
  }
146
146
  ```
147
147
 
@@ -198,15 +198,15 @@ Controls how feedback is collected and what data is captured:
198
198
  ```tsx
199
199
  // Implicit feedback - tracks changes automatically
200
200
  const [content, setContent] = useFeedbackState(
201
- 'Initial content',
202
- 'content-editor'
203
- );
201
+ "Initial content",
202
+ "content-editor"
203
+ )
204
204
  // Sends feedback when user stops editing
205
205
 
206
206
  // Loading pattern - no noise generated
207
- const [user, setUser] = useFeedbackState(null, 'user-data');
208
- setUser(userData); // ❌ No feedback sent (ignoreInitialNullish: true)
209
- setUser(updatedUser); // ✅ Feedback sent for real changes
207
+ const [user, setUser] = useFeedbackState(null, "user-data")
208
+ setUser(userData) // ❌ No feedback sent (ignoreInitialNullish: true)
209
+ setUser(updatedUser) // ✅ Feedback sent for real changes
210
210
  ```
211
211
 
212
212
  ### **🏷️ Trigger Names**
@@ -224,16 +224,16 @@ Categorization system for grouping and analyzing feedback:
224
224
 
225
225
  ```tsx
226
226
  // Content creation triggers
227
- 'user_typing' | 'ai_generation' | 'spell_check' | 'auto_format';
227
+ ;"user_typing" | "ai_generation" | "spell_check" | "auto_format"
228
228
 
229
229
  // User interaction triggers
230
- 'manual_edit' | 'voice_input' | 'copy_paste' | 'drag_drop';
230
+ ;"manual_edit" | "voice_input" | "copy_paste" | "drag_drop"
231
231
 
232
232
  // Workflow triggers
233
- 'draft' | 'review' | 'approval' | 'publication';
233
+ ;"draft" | "review" | "approval" | "publication"
234
234
 
235
235
  // AI interaction triggers
236
- 'ai_completion' | 'ai_correction' | 'prompt_result';
236
+ ;"ai_completion" | "ai_correction" | "prompt_result"
237
237
  ```
238
238
 
239
239
  #### **Dynamic Trigger Names**
@@ -241,14 +241,14 @@ Categorization system for grouping and analyzing feedback:
241
241
  ```tsx
242
242
  const [document, setDocument] = useFeedbackState(
243
243
  initialDoc,
244
- 'document-editor',
245
- { default_trigger_name: 'user_edit' }
246
- );
244
+ "document-editor",
245
+ { default_trigger_name: "user_edit" }
246
+ )
247
247
 
248
248
  // Different triggers for different actions
249
- setDocument(aiGeneratedContent, 'ai_generation');
250
- setDocument(userEditedContent, 'manual_refinement');
251
- setDocument(spellCheckedContent, 'spell_check');
249
+ setDocument(aiGeneratedContent, "ai_generation")
250
+ setDocument(userEditedContent, "manual_refinement")
251
+ setDocument(spellCheckedContent, "spell_check")
252
252
  ```
253
253
 
254
254
  ### **🔄 State Change Tracking**
@@ -260,9 +260,9 @@ For implicit feedback, understanding how state changes are processed:
260
260
  ```tsx
261
261
  // User types: "Hello" → "Hello World" → "Hello World!"
262
262
  // Only sends ONE feedback after user stops typing
263
- const [text, setText] = useFeedbackState('', 'editor', {
263
+ const [text, setText] = useFeedbackState("", "editor", {
264
264
  debounceMs: 3000, // Wait 3s after last change
265
- });
265
+ })
266
266
  ```
267
267
 
268
268
  #### **Diff Calculation**
@@ -281,14 +281,14 @@ Automatic classification of changes:
281
281
 
282
282
  ```tsx
283
283
  // Smart vote logic based on change magnitude
284
- const [data, setData] = useFeedbackState(initial, 'tracker', {
284
+ const [data, setData] = useFeedbackState(initial, "tracker", {
285
285
  vote: (before, after, diffPercentage) => {
286
286
  // Small changes = refinement (positive)
287
- if (diffPercentage <= 0.5) return 'upvote';
287
+ if (diffPercentage <= 0.5) return "upvote"
288
288
  // Large changes = major revision (might indicate issues)
289
- return 'downvote';
289
+ return "downvote"
290
290
  },
291
- });
291
+ })
292
292
  ```
293
293
 
294
294
  ### **🎯 Best Practices Summary**
@@ -330,7 +330,7 @@ Main container component that manages feedback state.
330
330
  session_id="unique-id" // Required: Unique tracking ID
331
331
  onFeedback={handleFeedback} // Required: Callback function
332
332
  trigger_name="user_feedback" // Optional: Categorization
333
- extra_metadata={{ page: 'home' }} // Optional: Additional data
333
+ extra_metadata={{ page: "home" }} // Optional: Additional data
334
334
  >
335
335
  {/* Child components */}
336
336
  </VoteFeedback.Root>
@@ -368,39 +368,39 @@ A **drop-in replacement for React's useState** that automatically tracks state c
368
368
  #### **Basic Usage**
369
369
 
370
370
  ```tsx
371
- const [count, setCount] = useFeedbackState(0, 'counter-widget');
371
+ const [count, setCount] = useFeedbackState(0, "counter-widget")
372
372
  ```
373
373
 
374
374
  #### **Advanced Configuration**
375
375
 
376
376
  ```tsx
377
377
  const [profile, setProfile] = useFeedbackState(
378
- { name: '', email: '' },
379
- state => `profile-${state.email}`, // Dynamic session_id
378
+ { name: "", email: "" },
379
+ (state) => `profile-${state.email}`, // Dynamic session_id
380
380
  {
381
381
  debounceMs: 2000, // Wait time before sending feedback
382
- diffType: 'object', // Format: 'git' | 'object' | 'json'
383
- metadata: { component: 'UserProfile' },
384
- vote: 'upvote', // Static vote or custom function
382
+ diffType: "object", // Format: 'git' | 'object' | 'json'
383
+ metadata: { component: "UserProfile" },
384
+ vote: "upvote", // Static vote or custom function
385
385
  }
386
- );
386
+ )
387
387
  ```
388
388
 
389
389
  #### **Trigger Names for Categorization**
390
390
 
391
391
  ```tsx
392
392
  const [content, setContent] = useFeedbackState(
393
- 'Initial content',
394
- 'content-editor',
395
- { default_trigger_name: 'manual_edit' }
396
- );
393
+ "Initial content",
394
+ "content-editor",
395
+ { default_trigger_name: "manual_edit" }
396
+ )
397
397
 
398
398
  // Uses default trigger
399
- setContent('User typed this');
399
+ setContent("User typed this")
400
400
 
401
401
  // Override with specific trigger
402
- setContent('AI generated this', 'ai_assistance');
403
- setContent('Spell checker fixed this', 'spell_check');
402
+ setContent("AI generated this", "ai_assistance")
403
+ setContent("Spell checker fixed this", "spell_check")
404
404
  ```
405
405
 
406
406
  ### **useFeedbackReducer Hook**
@@ -411,12 +411,12 @@ A **drop-in replacement for React's useReducer** with automatic trigger name ext
411
411
  const [state, dispatch] = useFeedbackReducer(
412
412
  counterReducer,
413
413
  { count: 0 },
414
- 'counter-widget'
415
- );
414
+ "counter-widget"
415
+ )
416
416
 
417
- dispatch({ type: 'increment' }); // trigger_name: 'increment'
418
- dispatch({ type: 'reset' }); // trigger_name: 'reset'
419
- dispatch({ type: 'custom' }, 'override'); // Custom trigger name
417
+ dispatch({ type: "increment" }) // trigger_name: 'increment'
418
+ dispatch({ type: "reset" }) // trigger_name: 'reset'
419
+ dispatch({ type: "custom" }, "override") // Custom trigger name
420
420
  ```
421
421
 
422
422
  ---
@@ -426,7 +426,7 @@ dispatch({ type: 'custom' }, 'override'); // Custom trigger name
426
426
  ### **Basic Voting Interface**
427
427
 
428
428
  ```tsx
429
- <VoteFeedback.Root onFeedback={feedback => console.log(feedback)}>
429
+ <VoteFeedback.Root onFeedback={(feedback) => console.log(feedback)}>
430
430
  <VoteFeedback.UpvoteButton>👍</VoteFeedback.UpvoteButton>
431
431
  <VoteFeedback.DownvoteButton>👎</VoteFeedback.DownvoteButton>
432
432
  </VoteFeedback.Root>
@@ -470,7 +470,7 @@ dispatch({ type: 'custom' }, 'override'); // Custom trigger name
470
470
  onFeedback={handleFeedback}
471
471
  trigger_name="ai_evaluation"
472
472
  extra_metadata={{
473
- model: 'gpt-4',
473
+ model: "gpt-4",
474
474
  prompt_length: 150,
475
475
  response_time: 1200,
476
476
  }}
@@ -492,14 +492,14 @@ dispatch({ type: 'custom' }, 'override'); // Custom trigger name
492
492
 
493
493
  ```typescript
494
494
  interface FeedbackData {
495
- session_id: string; // Unique tracking ID
496
- vote: 'upvote' | 'downvote'; // User's vote
497
- explanation?: string; // Optional user comment
498
- extra_metadata?: Record<string, any>; // Additional context data
499
- source?: 'IMPLICIT' | 'EXPLICIT'; // How feedback was collected
500
- correction?: string; // For implicit feedback diffs
501
- selection?: string; // Selected text context
502
- trigger_name?: string; // Categorization tag
495
+ session_id: string // Unique tracking ID
496
+ vote: "upvote" | "downvote" // User's vote
497
+ explanation?: string // Optional user comment
498
+ extra_metadata?: Record<string, any> // Additional context data
499
+ source?: "IMPLICIT" | "EXPLICIT" // How feedback was collected
500
+ correction?: string // For implicit feedback diffs
501
+ selection?: string // Selected text context
502
+ trigger_name?: string // Categorization tag
503
503
  }
504
504
  ```
505
505
 
@@ -615,9 +615,9 @@ bun run checks # Run all quality checks (lint, format, typecheck, tests)
615
615
 
616
616
  ```tsx
617
617
  // ✅ Ensure debounce time has passed(the time, not the configuration! :P) and state actually changed
618
- const [value, setValue] = useFeedbackState('initial', 'test', {
618
+ const [value, setValue] = useFeedbackState("initial", "test", {
619
619
  debounceMs: 1000, // Wait 1 second after last change
620
- });
620
+ })
621
621
  ```
622
622
 
623
623
  #### **Q: Styling not working**
@@ -1,6 +1,6 @@
1
1
  import { DownvoteButtonProps, PopoverProps, SubmitButtonProps, TextareaProps, UpvoteButtonProps, VoteFeedbackRootProps } from '../types';
2
2
  export declare const VoteFeedback: {
3
- Root: ({ children, onFeedback, defaultText, session_id: sessionIdProp, extra_metadata, trigger_name, }: VoteFeedbackRootProps) => import("react/jsx-runtime").JSX.Element;
3
+ Root: ({ children, onFeedback, defaultText, session_id: sessionIdProp, metadata, trigger_name: triggerProp, trace_id, }: VoteFeedbackRootProps) => import("react/jsx-runtime").JSX.Element;
4
4
  UpvoteButton: ({ asChild, children, onClick, ...props }: UpvoteButtonProps) => import("react/jsx-runtime").JSX.Element;
5
5
  DownvoteButton: ({ asChild, children, onClick, ...props }: DownvoteButtonProps) => string | number | bigint | true | Iterable<import('react').ReactNode> | Promise<string | number | bigint | boolean | import('react').ReactPortal | import('react').ReactElement<unknown, string | import('react').JSXElementConstructor<any>> | Iterable<import('react').ReactNode> | null | undefined> | import("react/jsx-runtime").JSX.Element;
6
6
  Popover: ({ asChild, children, ...props }: PopoverProps) => import("react/jsx-runtime").JSX.Element | null;