ui-sniper 3.0.10 → 3.1.1

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.mts CHANGED
@@ -1,6 +1,34 @@
1
1
  import * as react from 'react';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
 
4
+ interface PIIRedactionConfig {
5
+ /**
6
+ * Whether PII redaction is enabled.
7
+ * When using the boolean shorthand `redactPII={true}`, all defaults apply.
8
+ */
9
+ enabled: boolean;
10
+ /**
11
+ * Additional CSS selectors whose matched elements will be visually blurred.
12
+ * Built-in selectors are always included when `enabled` is true:
13
+ * `.patient-data`, `[data-pii]`, `[data-phi]`, `[data-sensitive]`
14
+ */
15
+ selectors?: string[];
16
+ /**
17
+ * Enable regex-based pattern scanning on text nodes.
18
+ * Matches: email addresses, phone numbers, US SSNs, credit card numbers.
19
+ * Matched text nodes are wrapped in a blur span during capture.
20
+ * Default: true
21
+ */
22
+ patterns?: boolean;
23
+ /**
24
+ * Also redact matched text from annotation string fields
25
+ * (comment, selectedText, nearbyText, fullPath).
26
+ * Replaced with `[REDACTED]` in markdown output.
27
+ * Default: true
28
+ */
29
+ redactOutput?: boolean;
30
+ }
31
+
4
32
  type Annotation = {
5
33
  id: string;
6
34
  x: number;
@@ -81,6 +109,19 @@ type ThreadMessage = {
81
109
  content: string;
82
110
  timestamp: number;
83
111
  };
112
+ /** Fired by the `onTelemetry` callback on key user actions. */
113
+ type TelemetryEvent = {
114
+ /** What triggered the telemetry event */
115
+ trigger: "copy" | "submit" | "annotate" | "clear";
116
+ /** All annotations at the time of the event */
117
+ annotations: Annotation[];
118
+ /** The markdown output string (populated for copy/submit) */
119
+ output?: string;
120
+ /** Unix timestamp (ms) */
121
+ timestamp: number;
122
+ /** Current page URL */
123
+ pageUrl: string;
124
+ };
84
125
 
85
126
  type DemoAnnotation = {
86
127
  selector: string;
@@ -115,10 +156,110 @@ type PageFeedbackToolbarCSSProps = {
115
156
  webhookUrl?: string;
116
157
  /** Custom class name applied to the toolbar container. Use to adjust positioning or z-index. */
117
158
  className?: string;
159
+ /**
160
+ * When true, hides the default floating trigger button/badge.
161
+ * Use with `useUISniper()` hook to build your own custom trigger UI.
162
+ * @example
163
+ * ```tsx
164
+ * <UISniper headless />
165
+ * // Anywhere in your tree:
166
+ * const { open } = useUISniper();
167
+ * ```
168
+ */
169
+ headless?: boolean;
170
+ /** Fired when the toolbar is activated (expanded). */
171
+ onActivate?: () => void;
172
+ /** Fired when the toolbar is deactivated (collapsed). */
173
+ onDeactivate?: () => void;
174
+ /**
175
+ * Called on key user actions (copy, submit, annotate, clear).
176
+ * Provides a structured event payload so you can capture telemetry
177
+ * without monkey-patching globals.
178
+ */
179
+ onTelemetry?: (event: TelemetryEvent) => void;
180
+ /**
181
+ * When true, failed webhook requests are queued in localStorage and
182
+ * automatically retried when the browser comes back online.
183
+ * Default: false
184
+ */
185
+ offlineQueue?: boolean;
186
+ /**
187
+ * localStorage key for the offline queue.
188
+ * Default: "ui-sniper-offline-queue"
189
+ */
190
+ offlineQueueKey?: string;
191
+ /**
192
+ * Enable PII/PHI redaction before screenshots are captured and in
193
+ * annotation text output.
194
+ *
195
+ * Pass `true` for defaults (blurs `.patient-data`, `[data-pii]`,
196
+ * `[data-phi]`, and pattern-matches emails/phones/SSNs).
197
+ * Or pass a `PIIRedactionConfig` object for fine-grained control.
198
+ *
199
+ * @example
200
+ * ```tsx
201
+ * <UISniper redactPII />
202
+ * <UISniper redactPII={{ selectors: ['.mrn', '.dob'], patterns: true }} />
203
+ * ```
204
+ */
205
+ redactPII?: boolean | PIIRedactionConfig;
206
+ /**
207
+ * Suppresses UI Sniper's own `[UI Sniper]`-prefixed console warnings
208
+ * in development mode. Also adds `suppressHydrationWarning` to the
209
+ * portal wrapper to silence Next.js hydration mismatch noise.
210
+ * Has no effect in production.
211
+ */
212
+ suppressDevWarnings?: boolean;
118
213
  };
119
214
  /** Alias for PageFeedbackToolbarCSSProps */
120
215
  type UISniperProps = PageFeedbackToolbarCSSProps;
121
- declare function PageFeedbackToolbarCSS({ demoAnnotations, demoDelay, enableDemoMode, onAnnotationAdd, onAnnotationDelete, onAnnotationUpdate, onAnnotationsClear, onCopy, onSubmit, copyToClipboard, endpoint, sessionId: initialSessionId, onSessionCreated, webhookUrl, className: userClassName, }?: PageFeedbackToolbarCSSProps): react.ReactPortal | null;
216
+ declare function PageFeedbackToolbarCSS({ demoAnnotations, demoDelay, enableDemoMode, onAnnotationAdd, onAnnotationDelete, onAnnotationUpdate, onAnnotationsClear, onCopy, onSubmit, copyToClipboard, endpoint, sessionId: initialSessionId, onSessionCreated, webhookUrl, className: userClassName, headless, onActivate, onDeactivate, onTelemetry, offlineQueue, offlineQueueKey, redactPII, suppressDevWarnings, }?: PageFeedbackToolbarCSSProps): react.ReactPortal | null;
217
+
218
+ interface UISniperContextValue {
219
+ /** Whether the toolbar is currently expanded/active */
220
+ isActive: boolean;
221
+ /** Open (activate) the toolbar */
222
+ open: () => void;
223
+ /** Close (deactivate) the toolbar */
224
+ close: () => void;
225
+ /** Toggle toolbar open/closed */
226
+ toggle: () => void;
227
+ }
228
+ declare const UISniperContext: react.Context<UISniperContextValue>;
229
+ /**
230
+ * Access UISniper's programmatic API.
231
+ *
232
+ * Must be rendered inside the same React tree that contains a `<UISniper />`
233
+ * component. Combine with `headless` prop on `<UISniper />` to hide the
234
+ * default floating button and use your own custom trigger.
235
+ *
236
+ * @example
237
+ * ```tsx
238
+ * // In your layout (e.g. app/layout.tsx):
239
+ * <UISniper headless />
240
+ *
241
+ * // In any child component:
242
+ * const { open, isActive } = useUISniper();
243
+ * return <button onClick={open}>Give Feedback</button>;
244
+ * ```
245
+ */
246
+ declare function useUISniper(): UISniperContextValue;
247
+
248
+ interface ReviewPanelProps {
249
+ /** Annotations to review */
250
+ annotations: Annotation[];
251
+ /** Called when the panel should close */
252
+ onClose: () => void;
253
+ /** Called when user clicks "Jump to" on an annotation */
254
+ onJumpTo?: (annotation: Annotation) => void;
255
+ /** Called when user deletes an annotation from the panel */
256
+ onDelete?: (annotation: Annotation) => void;
257
+ /** Whether the panel is in dark or light mode */
258
+ isDarkMode?: boolean;
259
+ /** Called when user clicks copy on an annotation */
260
+ onCopy?: (annotation: Annotation) => void;
261
+ }
262
+ declare function ReviewPanel({ annotations, onClose, onJumpTo, onDelete, onCopy, }: ReviewPanelProps): react_jsx_runtime.JSX.Element;
122
263
 
123
264
  interface AnnotationPopupCSSProps {
124
265
  /** Element name to display in header */
@@ -326,4 +467,4 @@ declare function getStorageKey(pathname: string): string;
326
467
  declare function loadAnnotations<T = Annotation>(pathname: string): T[];
327
468
  declare function saveAnnotations<T = Annotation>(pathname: string, annotations: T[]): void;
328
469
 
329
- export { AnimatedBunny, type Annotation, AnnotationPopupCSS, type AnnotationPopupCSSHandle, type AnnotationPopupCSSProps, type DemoAnnotation, IconChatEllipsis, IconCheck, IconCheckSmall, IconCheckSmallAnimated, IconCheckmark, IconCheckmarkCircle, IconCheckmarkLarge, IconChevronLeft, IconChevronRight, IconClose, IconCopyAlt, IconCopyAnimated, IconEdit, IconEye, IconEyeAlt, IconEyeAnimated, IconEyeClosed, IconEyeMinus, IconGear, IconHelp, IconLayout, IconListSparkle, IconMoon, IconPause, IconPauseAlt, IconPausePlayAnimated, IconPlayAlt, IconPlus, IconSendAnimated, IconSendArrow, IconSun, IconTarget, IconTrash, IconTrashAlt, IconXmark, IconXmarkLarge, PageFeedbackToolbarCSS, PageFeedbackToolbarCSS as UISniper, type UISniperProps, closestCrossingShadow, getElementClasses, getElementPath, getNearbyText, getShadowHost, getStorageKey, identifyAnimationElement, identifyElement, isInShadowDOM, loadAnnotations, saveAnnotations };
470
+ export { AnimatedBunny, type Annotation, AnnotationPopupCSS, type AnnotationPopupCSSHandle, type AnnotationPopupCSSProps, type DemoAnnotation, IconChatEllipsis, IconCheck, IconCheckSmall, IconCheckSmallAnimated, IconCheckmark, IconCheckmarkCircle, IconCheckmarkLarge, IconChevronLeft, IconChevronRight, IconClose, IconCopyAlt, IconCopyAnimated, IconEdit, IconEye, IconEyeAlt, IconEyeAnimated, IconEyeClosed, IconEyeMinus, IconGear, IconHelp, IconLayout, IconListSparkle, IconMoon, IconPause, IconPauseAlt, IconPausePlayAnimated, IconPlayAlt, IconPlus, IconSendAnimated, IconSendArrow, IconSun, IconTarget, IconTrash, IconTrashAlt, IconXmark, IconXmarkLarge, type PIIRedactionConfig, PageFeedbackToolbarCSS, ReviewPanel, type ReviewPanelProps, type TelemetryEvent, PageFeedbackToolbarCSS as UISniper, UISniperContext, type UISniperContextValue, type UISniperProps, closestCrossingShadow, getElementClasses, getElementPath, getNearbyText, getShadowHost, getStorageKey, identifyAnimationElement, identifyElement, isInShadowDOM, loadAnnotations, saveAnnotations, useUISniper };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,34 @@
1
1
  import * as react from 'react';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
 
4
+ interface PIIRedactionConfig {
5
+ /**
6
+ * Whether PII redaction is enabled.
7
+ * When using the boolean shorthand `redactPII={true}`, all defaults apply.
8
+ */
9
+ enabled: boolean;
10
+ /**
11
+ * Additional CSS selectors whose matched elements will be visually blurred.
12
+ * Built-in selectors are always included when `enabled` is true:
13
+ * `.patient-data`, `[data-pii]`, `[data-phi]`, `[data-sensitive]`
14
+ */
15
+ selectors?: string[];
16
+ /**
17
+ * Enable regex-based pattern scanning on text nodes.
18
+ * Matches: email addresses, phone numbers, US SSNs, credit card numbers.
19
+ * Matched text nodes are wrapped in a blur span during capture.
20
+ * Default: true
21
+ */
22
+ patterns?: boolean;
23
+ /**
24
+ * Also redact matched text from annotation string fields
25
+ * (comment, selectedText, nearbyText, fullPath).
26
+ * Replaced with `[REDACTED]` in markdown output.
27
+ * Default: true
28
+ */
29
+ redactOutput?: boolean;
30
+ }
31
+
4
32
  type Annotation = {
5
33
  id: string;
6
34
  x: number;
@@ -81,6 +109,19 @@ type ThreadMessage = {
81
109
  content: string;
82
110
  timestamp: number;
83
111
  };
112
+ /** Fired by the `onTelemetry` callback on key user actions. */
113
+ type TelemetryEvent = {
114
+ /** What triggered the telemetry event */
115
+ trigger: "copy" | "submit" | "annotate" | "clear";
116
+ /** All annotations at the time of the event */
117
+ annotations: Annotation[];
118
+ /** The markdown output string (populated for copy/submit) */
119
+ output?: string;
120
+ /** Unix timestamp (ms) */
121
+ timestamp: number;
122
+ /** Current page URL */
123
+ pageUrl: string;
124
+ };
84
125
 
85
126
  type DemoAnnotation = {
86
127
  selector: string;
@@ -115,10 +156,110 @@ type PageFeedbackToolbarCSSProps = {
115
156
  webhookUrl?: string;
116
157
  /** Custom class name applied to the toolbar container. Use to adjust positioning or z-index. */
117
158
  className?: string;
159
+ /**
160
+ * When true, hides the default floating trigger button/badge.
161
+ * Use with `useUISniper()` hook to build your own custom trigger UI.
162
+ * @example
163
+ * ```tsx
164
+ * <UISniper headless />
165
+ * // Anywhere in your tree:
166
+ * const { open } = useUISniper();
167
+ * ```
168
+ */
169
+ headless?: boolean;
170
+ /** Fired when the toolbar is activated (expanded). */
171
+ onActivate?: () => void;
172
+ /** Fired when the toolbar is deactivated (collapsed). */
173
+ onDeactivate?: () => void;
174
+ /**
175
+ * Called on key user actions (copy, submit, annotate, clear).
176
+ * Provides a structured event payload so you can capture telemetry
177
+ * without monkey-patching globals.
178
+ */
179
+ onTelemetry?: (event: TelemetryEvent) => void;
180
+ /**
181
+ * When true, failed webhook requests are queued in localStorage and
182
+ * automatically retried when the browser comes back online.
183
+ * Default: false
184
+ */
185
+ offlineQueue?: boolean;
186
+ /**
187
+ * localStorage key for the offline queue.
188
+ * Default: "ui-sniper-offline-queue"
189
+ */
190
+ offlineQueueKey?: string;
191
+ /**
192
+ * Enable PII/PHI redaction before screenshots are captured and in
193
+ * annotation text output.
194
+ *
195
+ * Pass `true` for defaults (blurs `.patient-data`, `[data-pii]`,
196
+ * `[data-phi]`, and pattern-matches emails/phones/SSNs).
197
+ * Or pass a `PIIRedactionConfig` object for fine-grained control.
198
+ *
199
+ * @example
200
+ * ```tsx
201
+ * <UISniper redactPII />
202
+ * <UISniper redactPII={{ selectors: ['.mrn', '.dob'], patterns: true }} />
203
+ * ```
204
+ */
205
+ redactPII?: boolean | PIIRedactionConfig;
206
+ /**
207
+ * Suppresses UI Sniper's own `[UI Sniper]`-prefixed console warnings
208
+ * in development mode. Also adds `suppressHydrationWarning` to the
209
+ * portal wrapper to silence Next.js hydration mismatch noise.
210
+ * Has no effect in production.
211
+ */
212
+ suppressDevWarnings?: boolean;
118
213
  };
119
214
  /** Alias for PageFeedbackToolbarCSSProps */
120
215
  type UISniperProps = PageFeedbackToolbarCSSProps;
121
- declare function PageFeedbackToolbarCSS({ demoAnnotations, demoDelay, enableDemoMode, onAnnotationAdd, onAnnotationDelete, onAnnotationUpdate, onAnnotationsClear, onCopy, onSubmit, copyToClipboard, endpoint, sessionId: initialSessionId, onSessionCreated, webhookUrl, className: userClassName, }?: PageFeedbackToolbarCSSProps): react.ReactPortal | null;
216
+ declare function PageFeedbackToolbarCSS({ demoAnnotations, demoDelay, enableDemoMode, onAnnotationAdd, onAnnotationDelete, onAnnotationUpdate, onAnnotationsClear, onCopy, onSubmit, copyToClipboard, endpoint, sessionId: initialSessionId, onSessionCreated, webhookUrl, className: userClassName, headless, onActivate, onDeactivate, onTelemetry, offlineQueue, offlineQueueKey, redactPII, suppressDevWarnings, }?: PageFeedbackToolbarCSSProps): react.ReactPortal | null;
217
+
218
+ interface UISniperContextValue {
219
+ /** Whether the toolbar is currently expanded/active */
220
+ isActive: boolean;
221
+ /** Open (activate) the toolbar */
222
+ open: () => void;
223
+ /** Close (deactivate) the toolbar */
224
+ close: () => void;
225
+ /** Toggle toolbar open/closed */
226
+ toggle: () => void;
227
+ }
228
+ declare const UISniperContext: react.Context<UISniperContextValue>;
229
+ /**
230
+ * Access UISniper's programmatic API.
231
+ *
232
+ * Must be rendered inside the same React tree that contains a `<UISniper />`
233
+ * component. Combine with `headless` prop on `<UISniper />` to hide the
234
+ * default floating button and use your own custom trigger.
235
+ *
236
+ * @example
237
+ * ```tsx
238
+ * // In your layout (e.g. app/layout.tsx):
239
+ * <UISniper headless />
240
+ *
241
+ * // In any child component:
242
+ * const { open, isActive } = useUISniper();
243
+ * return <button onClick={open}>Give Feedback</button>;
244
+ * ```
245
+ */
246
+ declare function useUISniper(): UISniperContextValue;
247
+
248
+ interface ReviewPanelProps {
249
+ /** Annotations to review */
250
+ annotations: Annotation[];
251
+ /** Called when the panel should close */
252
+ onClose: () => void;
253
+ /** Called when user clicks "Jump to" on an annotation */
254
+ onJumpTo?: (annotation: Annotation) => void;
255
+ /** Called when user deletes an annotation from the panel */
256
+ onDelete?: (annotation: Annotation) => void;
257
+ /** Whether the panel is in dark or light mode */
258
+ isDarkMode?: boolean;
259
+ /** Called when user clicks copy on an annotation */
260
+ onCopy?: (annotation: Annotation) => void;
261
+ }
262
+ declare function ReviewPanel({ annotations, onClose, onJumpTo, onDelete, onCopy, }: ReviewPanelProps): react_jsx_runtime.JSX.Element;
122
263
 
123
264
  interface AnnotationPopupCSSProps {
124
265
  /** Element name to display in header */
@@ -326,4 +467,4 @@ declare function getStorageKey(pathname: string): string;
326
467
  declare function loadAnnotations<T = Annotation>(pathname: string): T[];
327
468
  declare function saveAnnotations<T = Annotation>(pathname: string, annotations: T[]): void;
328
469
 
329
- export { AnimatedBunny, type Annotation, AnnotationPopupCSS, type AnnotationPopupCSSHandle, type AnnotationPopupCSSProps, type DemoAnnotation, IconChatEllipsis, IconCheck, IconCheckSmall, IconCheckSmallAnimated, IconCheckmark, IconCheckmarkCircle, IconCheckmarkLarge, IconChevronLeft, IconChevronRight, IconClose, IconCopyAlt, IconCopyAnimated, IconEdit, IconEye, IconEyeAlt, IconEyeAnimated, IconEyeClosed, IconEyeMinus, IconGear, IconHelp, IconLayout, IconListSparkle, IconMoon, IconPause, IconPauseAlt, IconPausePlayAnimated, IconPlayAlt, IconPlus, IconSendAnimated, IconSendArrow, IconSun, IconTarget, IconTrash, IconTrashAlt, IconXmark, IconXmarkLarge, PageFeedbackToolbarCSS, PageFeedbackToolbarCSS as UISniper, type UISniperProps, closestCrossingShadow, getElementClasses, getElementPath, getNearbyText, getShadowHost, getStorageKey, identifyAnimationElement, identifyElement, isInShadowDOM, loadAnnotations, saveAnnotations };
470
+ export { AnimatedBunny, type Annotation, AnnotationPopupCSS, type AnnotationPopupCSSHandle, type AnnotationPopupCSSProps, type DemoAnnotation, IconChatEllipsis, IconCheck, IconCheckSmall, IconCheckSmallAnimated, IconCheckmark, IconCheckmarkCircle, IconCheckmarkLarge, IconChevronLeft, IconChevronRight, IconClose, IconCopyAlt, IconCopyAnimated, IconEdit, IconEye, IconEyeAlt, IconEyeAnimated, IconEyeClosed, IconEyeMinus, IconGear, IconHelp, IconLayout, IconListSparkle, IconMoon, IconPause, IconPauseAlt, IconPausePlayAnimated, IconPlayAlt, IconPlus, IconSendAnimated, IconSendArrow, IconSun, IconTarget, IconTrash, IconTrashAlt, IconXmark, IconXmarkLarge, type PIIRedactionConfig, PageFeedbackToolbarCSS, ReviewPanel, type ReviewPanelProps, type TelemetryEvent, PageFeedbackToolbarCSS as UISniper, UISniperContext, type UISniperContextValue, type UISniperProps, closestCrossingShadow, getElementClasses, getElementPath, getNearbyText, getShadowHost, getStorageKey, identifyAnimationElement, identifyElement, isInShadowDOM, loadAnnotations, saveAnnotations, useUISniper };