featuredrop 1.1.0 → 1.3.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.
Files changed (84) hide show
  1. package/README.md +547 -4
  2. package/dist/admin.cjs +212 -0
  3. package/dist/admin.cjs.map +1 -0
  4. package/dist/admin.d.cts +176 -0
  5. package/dist/admin.d.ts +176 -0
  6. package/dist/admin.js +207 -0
  7. package/dist/admin.js.map +1 -0
  8. package/dist/angular.cjs +296 -0
  9. package/dist/angular.cjs.map +1 -0
  10. package/dist/angular.d.cts +233 -0
  11. package/dist/angular.d.ts +233 -0
  12. package/dist/angular.js +293 -0
  13. package/dist/angular.js.map +1 -0
  14. package/dist/bridges.cjs +401 -0
  15. package/dist/bridges.cjs.map +1 -0
  16. package/dist/bridges.d.cts +194 -0
  17. package/dist/bridges.d.ts +194 -0
  18. package/dist/bridges.js +394 -0
  19. package/dist/bridges.js.map +1 -0
  20. package/dist/ci.cjs +328 -0
  21. package/dist/ci.cjs.map +1 -0
  22. package/dist/ci.d.cts +176 -0
  23. package/dist/ci.d.ts +176 -0
  24. package/dist/ci.js +324 -0
  25. package/dist/ci.js.map +1 -0
  26. package/dist/featuredrop.cjs +1377 -0
  27. package/dist/featuredrop.cjs.map +1 -0
  28. package/dist/flags.cjs +51 -0
  29. package/dist/flags.cjs.map +1 -0
  30. package/dist/flags.d.cts +48 -0
  31. package/dist/flags.d.ts +48 -0
  32. package/dist/flags.js +47 -0
  33. package/dist/flags.js.map +1 -0
  34. package/dist/index.cjs +4734 -70
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +1516 -9
  37. package/dist/index.d.ts +1516 -9
  38. package/dist/index.js +4660 -71
  39. package/dist/index.js.map +1 -1
  40. package/dist/preact.cjs +7790 -0
  41. package/dist/preact.cjs.map +1 -0
  42. package/dist/preact.d.cts +1213 -0
  43. package/dist/preact.d.ts +1213 -0
  44. package/dist/preact.js +7760 -0
  45. package/dist/preact.js.map +1 -0
  46. package/dist/react.cjs +6678 -159
  47. package/dist/react.cjs.map +1 -1
  48. package/dist/react.d.cts +852 -112
  49. package/dist/react.d.ts +852 -112
  50. package/dist/react.js +6657 -156
  51. package/dist/react.js.map +1 -1
  52. package/dist/schema.cjs +292 -0
  53. package/dist/schema.cjs.map +1 -0
  54. package/dist/schema.d.cts +345 -0
  55. package/dist/schema.d.ts +345 -0
  56. package/dist/schema.js +286 -0
  57. package/dist/schema.js.map +1 -0
  58. package/dist/solid.cjs +383 -0
  59. package/dist/solid.cjs.map +1 -0
  60. package/dist/solid.d.cts +246 -0
  61. package/dist/solid.d.ts +246 -0
  62. package/dist/solid.js +376 -0
  63. package/dist/solid.js.map +1 -0
  64. package/dist/svelte.cjs +339 -0
  65. package/dist/svelte.cjs.map +1 -0
  66. package/dist/svelte.js +334 -0
  67. package/dist/svelte.js.map +1 -0
  68. package/dist/testing.cjs +1543 -0
  69. package/dist/testing.cjs.map +1 -0
  70. package/dist/testing.d.cts +361 -0
  71. package/dist/testing.d.ts +361 -0
  72. package/dist/testing.js +1536 -0
  73. package/dist/testing.js.map +1 -0
  74. package/dist/vue.cjs +1094 -0
  75. package/dist/vue.cjs.map +1 -0
  76. package/dist/vue.js +1082 -0
  77. package/dist/vue.js.map +1 -0
  78. package/dist/web-components.cjs +493 -0
  79. package/dist/web-components.cjs.map +1 -0
  80. package/dist/web-components.d.cts +215 -0
  81. package/dist/web-components.d.ts +215 -0
  82. package/dist/web-components.js +487 -0
  83. package/dist/web-components.js.map +1 -0
  84. package/package.json +184 -3
@@ -0,0 +1,1213 @@
1
+ import * as react from 'react';
2
+ import { ReactNode, CSSProperties, RefObject } from 'react';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+
5
+ /** Entry type label — determines default icon/color in UI */
6
+ type FeatureType = "feature" | "improvement" | "fix" | "breaking";
7
+ /** Priority level for announcements */
8
+ type FeaturePriority = "critical" | "normal" | "low";
9
+ /** Motion preset for built-in component transitions */
10
+ type FeatureDropAnimationPreset = "none" | "subtle" | "normal" | "playful";
11
+ /** Call-to-action for a feature entry */
12
+ interface FeatureCTA {
13
+ /** Button/link label */
14
+ label: string;
15
+ /** URL to navigate to */
16
+ url: string;
17
+ }
18
+ /** Variant-level overrides for A/B announcement testing */
19
+ interface FeatureVariant {
20
+ /** Optional variant-specific label override */
21
+ label?: string;
22
+ /** Optional variant-specific description override */
23
+ description?: string;
24
+ /** Optional variant-specific image override */
25
+ image?: string;
26
+ /** Optional variant-specific CTA override */
27
+ cta?: FeatureCTA;
28
+ /** Optional variant-specific metadata overrides */
29
+ meta?: Record<string, unknown>;
30
+ }
31
+ /** Audience targeting rule — determines which user segments see a feature */
32
+ interface AudienceRule {
33
+ /** Plans that should see this feature (e.g. ["pro", "enterprise"]) */
34
+ plan?: string[];
35
+ /** Roles that should see this feature (e.g. ["admin", "editor"]) */
36
+ role?: string[];
37
+ /** Regions that should see this feature (e.g. ["us", "eu"]) */
38
+ region?: string[];
39
+ /** Arbitrary key-value pairs for custom matching logic */
40
+ custom?: Record<string, unknown>;
41
+ }
42
+ /** User context for audience targeting */
43
+ interface UserContext {
44
+ /** Current user's plan (e.g. "pro", "free") */
45
+ plan?: string;
46
+ /** Current user's role (e.g. "admin", "viewer") */
47
+ role?: string;
48
+ /** Current user's region (e.g. "us", "eu") */
49
+ region?: string;
50
+ /** Arbitrary traits for custom matching logic */
51
+ traits?: Record<string, unknown>;
52
+ }
53
+ /** Custom audience matcher function */
54
+ type AudienceMatchFn = (audience: AudienceRule, userContext: UserContext) => boolean;
55
+ /** Feature flag resolver interface for gating announcement visibility */
56
+ interface FeatureFlagBridge {
57
+ isEnabled: (flagKey: string, userContext?: UserContext) => boolean;
58
+ }
59
+ /** Dependency gates for progressive feature discovery */
60
+ interface FeatureDependencies {
61
+ /** Features the user must have seen before this one can surface */
62
+ seen?: string[];
63
+ /** Features the user must have clicked before this one can surface */
64
+ clicked?: string[];
65
+ /** Features the user must have dismissed before this one can surface */
66
+ dismissed?: string[];
67
+ }
68
+ /** Runtime context used by trigger evaluation */
69
+ interface TriggerContext {
70
+ /** Current app route/path */
71
+ path?: string;
72
+ /** Named events observed in this session */
73
+ events?: ReadonlySet<string>;
74
+ /** Named milestone flags reached in this session */
75
+ milestones?: ReadonlySet<string>;
76
+ /** Usage counters keyed by event/pattern name */
77
+ usage?: Record<string, number>;
78
+ /** Session elapsed time in milliseconds */
79
+ elapsedMs?: number;
80
+ /** Scroll completion percentage (0-100) */
81
+ scrollPercent?: number;
82
+ /** Optional additional trigger context */
83
+ metadata?: Record<string, unknown>;
84
+ }
85
+ type FeatureTrigger = {
86
+ type: "page";
87
+ match: string | RegExp;
88
+ } | {
89
+ type: "usage";
90
+ event: string;
91
+ minActions?: number;
92
+ } | {
93
+ type: "time";
94
+ minSeconds: number;
95
+ } | {
96
+ type: "milestone";
97
+ event: string;
98
+ } | {
99
+ type: "frustration";
100
+ pattern: string;
101
+ threshold?: number;
102
+ } | {
103
+ type: "scroll";
104
+ minPercent?: number;
105
+ } | {
106
+ type: "custom";
107
+ evaluate: (context: TriggerContext) => boolean;
108
+ };
109
+ /** A single feature entry in the manifest */
110
+ interface FeatureEntry {
111
+ /** Unique identifier for the feature */
112
+ id: string;
113
+ /** Human-readable label (e.g. "Decision Journal") */
114
+ label: string;
115
+ /** Optional longer description (supports markdown in UI components) */
116
+ description?: string;
117
+ /**
118
+ * Semantic version targeting.
119
+ * If provided as an object, requires `appVersion` to be supplied to the provider/helpers.
120
+ * - introduced: earliest app version that includes this feature
121
+ * - showNewUntil: stop showing "new" once appVersion reaches this
122
+ * - deprecatedAt: hide feature for app versions at or above this (optional safety)
123
+ * - showIn: range string, e.g. ">=2.5.0 <3.0.0"
124
+ */
125
+ version?: string | {
126
+ introduced?: string;
127
+ showNewUntil?: string;
128
+ deprecatedAt?: string;
129
+ showIn?: string;
130
+ };
131
+ /** ISO date when this feature was released */
132
+ releasedAt: string;
133
+ /** ISO date after which the "new" badge should stop showing */
134
+ showNewUntil: string;
135
+ /** Optional key to match navigation items (e.g. "/journal", "settings") */
136
+ sidebarKey?: string;
137
+ /** Optional grouping category (e.g. "ai", "billing", "core") */
138
+ category?: string;
139
+ /** Optional product scope (`"*"`, `"askverdict"`, etc.) for multi-product manifests */
140
+ product?: string;
141
+ /** Optional URL to link to (e.g. docs page, changelog entry) */
142
+ url?: string;
143
+ /** Optional feature flag key; requires a flag bridge to evaluate */
144
+ flagKey?: string;
145
+ /** Entry type — determines default icon/color in UI components */
146
+ type?: FeatureType;
147
+ /** Priority level — critical entries get special treatment in UI */
148
+ priority?: FeaturePriority;
149
+ /** Optional image/screenshot URL */
150
+ image?: string;
151
+ /** Optional call-to-action button */
152
+ cta?: FeatureCTA;
153
+ /** ISO date — entry is hidden until this date (scheduled publishing) */
154
+ publishAt?: string;
155
+ /** Optional arbitrary metadata */
156
+ meta?: Record<string, unknown>;
157
+ /** A/B variants keyed by variant name (e.g. control, treatment_a) */
158
+ variants?: Record<string, FeatureVariant>;
159
+ /** Percentage split per variant (same order as variants object keys) */
160
+ variantSplit?: number[];
161
+ /** Audience targeting — if set, only matching users see this feature */
162
+ audience?: AudienceRule;
163
+ /** Dependency requirements (progressive disclosure sequencing) */
164
+ dependsOn?: FeatureDependencies;
165
+ /** Contextual trigger rule */
166
+ trigger?: FeatureTrigger;
167
+ }
168
+ /** The full feature manifest — an array of feature entries */
169
+ type FeatureManifest = readonly FeatureEntry[];
170
+ /**
171
+ * Storage adapter interface — implement for your persistence layer.
172
+ *
173
+ * The adapter bridges two data sources:
174
+ * - **Watermark**: a server-side timestamp ("features seen at")
175
+ * - **Dismissed IDs**: client-side per-feature dismissals
176
+ */
177
+ interface StorageAdapter {
178
+ /** Get the user's "features seen at" watermark (ISO string or null) */
179
+ getWatermark(): string | null;
180
+ /** Get the set of individually dismissed feature IDs */
181
+ getDismissedIds(): ReadonlySet<string>;
182
+ /** Dismiss a single feature by ID */
183
+ dismiss(id: string): void;
184
+ /** Dismiss all features — sets watermark to `now` and clears dismissals */
185
+ dismissAll(now: Date): Promise<void>;
186
+ }
187
+ /** Analytics event callbacks — pipe to your analytics provider */
188
+ interface AnalyticsCallbacks {
189
+ /** Fired when a feature badge becomes visible to the user */
190
+ onFeatureSeen?: (feature: FeatureEntry) => void;
191
+ /** Fired when a user dismisses a single feature */
192
+ onFeatureDismissed?: (feature: FeatureEntry) => void;
193
+ /** Fired when a user clicks a feature link or CTA */
194
+ onFeatureClicked?: (feature: FeatureEntry) => void;
195
+ /** Fired when the changelog widget is opened */
196
+ onWidgetOpened?: () => void;
197
+ /** Fired when the changelog widget is closed */
198
+ onWidgetClosed?: () => void;
199
+ /** Fired when all features are dismissed at once */
200
+ onAllDismissed?: () => void;
201
+ }
202
+
203
+ interface ThrottleOptions {
204
+ maxSimultaneousBadges?: number;
205
+ maxSimultaneousSpotlights?: number;
206
+ maxToastsPerSession?: number;
207
+ minTimeBetweenModals?: number;
208
+ minTimeBetweenTours?: number;
209
+ sessionCooldown?: number;
210
+ respectDoNotDisturb?: boolean;
211
+ }
212
+
213
+ type AdoptionEventType = "feature_seen" | "feature_clicked" | "feature_dismissed" | "tour_started" | "tour_completed" | "tour_skipped" | "checklist_task_completed" | "checklist_completed" | "survey_submitted" | "feedback_submitted" | "announcement_shown" | "cta_clicked";
214
+ interface AdoptionEvent {
215
+ type: AdoptionEventType;
216
+ featureId?: string;
217
+ tourId?: string;
218
+ variant?: string;
219
+ timestamp: string;
220
+ sessionId?: string;
221
+ userId?: string;
222
+ metadata?: Record<string, unknown>;
223
+ }
224
+ type AdoptionEventInput = Omit<AdoptionEvent, "timestamp"> & {
225
+ timestamp?: string;
226
+ };
227
+ interface AnalyticsAdapter {
228
+ track: (event: AdoptionEvent) => void | Promise<void>;
229
+ trackBatch?: (events: AdoptionEvent[]) => void | Promise<void>;
230
+ }
231
+ interface AnalyticsCollectorOptions {
232
+ adapter: AnalyticsAdapter;
233
+ batchSize?: number;
234
+ flushInterval?: number;
235
+ sampleRate?: number;
236
+ enabled?: boolean;
237
+ sessionId?: string;
238
+ userId?: string;
239
+ now?: () => Date;
240
+ random?: () => number;
241
+ }
242
+ declare class AnalyticsCollector {
243
+ private adapter;
244
+ private queue;
245
+ private batchSize;
246
+ private flushInterval;
247
+ private sampleRate;
248
+ private enabled;
249
+ private now;
250
+ private random;
251
+ private sessionId?;
252
+ private userId?;
253
+ private timer;
254
+ private flushing;
255
+ constructor(options: AnalyticsCollectorOptions);
256
+ setEnabled(enabled: boolean): void;
257
+ setContext(context: {
258
+ sessionId?: string;
259
+ userId?: string;
260
+ }): void;
261
+ getQueueSize(): number;
262
+ track(event: AdoptionEventInput): void;
263
+ flush(): Promise<void>;
264
+ destroy(): Promise<void>;
265
+ private startTimer;
266
+ }
267
+ interface FeatureEngagementMetrics {
268
+ seen: number;
269
+ clicked: number;
270
+ dismissed: number;
271
+ }
272
+ interface AdoptionMetrics {
273
+ getAdoptionRate: (featureId: string) => number;
274
+ getTourCompletionRate: (tourId: string) => number;
275
+ getChecklistCompletionRate: (checklistId: string) => number;
276
+ getFeatureEngagement: (featureId: string) => FeatureEngagementMetrics;
277
+ getVariantPerformance: (featureId: string) => Record<string, number>;
278
+ }
279
+
280
+ interface FeatureDropTranslations {
281
+ newBadge: string;
282
+ whatsNewTitle: string;
283
+ markAllRead: string;
284
+ allCaughtUp: string;
285
+ close: string;
286
+ changelogTitle: string;
287
+ searchPlaceholder: string;
288
+ allCategories: string;
289
+ noUpdatesYet: string;
290
+ loadMore: string;
291
+ share: string;
292
+ skipToEntries: string;
293
+ newFeatureCount: (count: number) => string;
294
+ stepOf: (current: number, total: number) => string;
295
+ back: string;
296
+ next: string;
297
+ skip: string;
298
+ finish: string;
299
+ gotIt: string;
300
+ announcement: string;
301
+ feedbackTitle: string;
302
+ feedbackTrigger: string;
303
+ feedbackSubmitted: string;
304
+ submit: string;
305
+ cancel: string;
306
+ askLater: string;
307
+ }
308
+
309
+ interface FeatureDropProviderProps {
310
+ /** The feature manifest — typically a frozen array of FeatureEntry objects */
311
+ manifest: FeatureManifest;
312
+ /** Storage adapter instance (e.g. LocalStorageAdapter, MemoryAdapter) */
313
+ storage: StorageAdapter;
314
+ /** Optional analytics callbacks — pipe to your analytics provider */
315
+ analytics?: AnalyticsCallbacks;
316
+ /** Optional error callback for monitoring caught component errors */
317
+ onError?: (error: unknown, context?: {
318
+ component?: string;
319
+ componentStack?: string;
320
+ }) => void;
321
+ /** User context for audience targeting (plan, role, region, traits) */
322
+ userContext?: UserContext;
323
+ /** Custom audience matcher — overrides default AND/OR matching logic */
324
+ matchAudience?: AudienceMatchFn;
325
+ /** Current app version (semver) for version-pinned features */
326
+ appVersion?: string;
327
+ /** Current product scope for multi-product manifests */
328
+ product?: string;
329
+ /** Announcement throttling and session cooldown controls */
330
+ throttle?: ThrottleOptions;
331
+ /** Stable identifier for A/B variant assignment (e.g. userId) */
332
+ variantKey?: string;
333
+ /** Optional adoption analytics collector */
334
+ collector?: AnalyticsCollector;
335
+ /** Feature flag bridge for evaluating `feature.flagKey` visibility */
336
+ flagBridge?: FeatureFlagBridge;
337
+ /** Locale code for built-in component translations (e.g. "en", "fr", "es") */
338
+ locale?: string;
339
+ /** Animation preset for built-in component transitions */
340
+ animation?: FeatureDropAnimationPreset;
341
+ /** Custom translation overrides for built-in component strings */
342
+ translations?: Partial<FeatureDropTranslations>;
343
+ children: ReactNode;
344
+ }
345
+ /**
346
+ * Provides feature discovery state to the component tree.
347
+ *
348
+ * Wrap your app (or a subtree) with this provider to enable
349
+ * `useFeatureDrop`, `useNewFeature`, `useNewCount`, and other hooks.
350
+ */
351
+ declare function FeatureDropProvider({ manifest, storage, analytics, onError, userContext, matchAudience: matchAudienceFn, appVersion, product, throttle, variantKey, collector, flagBridge, locale, animation, translations: translationOverrides, children, }: FeatureDropProviderProps): react_jsx_runtime.JSX.Element;
352
+
353
+ interface FeatureDropTheme {
354
+ colors: {
355
+ primary: string;
356
+ background: string;
357
+ text: string;
358
+ textMuted: string;
359
+ border: string;
360
+ success: string;
361
+ warning: string;
362
+ error: string;
363
+ };
364
+ fonts: {
365
+ family: string;
366
+ sizeBase: string;
367
+ sizeSm: string;
368
+ sizeLg: string;
369
+ };
370
+ spacing: {
371
+ xs: string;
372
+ sm: string;
373
+ md: string;
374
+ lg: string;
375
+ xl: string;
376
+ };
377
+ radii: {
378
+ sm: string;
379
+ md: string;
380
+ lg: string;
381
+ full: string;
382
+ };
383
+ shadows: {
384
+ sm: string;
385
+ md: string;
386
+ lg: string;
387
+ };
388
+ zIndex: {
389
+ base: number;
390
+ tooltip: number;
391
+ modal: number;
392
+ overlay: number;
393
+ };
394
+ }
395
+ type FeatureDropThemePreset = "light" | "dark" | "auto" | "minimal" | "vibrant";
396
+ type FeatureDropThemeOverrides = {
397
+ [K in keyof FeatureDropTheme]?: Partial<FeatureDropTheme[K]>;
398
+ };
399
+ type FeatureDropThemeInput = FeatureDropThemePreset | FeatureDropThemeOverrides | FeatureDropTheme;
400
+
401
+ interface ThemeProviderProps {
402
+ /** Theme preset ("light" | "dark" | "auto" | "minimal" | "vibrant") or custom theme overrides */
403
+ theme?: FeatureDropThemeInput;
404
+ /** Optional CSS class for the wrapper element */
405
+ className?: string;
406
+ /** Optional inline style merged after theme CSS variables */
407
+ style?: CSSProperties;
408
+ children: ReactNode;
409
+ }
410
+ /**
411
+ * Applies FeatureDrop theme tokens as CSS custom properties to a subtree.
412
+ *
413
+ * All featuredrop components inside this provider inherit the resolved theme.
414
+ */
415
+ declare function ThemeProvider({ theme, className, style, children, }: ThemeProviderProps): react_jsx_runtime.JSX.Element;
416
+
417
+ interface FeatureDropContextValue {
418
+ /** Full manifest provided to the provider */
419
+ manifest: FeatureEntry[] | readonly FeatureEntry[];
420
+ /** All currently "new" features */
421
+ newFeatures: FeatureEntry[];
422
+ /** New features currently queued by throttling rules */
423
+ queuedFeatures: FeatureEntry[];
424
+ /** Count of new features */
425
+ newCount: number;
426
+ /** Count before throttling (all pending new features) */
427
+ totalNewCount: number;
428
+ /** All new features sorted by priority then release date */
429
+ newFeaturesSorted: FeatureEntry[];
430
+ /** Check if a sidebar key has any new features */
431
+ isNew: (sidebarKey: string) => boolean;
432
+ /** Dismiss a single feature by ID */
433
+ dismiss: (id: string) => void;
434
+ /** Dismiss all features (marks all as seen) */
435
+ dismissAll: () => Promise<void>;
436
+ /** Get the feature entry for a sidebar key (if it's new) */
437
+ getFeature: (sidebarKey: string) => FeatureEntry | undefined;
438
+ /** Whether quiet mode (Do Not Disturb) is enabled */
439
+ quietMode: boolean;
440
+ /** Enable/disable quiet mode */
441
+ setQuietMode: (enabled: boolean) => void;
442
+ /** Mark a feature as seen for dependency-chain resolution */
443
+ markFeatureSeen: (featureId: string) => void;
444
+ /** Mark a feature as clicked for dependency-chain resolution */
445
+ markFeatureClicked: (featureId: string) => void;
446
+ /** Remaining toasts allowed in this session under throttle rules */
447
+ getRemainingToastSlots: () => number;
448
+ /** Mark toasts as shown in this session */
449
+ markToastsShown: (featureIds: string[]) => void;
450
+ /** Whether a modal can open right now under throttle rules */
451
+ canShowModal: (priority?: FeaturePriority) => boolean;
452
+ /** Record a modal display timestamp */
453
+ markModalShown: () => void;
454
+ /** Whether a tour can start right now under throttle rules */
455
+ canShowTour: () => boolean;
456
+ /** Record a tour start timestamp */
457
+ markTourShown: () => void;
458
+ /** Acquire/release spotlight slots under maxSimultaneousSpotlights */
459
+ acquireSpotlightSlot: (id: string, priority?: FeaturePriority) => boolean;
460
+ releaseSpotlightSlot: (id: string) => void;
461
+ /** Number of currently active spotlight slots */
462
+ activeSpotlightCount: number;
463
+ /** Emit an adoption analytics event (collector-backed when configured) */
464
+ trackAdoptionEvent: (event: AdoptionEventInput) => void;
465
+ /** Report a component/runtime error to provider-level monitoring hooks */
466
+ reportError: (error: unknown, context?: {
467
+ component?: string;
468
+ componentStack?: string;
469
+ }) => void;
470
+ /** Active locale code used by built-in UI strings */
471
+ locale: string;
472
+ /** Text direction derived from locale */
473
+ direction: "ltr" | "rtl";
474
+ /** Active motion preset for built-in component transitions */
475
+ animation: FeatureDropAnimationPreset;
476
+ /** Resolved translation strings for built-in React components */
477
+ translations: FeatureDropTranslations;
478
+ /** Track a named usage event for trigger rules */
479
+ trackUsageEvent: (event: string, delta?: number) => void;
480
+ /** Track a named trigger event for trigger rules */
481
+ trackTriggerEvent: (event: string) => void;
482
+ /** Mark a milestone for trigger rules */
483
+ trackMilestone: (event: string) => void;
484
+ /** Manually override current path for page trigger rules */
485
+ setTriggerPath: (path: string) => void;
486
+ }
487
+ declare const FeatureDropContext: react.Context<FeatureDropContextValue | null>;
488
+
489
+ /**
490
+ * Access the full feature discovery context.
491
+ *
492
+ * Returns: `{ newFeatures, newCount, isNew, dismiss, dismissAll, getFeature }`
493
+ *
494
+ * @throws Error if used outside of `<FeatureDropProvider>`
495
+ */
496
+ declare function useFeatureDrop(): FeatureDropContextValue;
497
+
498
+ interface UseNewFeatureResult {
499
+ /** Whether this sidebar key has a new feature */
500
+ isNew: boolean;
501
+ /** The feature entry, if new */
502
+ feature: FeatureEntry | undefined;
503
+ /** Dismiss the feature for this sidebar key */
504
+ dismiss: () => void;
505
+ }
506
+ /**
507
+ * Check if a single navigation item has a new feature.
508
+ *
509
+ * @param sidebarKey - The key to check (e.g. "/journal", "settings")
510
+ * @returns `{ isNew, feature, dismiss }`
511
+ */
512
+ declare function useNewFeature(sidebarKey: string): UseNewFeatureResult;
513
+
514
+ /**
515
+ * Get the count of currently new features.
516
+ *
517
+ * Useful for rendering a badge count on a "What's New" button.
518
+ *
519
+ * @returns The number of new features
520
+ */
521
+ declare function useNewCount(): number;
522
+
523
+ interface UseTabNotificationOptions {
524
+ /** Whether tab notifications are enabled. Default: true */
525
+ enabled?: boolean;
526
+ /** Template string. `{count}` is replaced with the number. Default: "({count}) {title}" */
527
+ template?: string;
528
+ /** Enable flashing/blinking pattern for attention. Default: false */
529
+ flash?: boolean;
530
+ /** Flash interval in ms. Default: 1500 */
531
+ flashInterval?: number;
532
+ }
533
+ /**
534
+ * Updates the browser tab title with the unread feature count.
535
+ *
536
+ * Shows "(3) My App" when there are new features, restores the original
537
+ * title when all features are read. Optional flash/blink pattern for attention.
538
+ *
539
+ * @example
540
+ * ```tsx
541
+ * function App() {
542
+ * useTabNotification();
543
+ * return <div>...</div>;
544
+ * }
545
+ * ```
546
+ *
547
+ * @example With flash
548
+ * ```tsx
549
+ * useTabNotification({ flash: true, template: "[{count} new] {title}" });
550
+ * ```
551
+ */
552
+ declare function useTabNotification(options?: UseTabNotificationOptions): void;
553
+
554
+ declare function useAdoptionAnalytics(events: AdoptionEvent[]): AdoptionMetrics;
555
+
556
+ interface TourStep {
557
+ id: string;
558
+ target: string | RefObject<HTMLElement | null>;
559
+ title: string;
560
+ content: string | ReactNode;
561
+ placement?: "top" | "bottom" | "left" | "right" | "auto";
562
+ action?: "click" | "input" | "custom";
563
+ advanceOn?: {
564
+ selector: string;
565
+ event: string;
566
+ };
567
+ highlightTarget?: boolean;
568
+ beforeStep?: () => Promise<void>;
569
+ afterStep?: () => Promise<void>;
570
+ skipable?: boolean;
571
+ }
572
+ interface TourRenderProps {
573
+ isActive: boolean;
574
+ step: TourStep | null;
575
+ stepIndex: number;
576
+ totalSteps: number;
577
+ startTour: () => void;
578
+ nextStep: () => void;
579
+ prevStep: () => void;
580
+ skipTour: () => void;
581
+ closeTour: () => void;
582
+ }
583
+ interface TourProps {
584
+ id: string;
585
+ steps: TourStep[];
586
+ onComplete?: () => void;
587
+ onSkip?: (stepId: string) => void;
588
+ onTourStarted?: () => void;
589
+ onTourCompleted?: () => void;
590
+ onTourSkipped?: (stepId: string) => void;
591
+ onStepViewed?: (step: TourStep, index: number) => void;
592
+ overlay?: boolean;
593
+ showProgress?: boolean;
594
+ keyboard?: boolean;
595
+ persistence?: boolean;
596
+ children?: (props: TourRenderProps) => ReactNode;
597
+ }
598
+
599
+ interface TourSnapshot {
600
+ isActive: boolean;
601
+ currentStepIndex: number;
602
+ currentStep: TourStep | null;
603
+ totalSteps: number;
604
+ }
605
+
606
+ interface UseTourResult {
607
+ startTour: () => void;
608
+ nextStep: () => void;
609
+ prevStep: () => void;
610
+ skipTour: () => void;
611
+ closeTour: () => void;
612
+ currentStep: TourSnapshot["currentStep"];
613
+ currentStepIndex: number;
614
+ totalSteps: number;
615
+ isActive: boolean;
616
+ }
617
+ declare function useTour(id: string): UseTourResult;
618
+
619
+ interface TourSequenceItem {
620
+ featureId: string;
621
+ tourId: string;
622
+ }
623
+ interface UseTourSequencerResult {
624
+ nextTourId: string | null;
625
+ nextFeatureId: string | null;
626
+ remainingTours: number;
627
+ startNextTour: () => boolean;
628
+ }
629
+ declare function useTourSequencer(sequence: TourSequenceItem[]): UseTourSequencerResult;
630
+
631
+ interface UseChecklistResult {
632
+ completeTask: (taskId: string) => void;
633
+ resetChecklist: () => void;
634
+ dismissChecklist: () => void;
635
+ toggleCollapsed: () => void;
636
+ isComplete: boolean;
637
+ progress: {
638
+ completed: number;
639
+ total: number;
640
+ percent: number;
641
+ };
642
+ tasks: Array<{
643
+ id: string;
644
+ completed: boolean;
645
+ }>;
646
+ dismissed: boolean;
647
+ collapsed: boolean;
648
+ }
649
+ declare function useChecklist(id: string): UseChecklistResult;
650
+
651
+ type SurveyType = "nps" | "csat" | "ces" | "custom";
652
+ type SurveyQuestionType = "single-choice" | "multi-choice" | "text";
653
+ interface SurveyQuestion {
654
+ id: string;
655
+ type: SurveyQuestionType;
656
+ prompt: string;
657
+ options?: string[];
658
+ required?: boolean;
659
+ }
660
+ interface SurveyTriggerRules {
661
+ signupAt?: string | Date;
662
+ minDaysSinceSignup?: number;
663
+ featureUsageIds?: string[];
664
+ pageMatch?: string | RegExp | ((path: string) => boolean);
665
+ sampleRate?: number;
666
+ maxFrequencyDays?: number;
667
+ askLaterCooldownDays?: number;
668
+ }
669
+ interface SurveyPayload {
670
+ id: string;
671
+ type: SurveyType;
672
+ prompt?: string;
673
+ score?: number;
674
+ responses?: Record<string, unknown>;
675
+ feedback?: string;
676
+ timestamp: string;
677
+ url: string;
678
+ featureId?: string;
679
+ metadata?: Record<string, unknown>;
680
+ }
681
+ interface SurveyRenderProps {
682
+ isOpen: boolean;
683
+ isSubmitting: boolean;
684
+ submitted: boolean;
685
+ canShow: boolean;
686
+ error: string | null;
687
+ type: SurveyType;
688
+ score: number | null;
689
+ feedback: string;
690
+ responses: Record<string, unknown>;
691
+ show: (options?: {
692
+ force?: boolean;
693
+ }) => boolean;
694
+ hide: () => void;
695
+ askLater: () => void;
696
+ setScore: (value: number | null) => void;
697
+ setFeedback: (value: string) => void;
698
+ setResponse: (questionId: string, value: unknown) => void;
699
+ submit: () => Promise<boolean>;
700
+ }
701
+ interface SurveyProps {
702
+ id: string;
703
+ type: SurveyType;
704
+ prompt?: string;
705
+ featureId?: string;
706
+ questions?: SurveyQuestion[];
707
+ trigger?: "auto" | "manual";
708
+ triggerRules?: SurveyTriggerRules;
709
+ defaultOpen?: boolean;
710
+ showAskLater?: boolean;
711
+ submitLabel?: string;
712
+ askLaterLabel?: string;
713
+ closeLabel?: string;
714
+ title?: string;
715
+ metadata?: Record<string, unknown>;
716
+ onSubmit: (payload: SurveyPayload) => Promise<void> | void;
717
+ onAskLater?: () => void;
718
+ onDismiss?: () => void;
719
+ className?: string;
720
+ style?: CSSProperties;
721
+ children?: (props: SurveyRenderProps) => ReactNode;
722
+ }
723
+
724
+ interface UseSurveyResult {
725
+ show: (options?: {
726
+ force?: boolean;
727
+ }) => boolean;
728
+ hide: () => void;
729
+ askLater: () => void;
730
+ isOpen: boolean;
731
+ submitted: boolean;
732
+ canShow: boolean;
733
+ type: SurveyType;
734
+ }
735
+ declare function useSurvey(id: string): UseSurveyResult;
736
+
737
+ interface NewBadgeRenderProps {
738
+ /** Whether the feature is currently new */
739
+ isNew: boolean;
740
+ }
741
+ interface NewBadgeProps {
742
+ /** Display variant */
743
+ variant?: "pill" | "dot" | "count";
744
+ /** Whether to show the badge (typically from `useNewFeature().isNew`) */
745
+ show?: boolean;
746
+ /** Count to display when variant is "count" */
747
+ count?: number;
748
+ /** Text label for the pill variant. Default: "New" */
749
+ label?: string;
750
+ /** Dismiss callback. If set with `dismissOnClick`, clicking dismisses. */
751
+ onDismiss?: () => void;
752
+ /** Whether clicking the badge should trigger onDismiss */
753
+ dismissOnClick?: boolean;
754
+ /** Additional CSS class */
755
+ className?: string;
756
+ /** Additional inline styles (merged with defaults) */
757
+ style?: CSSProperties;
758
+ /** Render prop for full customization */
759
+ children?: (props: NewBadgeRenderProps) => ReactNode;
760
+ }
761
+
762
+ type ReactionCounts = Record<string, number>;
763
+
764
+ interface ChangelogEntryRenderProps {
765
+ feature: FeatureEntry;
766
+ dismiss: () => void;
767
+ onFeatureClick?: () => void;
768
+ reactions?: ReactionCounts;
769
+ userReaction?: string | null;
770
+ canReact?: boolean;
771
+ react?: (reaction: string) => void;
772
+ }
773
+ interface ChangelogWidgetRenderProps {
774
+ /** Whether the widget is currently open */
775
+ isOpen: boolean;
776
+ /** Open the widget */
777
+ open: () => void;
778
+ /** Close the widget */
779
+ close: () => void;
780
+ /** Toggle open/close */
781
+ toggle: () => void;
782
+ /** Current new feature count */
783
+ count: number;
784
+ /** Sorted features to display */
785
+ features: FeatureEntry[];
786
+ /** Dismiss a single feature */
787
+ dismiss: (id: string) => void;
788
+ /** Dismiss all features */
789
+ dismissAll: () => Promise<void>;
790
+ }
791
+ interface ChangelogWidgetProps {
792
+ /** Display variant */
793
+ variant?: "panel" | "modal" | "popover";
794
+ /** Title shown in the widget header. Default: "What's New" */
795
+ title?: string;
796
+ /** Text for the trigger button. Default: "What's New" */
797
+ triggerLabel?: string;
798
+ /** Show trigger badge count. Default: true */
799
+ showCount?: boolean;
800
+ /** Text for the "mark all as read" button. Default: "Mark all as read" */
801
+ markAllLabel?: string;
802
+ /** Whether to show the mark-all button. Default: true */
803
+ showMarkAll?: boolean;
804
+ /** Text shown when no new features exist. Default: "You're all caught up!" */
805
+ emptyLabel?: string;
806
+ /** Max height for the feed area. Default: "400px" */
807
+ maxHeight?: string;
808
+ /** Date display mode for entry metadata. Default: "absolute" */
809
+ dateFormat?: "absolute" | "relative";
810
+ /** Analytics callbacks */
811
+ analytics?: AnalyticsCallbacks;
812
+ /** Additional CSS class for the container */
813
+ className?: string;
814
+ /** Additional inline styles for the container */
815
+ style?: CSSProperties;
816
+ /** Optional component-scoped theme preset or overrides */
817
+ theme?: FeatureDropThemeInput;
818
+ /** Render prop for full customization — receives widget state */
819
+ children?: (props: ChangelogWidgetRenderProps) => ReactNode;
820
+ /** Custom render for each entry — receives feature + dismiss callback */
821
+ renderEntry?: (props: ChangelogEntryRenderProps) => ReactNode;
822
+ /** Custom render for the trigger button */
823
+ renderTrigger?: (props: {
824
+ count: number;
825
+ onClick: () => void;
826
+ }) => ReactNode;
827
+ /** Show reaction controls on each entry. Default: false */
828
+ showReactions?: boolean;
829
+ /** Reaction options. Default: 👍 ❤️ 🎉 👀 👎 */
830
+ reactions?: string[];
831
+ /** Callback fired when a reaction is persisted */
832
+ onReaction?: (feature: FeatureEntry, reaction: string, counts: ReactionCounts) => void;
833
+ }
834
+
835
+ interface SpotlightRenderProps {
836
+ /** The feature being spotlighted */
837
+ feature: FeatureEntry | undefined;
838
+ /** Whether the spotlight is active */
839
+ isActive: boolean;
840
+ /** Whether the tooltip is visible */
841
+ isTooltipOpen: boolean;
842
+ /** Show the tooltip */
843
+ openTooltip: () => void;
844
+ /** Hide the tooltip */
845
+ closeTooltip: () => void;
846
+ /** Dismiss this spotlight permanently */
847
+ dismiss: () => void;
848
+ }
849
+ interface SpotlightProps {
850
+ /** The feature ID to spotlight */
851
+ featureId: string;
852
+ /** Ref to the target DOM element — beacon will be positioned over it */
853
+ targetRef?: RefObject<HTMLElement | null>;
854
+ /** CSS selector for the target element (alternative to targetRef) */
855
+ targetSelector?: string;
856
+ /** Tooltip placement relative to target */
857
+ placement?: "top" | "bottom" | "left" | "right";
858
+ /** Beacon size in pixels. Default: 12 */
859
+ beaconSize?: number;
860
+ /** Auto-dismiss after the tooltip is seen */
861
+ autoDismiss?: boolean;
862
+ /** Delay before auto-dismiss in ms. Default: 5000 */
863
+ autoDismissDelay?: number;
864
+ /** Analytics callbacks */
865
+ analytics?: AnalyticsCallbacks;
866
+ /** Additional CSS class */
867
+ className?: string;
868
+ /** Custom tooltip content */
869
+ tooltipContent?: ReactNode;
870
+ /** Render prop for full customization */
871
+ children?: (props: SpotlightRenderProps) => ReactNode;
872
+ }
873
+
874
+ type BannerVariant = "info" | "success" | "warning" | "announcement";
875
+ interface BannerRenderProps {
876
+ /** The feature being announced */
877
+ feature: FeatureEntry | undefined;
878
+ /** Whether the banner is active */
879
+ isActive: boolean;
880
+ /** Whether the banner has been dismissed this session */
881
+ isDismissed: boolean;
882
+ /** Dismiss the banner permanently */
883
+ dismiss: () => void;
884
+ }
885
+ interface BannerProps {
886
+ /** Feature ID to display as a banner */
887
+ featureId: string;
888
+ /** Banner visual variant. Default: "announcement" */
889
+ variant?: BannerVariant;
890
+ /** Whether the banner is dismissible. Default: true */
891
+ dismissible?: boolean;
892
+ /** Position mode. Default: "sticky" */
893
+ position?: "sticky" | "inline" | "fixed";
894
+ /** Analytics callbacks */
895
+ analytics?: AnalyticsCallbacks;
896
+ /** Additional CSS class */
897
+ className?: string;
898
+ /** Additional inline styles */
899
+ style?: CSSProperties;
900
+ /** Render prop for full customization */
901
+ children?: (props: BannerRenderProps) => ReactNode;
902
+ }
903
+
904
+ interface ToastRenderProps {
905
+ /** Features currently showing as toasts */
906
+ toasts: FeatureEntry[];
907
+ /** Dismiss a specific toast */
908
+ dismiss: (id: string) => void;
909
+ /** Dismiss all toasts */
910
+ dismissAll: () => void;
911
+ }
912
+ interface ToastProps {
913
+ /** Feature IDs to show as toasts. If omitted, shows all new features. */
914
+ featureIds?: string[];
915
+ /** Max number of visible toasts at once. Default: 3 */
916
+ maxVisible?: number;
917
+ /** Auto-dismiss delay in ms. Default: 8000. Set to 0 to disable. */
918
+ autoDismissMs?: number;
919
+ /** Position on screen. Default: "bottom-right" */
920
+ position?: "top-right" | "top-left" | "bottom-right" | "bottom-left" | "top-center" | "bottom-center";
921
+ /** Analytics callbacks */
922
+ analytics?: AnalyticsCallbacks;
923
+ /** Additional CSS class for the container */
924
+ className?: string;
925
+ /** Additional inline styles for the container */
926
+ style?: CSSProperties;
927
+ /** Render prop for full customization */
928
+ children?: (props: ToastRenderProps) => ReactNode;
929
+ /** Custom render for each toast */
930
+ renderToast?: (props: {
931
+ feature: FeatureEntry;
932
+ dismiss: () => void;
933
+ }) => ReactNode;
934
+ }
935
+
936
+ type PaginationMode = "infinite-scroll" | "load-more" | "numbered";
937
+ interface ChangelogPageProps {
938
+ pageSize?: number;
939
+ pagination?: PaginationMode;
940
+ showFilters?: boolean;
941
+ showSearch?: boolean;
942
+ categories?: string[];
943
+ emptyState?: ReactNode;
944
+ renderEntry?: (entry: FeatureEntry, index: number) => ReactNode;
945
+ formatDate?: (date: string) => string;
946
+ dateFormat?: "absolute" | "relative";
947
+ basePath?: string;
948
+ manifest?: FeatureManifest;
949
+ className?: string;
950
+ style?: CSSProperties;
951
+ theme?: FeatureDropThemeInput;
952
+ showReactions?: boolean;
953
+ reactions?: string[];
954
+ onReaction?: (entry: FeatureEntry, reaction: string, counts: ReactionCounts) => void;
955
+ }
956
+
957
+ interface ChecklistTask {
958
+ id: string;
959
+ title: string;
960
+ description?: string;
961
+ completed?: boolean;
962
+ completionEvent?: string;
963
+ action?: {
964
+ type: "tour" | "link" | "callback";
965
+ target: string;
966
+ };
967
+ icon?: ReactNode;
968
+ estimatedTime?: string;
969
+ }
970
+ interface ChecklistRenderProps {
971
+ tasks: ChecklistTask[];
972
+ completedIds: Set<string>;
973
+ completeTask: (taskId: string) => void;
974
+ resetChecklist: () => void;
975
+ dismissChecklist: () => void;
976
+ isComplete: boolean;
977
+ progress: {
978
+ completed: number;
979
+ total: number;
980
+ percent: number;
981
+ };
982
+ collapsed: boolean;
983
+ toggleCollapsed: () => void;
984
+ }
985
+ interface ChecklistProps {
986
+ id: string;
987
+ tasks: ChecklistTask[];
988
+ position?: "bottom-right" | "bottom-left" | "top-right" | "top-left" | "inline";
989
+ collapsible?: boolean;
990
+ showProgress?: boolean;
991
+ onComplete?: () => void;
992
+ dismissible?: boolean;
993
+ actionHandlers?: Record<string, () => void>;
994
+ children?: (props: ChecklistRenderProps) => ReactNode;
995
+ }
996
+
997
+ interface HotspotProps {
998
+ id: string;
999
+ target: string;
1000
+ type?: "info" | "new" | "help";
1001
+ frequency?: "once" | "every-session" | "always";
1002
+ children: ReactNode;
1003
+ }
1004
+ interface TooltipGroupProps {
1005
+ maxVisible?: number;
1006
+ children: ReactNode;
1007
+ }
1008
+
1009
+ type FeedbackEmoji = "thumbs-up" | "thumbs-down" | "heart" | "thinking" | "fire";
1010
+ interface FeedbackPayload {
1011
+ featureId?: string;
1012
+ text: string;
1013
+ category?: string;
1014
+ emoji?: FeedbackEmoji;
1015
+ screenshot?: Blob;
1016
+ url: string;
1017
+ timestamp: string;
1018
+ metadata?: Record<string, unknown>;
1019
+ }
1020
+ type FeedbackRateLimit = "none" | "1-per-feature" | "1-per-session";
1021
+ interface FeedbackWidgetRenderProps {
1022
+ isOpen: boolean;
1023
+ isSubmitting: boolean;
1024
+ isRateLimited: boolean;
1025
+ submitted: boolean;
1026
+ text: string;
1027
+ category: string;
1028
+ emoji: FeedbackEmoji | null;
1029
+ screenshot: Blob | null;
1030
+ error: string | null;
1031
+ open: () => void;
1032
+ close: () => void;
1033
+ setText: (value: string) => void;
1034
+ setCategory: (value: string) => void;
1035
+ setEmoji: (value: FeedbackEmoji | null) => void;
1036
+ captureScreenshot: () => Promise<void>;
1037
+ submit: () => Promise<void>;
1038
+ }
1039
+ interface FeedbackWidgetProps {
1040
+ featureId?: string;
1041
+ onSubmit: (payload: FeedbackPayload) => Promise<void> | void;
1042
+ showScreenshot?: boolean;
1043
+ showEmoji?: boolean;
1044
+ rateLimit?: FeedbackRateLimit;
1045
+ categories?: string[];
1046
+ metadata?: Record<string, unknown>;
1047
+ screenshotCapture?: () => Promise<Blob | null | undefined>;
1048
+ triggerLabel?: string;
1049
+ title?: string;
1050
+ className?: string;
1051
+ style?: CSSProperties;
1052
+ children?: (props: FeedbackWidgetRenderProps) => ReactNode;
1053
+ }
1054
+
1055
+ interface AnnouncementSlide {
1056
+ id?: string;
1057
+ title: string;
1058
+ description?: string;
1059
+ image?: string;
1060
+ videoUrl?: string;
1061
+ primaryCta?: FeatureCTA;
1062
+ secondaryCta?: FeatureCTA;
1063
+ }
1064
+ interface AnnouncementModalRenderProps {
1065
+ isOpen: boolean;
1066
+ currentSlide: AnnouncementSlide | null;
1067
+ currentSlideIndex: number;
1068
+ totalSlides: number;
1069
+ open: () => void;
1070
+ close: () => void;
1071
+ nextSlide: () => void;
1072
+ prevSlide: () => void;
1073
+ dismiss: () => void;
1074
+ }
1075
+ interface AnnouncementModalProps {
1076
+ id?: string;
1077
+ featureId?: string;
1078
+ feature?: FeatureEntry;
1079
+ trigger?: "auto" | "manual";
1080
+ defaultOpen?: boolean;
1081
+ slides?: AnnouncementSlide[];
1082
+ frequency?: "once" | "every-session" | "always";
1083
+ dismissible?: boolean;
1084
+ mobileBreakpoint?: number;
1085
+ onOpen?: () => void;
1086
+ onDismiss?: () => void;
1087
+ onPrimaryCtaClick?: (slide: AnnouncementSlide, index: number) => void;
1088
+ onSecondaryCtaClick?: (slide: AnnouncementSlide, index: number) => void;
1089
+ className?: string;
1090
+ style?: CSSProperties;
1091
+ children?: (props: AnnouncementModalRenderProps) => ReactNode;
1092
+ }
1093
+
1094
+ interface SpotlightChainStep {
1095
+ id?: string;
1096
+ target: string;
1097
+ title?: string;
1098
+ content: ReactNode;
1099
+ autoAdvanceMs?: number;
1100
+ }
1101
+ interface SpotlightChainRenderProps {
1102
+ isActive: boolean;
1103
+ currentStep: SpotlightChainStep | null;
1104
+ currentStepIndex: number;
1105
+ totalSteps: number;
1106
+ start: () => void;
1107
+ next: () => void;
1108
+ skip: () => void;
1109
+ }
1110
+ interface SpotlightChainProps {
1111
+ steps: SpotlightChainStep[];
1112
+ startOnMount?: boolean;
1113
+ autoAdvance?: boolean;
1114
+ autoAdvanceMs?: number;
1115
+ onComplete?: () => void;
1116
+ onStepViewed?: (step: SpotlightChainStep, index: number) => void;
1117
+ onSkip?: (step: SpotlightChainStep | null, index: number) => void;
1118
+ children?: (props: SpotlightChainRenderProps) => ReactNode;
1119
+ }
1120
+
1121
+ interface FeatureRequestRecord {
1122
+ id: string;
1123
+ featureId?: string;
1124
+ title: string;
1125
+ description?: string;
1126
+ category?: string;
1127
+ votes: number;
1128
+ createdAt: string;
1129
+ updatedAt: string;
1130
+ }
1131
+ type FeatureRequestSort = "votes" | "recent";
1132
+
1133
+ interface FeatureRequestButtonRenderProps {
1134
+ votes: number;
1135
+ hasVoted: boolean;
1136
+ vote: () => void;
1137
+ request: FeatureRequestRecord | null;
1138
+ }
1139
+ interface FeatureRequestButtonProps {
1140
+ featureId: string;
1141
+ requestId?: string;
1142
+ requestTitle?: string;
1143
+ label?: string;
1144
+ onVote?: (result: {
1145
+ voted: boolean;
1146
+ request: FeatureRequestRecord;
1147
+ }) => void;
1148
+ className?: string;
1149
+ style?: CSSProperties;
1150
+ children?: (props: FeatureRequestButtonRenderProps) => ReactNode;
1151
+ }
1152
+
1153
+ interface FeatureRequestPayload extends FeatureRequestRecord {
1154
+ metadata?: Record<string, unknown>;
1155
+ }
1156
+ interface FeatureRequestFormRenderProps {
1157
+ requests: FeatureRequestRecord[];
1158
+ sortBy: FeatureRequestSort;
1159
+ title: string;
1160
+ description: string;
1161
+ category: string;
1162
+ isSubmitting: boolean;
1163
+ error: string | null;
1164
+ setTitle: (value: string) => void;
1165
+ setDescription: (value: string) => void;
1166
+ setCategory: (value: string) => void;
1167
+ setSortBy: (value: FeatureRequestSort) => void;
1168
+ submit: () => Promise<void>;
1169
+ vote: (requestId: string) => void;
1170
+ }
1171
+ interface FeatureRequestFormProps {
1172
+ onSubmit?: (request: FeatureRequestPayload) => Promise<void> | void;
1173
+ onWebhook?: (request: FeatureRequestPayload) => Promise<void> | void;
1174
+ categories?: string[];
1175
+ defaultSort?: FeatureRequestSort;
1176
+ metadata?: Record<string, unknown>;
1177
+ className?: string;
1178
+ style?: CSSProperties;
1179
+ children?: (props: FeatureRequestFormRenderProps) => ReactNode;
1180
+ }
1181
+
1182
+ declare const NewBadge: react.ComponentType<NewBadgeProps>;
1183
+
1184
+ declare const ChangelogWidget: react.ComponentType<ChangelogWidgetProps>;
1185
+
1186
+ declare const Spotlight: react.ComponentType<SpotlightProps>;
1187
+
1188
+ declare const Banner: react.ComponentType<BannerProps>;
1189
+
1190
+ declare const Toast: react.ComponentType<ToastProps>;
1191
+
1192
+ declare const ChangelogPage: react.ComponentType<ChangelogPageProps>;
1193
+
1194
+ declare const Tour: react.ComponentType<TourProps>;
1195
+
1196
+ declare const Checklist: react.ComponentType<ChecklistProps>;
1197
+
1198
+ declare const Hotspot: react.ComponentType<HotspotProps>;
1199
+ declare const TooltipGroup: react.ComponentType<TooltipGroupProps>;
1200
+
1201
+ declare const FeedbackWidget: react.ComponentType<FeedbackWidgetProps>;
1202
+
1203
+ declare const AnnouncementModal: react.ComponentType<AnnouncementModalProps>;
1204
+
1205
+ declare const SpotlightChain: react.ComponentType<SpotlightChainProps>;
1206
+
1207
+ declare const Survey: react.ComponentType<SurveyProps>;
1208
+
1209
+ declare const FeatureRequestButton: react.ComponentType<FeatureRequestButtonProps>;
1210
+
1211
+ declare const FeatureRequestForm: react.ComponentType<FeatureRequestFormProps>;
1212
+
1213
+ export { AnnouncementModal, type AnnouncementModalProps, type AnnouncementModalRenderProps, type AnnouncementSlide, Banner, type BannerProps, type BannerRenderProps, type BannerVariant, type ChangelogEntryRenderProps, ChangelogPage, type ChangelogPageProps, ChangelogWidget, type ChangelogWidgetProps, type ChangelogWidgetRenderProps, Checklist, type ChecklistProps, type ChecklistRenderProps, type ChecklistTask, FeatureDropContext, type FeatureDropContextValue, FeatureDropProvider, type FeatureDropProviderProps, FeatureRequestButton, type FeatureRequestButtonProps, type FeatureRequestButtonRenderProps, FeatureRequestForm, type FeatureRequestFormProps, type FeatureRequestFormRenderProps, type FeatureRequestPayload, type FeedbackEmoji, type FeedbackPayload, type FeedbackRateLimit, FeedbackWidget, type FeedbackWidgetProps, type FeedbackWidgetRenderProps, Hotspot, type HotspotProps, NewBadge, type NewBadgeProps, type NewBadgeRenderProps, type PaginationMode, Spotlight, SpotlightChain, type SpotlightChainProps, type SpotlightChainRenderProps, type SpotlightChainStep, type SpotlightProps, type SpotlightRenderProps, Survey, type SurveyPayload, type SurveyProps, type SurveyQuestion, type SurveyQuestionType, type SurveyRenderProps, type SurveyTriggerRules, type SurveyType, ThemeProvider, type ThemeProviderProps, Toast, type ToastProps, type ToastRenderProps, TooltipGroup, type TooltipGroupProps, Tour, type TourProps, type TourRenderProps, type TourSequenceItem, type TourStep, type UseChecklistResult, type UseNewFeatureResult, type UseSurveyResult, type UseTabNotificationOptions, type UseTourResult, type UseTourSequencerResult, useAdoptionAnalytics, useChecklist, useFeatureDrop, useNewCount, useNewFeature, useSurvey, useTabNotification, useTour, useTourSequencer };