featuredrop 2.7.1 → 3.0.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/README.md +34 -1
- package/dist/astro.cjs +333 -0
- package/dist/astro.cjs.map +1 -0
- package/dist/astro.d.cts +242 -0
- package/dist/astro.d.ts +242 -0
- package/dist/astro.js +329 -0
- package/dist/astro.js.map +1 -0
- package/dist/engine.cjs +552 -0
- package/dist/engine.cjs.map +1 -0
- package/dist/engine.d.cts +422 -0
- package/dist/engine.d.ts +422 -0
- package/dist/engine.js +545 -0
- package/dist/engine.js.map +1 -0
- package/dist/featuredrop.cjs +208 -1
- package/dist/featuredrop.cjs.map +1 -1
- package/dist/next.cjs +336 -0
- package/dist/next.cjs.map +1 -0
- package/dist/next.d.cts +243 -0
- package/dist/next.d.ts +243 -0
- package/dist/next.js +332 -0
- package/dist/next.js.map +1 -0
- package/dist/nuxt.cjs +352 -0
- package/dist/nuxt.cjs.map +1 -0
- package/dist/nuxt.d.cts +282 -0
- package/dist/nuxt.d.ts +282 -0
- package/dist/nuxt.js +347 -0
- package/dist/nuxt.js.map +1 -0
- package/dist/preact.cjs +354 -0
- package/dist/preact.cjs.map +1 -1
- package/dist/preact.d.cts +170 -1
- package/dist/preact.d.ts +170 -1
- package/dist/preact.js +350 -1
- package/dist/preact.js.map +1 -1
- package/dist/react-hooks.cjs +82 -0
- package/dist/react-hooks.cjs.map +1 -1
- package/dist/react-hooks.d.cts +117 -1
- package/dist/react-hooks.d.ts +117 -1
- package/dist/react-hooks.js +80 -1
- package/dist/react-hooks.js.map +1 -1
- package/dist/react.cjs +354 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +170 -1
- package/dist/react.d.ts +170 -1
- package/dist/react.js +350 -1
- package/dist/react.js.map +1 -1
- package/dist/remix.cjs +331 -0
- package/dist/remix.cjs.map +1 -0
- package/dist/remix.d.cts +305 -0
- package/dist/remix.d.ts +305 -0
- package/dist/remix.js +327 -0
- package/dist/remix.js.map +1 -0
- package/package.json +70 -2
package/dist/engine.d.ts
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
/** Entry type label — determines default icon/color in UI */
|
|
2
|
+
type FeatureType = "feature" | "improvement" | "fix" | "breaking";
|
|
3
|
+
/** Priority level for announcements */
|
|
4
|
+
type FeaturePriority = "critical" | "normal" | "low";
|
|
5
|
+
/** Call-to-action for a feature entry */
|
|
6
|
+
interface FeatureCTA {
|
|
7
|
+
/** Button/link label */
|
|
8
|
+
label: string;
|
|
9
|
+
/** URL to navigate to */
|
|
10
|
+
url: string;
|
|
11
|
+
}
|
|
12
|
+
/** Variant-level overrides for A/B announcement testing */
|
|
13
|
+
interface FeatureVariant {
|
|
14
|
+
/** Optional variant-specific label override */
|
|
15
|
+
label?: string;
|
|
16
|
+
/** Optional variant-specific description override */
|
|
17
|
+
description?: string;
|
|
18
|
+
/** Optional variant-specific image override */
|
|
19
|
+
image?: string;
|
|
20
|
+
/** Optional variant-specific CTA override */
|
|
21
|
+
cta?: FeatureCTA;
|
|
22
|
+
/** Optional variant-specific metadata overrides */
|
|
23
|
+
meta?: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
/** Audience targeting rule — determines which user segments see a feature */
|
|
26
|
+
interface AudienceRule {
|
|
27
|
+
/** Plans that should see this feature (e.g. ["pro", "enterprise"]) */
|
|
28
|
+
plan?: string[];
|
|
29
|
+
/** Roles that should see this feature (e.g. ["admin", "editor"]) */
|
|
30
|
+
role?: string[];
|
|
31
|
+
/** Regions that should see this feature (e.g. ["us", "eu"]) */
|
|
32
|
+
region?: string[];
|
|
33
|
+
/** Arbitrary key-value pairs for custom matching logic */
|
|
34
|
+
custom?: Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
/** Dependency gates for progressive feature discovery */
|
|
37
|
+
interface FeatureDependencies {
|
|
38
|
+
/** Features the user must have seen before this one can surface */
|
|
39
|
+
seen?: string[];
|
|
40
|
+
/** Features the user must have clicked before this one can surface */
|
|
41
|
+
clicked?: string[];
|
|
42
|
+
/** Features the user must have dismissed before this one can surface */
|
|
43
|
+
dismissed?: string[];
|
|
44
|
+
}
|
|
45
|
+
/** Runtime context used by trigger evaluation */
|
|
46
|
+
interface TriggerContext {
|
|
47
|
+
/** Current app route/path */
|
|
48
|
+
path?: string;
|
|
49
|
+
/** Named events observed in this session */
|
|
50
|
+
events?: ReadonlySet<string>;
|
|
51
|
+
/** Named milestone flags reached in this session */
|
|
52
|
+
milestones?: ReadonlySet<string>;
|
|
53
|
+
/** Usage counters keyed by event/pattern name */
|
|
54
|
+
usage?: Record<string, number>;
|
|
55
|
+
/** Session elapsed time in milliseconds */
|
|
56
|
+
elapsedMs?: number;
|
|
57
|
+
/** Scroll completion percentage (0-100) */
|
|
58
|
+
scrollPercent?: number;
|
|
59
|
+
/** Optional additional trigger context */
|
|
60
|
+
metadata?: Record<string, unknown>;
|
|
61
|
+
}
|
|
62
|
+
type FeatureTrigger = {
|
|
63
|
+
type: "page";
|
|
64
|
+
match: string | RegExp;
|
|
65
|
+
} | {
|
|
66
|
+
type: "usage";
|
|
67
|
+
event: string;
|
|
68
|
+
minActions?: number;
|
|
69
|
+
} | {
|
|
70
|
+
type: "time";
|
|
71
|
+
minSeconds: number;
|
|
72
|
+
} | {
|
|
73
|
+
type: "milestone";
|
|
74
|
+
event: string;
|
|
75
|
+
} | {
|
|
76
|
+
type: "frustration";
|
|
77
|
+
pattern: string;
|
|
78
|
+
threshold?: number;
|
|
79
|
+
} | {
|
|
80
|
+
type: "scroll";
|
|
81
|
+
minPercent?: number;
|
|
82
|
+
} | {
|
|
83
|
+
type: "custom";
|
|
84
|
+
evaluate: (context: TriggerContext) => boolean;
|
|
85
|
+
};
|
|
86
|
+
/** A single feature entry in the manifest */
|
|
87
|
+
interface FeatureEntry {
|
|
88
|
+
/** Unique identifier for the feature */
|
|
89
|
+
id: string;
|
|
90
|
+
/** Human-readable label (e.g. "Decision Journal") */
|
|
91
|
+
label: string;
|
|
92
|
+
/** Optional longer description (supports markdown in UI components) */
|
|
93
|
+
description?: string;
|
|
94
|
+
/**
|
|
95
|
+
* Semantic version targeting.
|
|
96
|
+
* If provided as an object, requires `appVersion` to be supplied to the provider/helpers.
|
|
97
|
+
* - introduced: earliest app version that includes this feature
|
|
98
|
+
* - showNewUntil: stop showing "new" once appVersion reaches this
|
|
99
|
+
* - deprecatedAt: hide feature for app versions at or above this (optional safety)
|
|
100
|
+
* - showIn: range string, e.g. ">=2.5.0 <3.0.0"
|
|
101
|
+
*/
|
|
102
|
+
version?: string | {
|
|
103
|
+
introduced?: string;
|
|
104
|
+
showNewUntil?: string;
|
|
105
|
+
deprecatedAt?: string;
|
|
106
|
+
showIn?: string;
|
|
107
|
+
};
|
|
108
|
+
/** ISO date when this feature was released */
|
|
109
|
+
releasedAt: string;
|
|
110
|
+
/** ISO date after which the "new" badge should stop showing */
|
|
111
|
+
showNewUntil: string;
|
|
112
|
+
/** Optional key to match navigation items (e.g. "/journal", "settings") */
|
|
113
|
+
sidebarKey?: string;
|
|
114
|
+
/** Optional grouping category (e.g. "ai", "billing", "core") */
|
|
115
|
+
category?: string;
|
|
116
|
+
/** Optional product scope (`"*"`, `"askverdict"`, etc.) for multi-product manifests */
|
|
117
|
+
product?: string;
|
|
118
|
+
/** Optional URL to link to (e.g. docs page, changelog entry) */
|
|
119
|
+
url?: string;
|
|
120
|
+
/** Optional feature flag key; requires a flag bridge to evaluate */
|
|
121
|
+
flagKey?: string;
|
|
122
|
+
/** Entry type — determines default icon/color in UI components */
|
|
123
|
+
type?: FeatureType;
|
|
124
|
+
/** Priority level — critical entries get special treatment in UI */
|
|
125
|
+
priority?: FeaturePriority;
|
|
126
|
+
/** Optional image/screenshot URL */
|
|
127
|
+
image?: string;
|
|
128
|
+
/** Optional call-to-action button */
|
|
129
|
+
cta?: FeatureCTA;
|
|
130
|
+
/** ISO date — entry is hidden until this date (scheduled publishing) */
|
|
131
|
+
publishAt?: string;
|
|
132
|
+
/** Optional arbitrary metadata */
|
|
133
|
+
meta?: Record<string, unknown>;
|
|
134
|
+
/** A/B variants keyed by variant name (e.g. control, treatment_a) */
|
|
135
|
+
variants?: Record<string, FeatureVariant>;
|
|
136
|
+
/** Percentage split per variant (same order as variants object keys) */
|
|
137
|
+
variantSplit?: number[];
|
|
138
|
+
/** Audience targeting — if set, only matching users see this feature */
|
|
139
|
+
audience?: AudienceRule;
|
|
140
|
+
/** Dependency requirements (progressive disclosure sequencing) */
|
|
141
|
+
dependsOn?: FeatureDependencies;
|
|
142
|
+
/** Contextual trigger rule */
|
|
143
|
+
trigger?: FeatureTrigger;
|
|
144
|
+
}
|
|
145
|
+
/** Display format hint from the engine */
|
|
146
|
+
type DisplayFormat = "badge" | "toast" | "modal" | "banner" | "inline" | "spotlight";
|
|
147
|
+
/** Interaction type tracked by the engine */
|
|
148
|
+
type InteractionType = "seen" | "dismissed" | "clicked" | "completed" | "snoozed" | "hovered" | "expanded";
|
|
149
|
+
/** Timing decision returned by the engine */
|
|
150
|
+
interface TimingDecision {
|
|
151
|
+
/** Whether to show the announcement now */
|
|
152
|
+
show: boolean;
|
|
153
|
+
/** Reason for the decision */
|
|
154
|
+
reason: string;
|
|
155
|
+
/** Suggested delay in ms if not showing now */
|
|
156
|
+
delayMs?: number;
|
|
157
|
+
/** Confidence level (0-1) */
|
|
158
|
+
confidence: number;
|
|
159
|
+
}
|
|
160
|
+
/** Format recommendation from the engine */
|
|
161
|
+
interface FormatRecommendation {
|
|
162
|
+
/** Recommended display format */
|
|
163
|
+
primary: DisplayFormat;
|
|
164
|
+
/** Fallback format if primary component isn't used */
|
|
165
|
+
fallback: DisplayFormat;
|
|
166
|
+
/** Reason for the recommendation */
|
|
167
|
+
reason: string;
|
|
168
|
+
}
|
|
169
|
+
/** Adoption score breakdown */
|
|
170
|
+
interface AdoptionScore {
|
|
171
|
+
/** Overall score (0-100) */
|
|
172
|
+
score: number;
|
|
173
|
+
/** Letter grade */
|
|
174
|
+
grade: "A" | "B" | "C" | "D" | "F";
|
|
175
|
+
/** Score breakdown */
|
|
176
|
+
breakdown: {
|
|
177
|
+
/** % of features the user has explored */
|
|
178
|
+
featuresExplored: number;
|
|
179
|
+
/** Rate of dismissals (lower is better) */
|
|
180
|
+
dismissRate: number;
|
|
181
|
+
/** Rate of tour/checklist completion */
|
|
182
|
+
completionRate: number;
|
|
183
|
+
/** Whether engagement is rising, stable, or declining */
|
|
184
|
+
engagementTrend: "rising" | "stable" | "declining";
|
|
185
|
+
};
|
|
186
|
+
/** Actionable recommendations */
|
|
187
|
+
recommendations: string[];
|
|
188
|
+
}
|
|
189
|
+
/** Per-feature adoption status */
|
|
190
|
+
interface FeatureAdoptionStatus {
|
|
191
|
+
featureId: string;
|
|
192
|
+
status: "unseen" | "seen" | "explored" | "adopted" | "dismissed";
|
|
193
|
+
firstSeen?: string;
|
|
194
|
+
lastInteraction?: string;
|
|
195
|
+
interactionCount: number;
|
|
196
|
+
}
|
|
197
|
+
/** Delivery context passed to the engine for timing decisions */
|
|
198
|
+
interface DeliveryContext {
|
|
199
|
+
/** Current route/path */
|
|
200
|
+
currentPath: string;
|
|
201
|
+
/** Seconds since session start */
|
|
202
|
+
sessionAge: number;
|
|
203
|
+
/** Dismissals in last 5 minutes */
|
|
204
|
+
recentDismissals: number;
|
|
205
|
+
/** Feature priority */
|
|
206
|
+
featurePriority: FeaturePriority;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Plugin interface for the FeatureDrop engine.
|
|
210
|
+
*
|
|
211
|
+
* The open-source library defines this interface.
|
|
212
|
+
* The proprietary @featuredrop/engine implements it.
|
|
213
|
+
* Users can also build their own engine implementation.
|
|
214
|
+
*
|
|
215
|
+
* The free library works perfectly without any engine.
|
|
216
|
+
*/
|
|
217
|
+
interface FeatureDropEngine {
|
|
218
|
+
/** Decide whether to show a feature announcement now */
|
|
219
|
+
shouldShow(featureId: string, context: DeliveryContext): TimingDecision;
|
|
220
|
+
/** Recommend the best display format for a feature */
|
|
221
|
+
recommendFormat(featureId: string): FormatRecommendation;
|
|
222
|
+
/** Get the user's overall adoption score */
|
|
223
|
+
getAdoptionScore(): AdoptionScore;
|
|
224
|
+
/** Track a user interaction with a feature */
|
|
225
|
+
trackInteraction(featureId: string, type: InteractionType): void;
|
|
226
|
+
/** Get adoption status for a specific feature */
|
|
227
|
+
getFeatureAdoption(featureId: string): FeatureAdoptionStatus;
|
|
228
|
+
/** Initialize the engine (called by provider on mount) */
|
|
229
|
+
initialize?(): void;
|
|
230
|
+
/** Cleanup resources (called by provider on unmount) */
|
|
231
|
+
destroy?(): void;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Compact behavior profile stored in localStorage */
|
|
235
|
+
interface BehaviorProfile {
|
|
236
|
+
version: 1;
|
|
237
|
+
firstSeen: string;
|
|
238
|
+
sessionCount: number;
|
|
239
|
+
totalInteractions: number;
|
|
240
|
+
dismissCount: number;
|
|
241
|
+
clickCount: number;
|
|
242
|
+
completionCount: number;
|
|
243
|
+
formatPrefs: {
|
|
244
|
+
badge: number;
|
|
245
|
+
toast: number;
|
|
246
|
+
modal: number;
|
|
247
|
+
inline: number;
|
|
248
|
+
banner: number;
|
|
249
|
+
spotlight: number;
|
|
250
|
+
};
|
|
251
|
+
/** 24-element array, interaction count per hour */
|
|
252
|
+
hourlyActivity: number[];
|
|
253
|
+
/** Last 20 dismissed feature IDs (circular buffer) */
|
|
254
|
+
recentDismissals: string[];
|
|
255
|
+
/** Per-feature interaction data */
|
|
256
|
+
featureInteractions: Record<string, {
|
|
257
|
+
seen: number;
|
|
258
|
+
clicked: number;
|
|
259
|
+
dismissed: number;
|
|
260
|
+
completed: number;
|
|
261
|
+
lastInteraction: string;
|
|
262
|
+
}>;
|
|
263
|
+
}
|
|
264
|
+
declare class BehaviorTracker {
|
|
265
|
+
private profile;
|
|
266
|
+
private sessionStartTime;
|
|
267
|
+
constructor();
|
|
268
|
+
/** Track a feature interaction */
|
|
269
|
+
trackInteraction(featureId: string, type: InteractionType): void;
|
|
270
|
+
/** Record a format engagement (user interacted via this format) */
|
|
271
|
+
trackFormatEngagement(format: keyof BehaviorProfile["formatPrefs"]): void;
|
|
272
|
+
/** Get current profile */
|
|
273
|
+
getProfile(): Readonly<BehaviorProfile>;
|
|
274
|
+
/** Session count */
|
|
275
|
+
getSessionCount(): number;
|
|
276
|
+
/** Average session duration (rough estimate based on current session) */
|
|
277
|
+
getSessionAge(): number;
|
|
278
|
+
/** Dismiss rate (0-1) */
|
|
279
|
+
getDismissRate(): number;
|
|
280
|
+
/** Engagement rate (clicked or completed / total interactions) */
|
|
281
|
+
getEngagementRate(): number;
|
|
282
|
+
/** Preferred format based on highest engagement count */
|
|
283
|
+
getPreferredFormat(): keyof BehaviorProfile["formatPrefs"];
|
|
284
|
+
/** Top 3 active hours (0-23) */
|
|
285
|
+
getActiveHours(): number[];
|
|
286
|
+
/** Recent dismissals (last N feature IDs) */
|
|
287
|
+
getRecentDismissals(): string[];
|
|
288
|
+
/** Count of dismissals in last N milliseconds */
|
|
289
|
+
getRecentDismissalCount(windowMs: number): number;
|
|
290
|
+
/** Get interaction data for a specific feature */
|
|
291
|
+
getFeatureInteractions(featureId: string): {
|
|
292
|
+
seen: number;
|
|
293
|
+
clicked: number;
|
|
294
|
+
dismissed: number;
|
|
295
|
+
completed: number;
|
|
296
|
+
lastInteraction: string;
|
|
297
|
+
};
|
|
298
|
+
/** Clear all behavior data */
|
|
299
|
+
clearProfile(): void;
|
|
300
|
+
private load;
|
|
301
|
+
private save;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
interface TimingOptimizerConfig {
|
|
305
|
+
/** Minimum session age in ms before showing anything (default: 10000) */
|
|
306
|
+
sessionGateMs: number;
|
|
307
|
+
/** Max dismissals in the backoff window before backing off (default: 2) */
|
|
308
|
+
maxDismissalsBeforeBackoff: number;
|
|
309
|
+
/** Backoff window in ms to count recent dismissals (default: 180000 = 3 min) */
|
|
310
|
+
dismissBackoffWindowMs: number;
|
|
311
|
+
/** Cooldown between announcements in ms (default: 60000) */
|
|
312
|
+
cooldownMs: number;
|
|
313
|
+
/** Path patterns to exclude (glob-style simple matching) */
|
|
314
|
+
excludePaths: string[];
|
|
315
|
+
}
|
|
316
|
+
declare class TimingOptimizer {
|
|
317
|
+
private config;
|
|
318
|
+
private tracker;
|
|
319
|
+
private lastAnnouncementTime;
|
|
320
|
+
constructor(tracker: BehaviorTracker, config?: Partial<TimingOptimizerConfig>);
|
|
321
|
+
/** Decide whether to show a feature announcement now */
|
|
322
|
+
shouldShowNow(_featureId: string, context: DeliveryContext): TimingDecision;
|
|
323
|
+
/** Mark that an announcement was shown (for cooldown tracking) */
|
|
324
|
+
recordAnnouncementShown(): void;
|
|
325
|
+
private isExcludedPath;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
declare class FormatSelector {
|
|
329
|
+
private tracker;
|
|
330
|
+
constructor(tracker: BehaviorTracker);
|
|
331
|
+
/** Recommend the best display format for a feature */
|
|
332
|
+
recommendFormat(featureId: string, priority: FeaturePriority): FormatRecommendation;
|
|
333
|
+
private getBestFormat;
|
|
334
|
+
private getFallbackFormat;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
declare class AdoptionScorer {
|
|
338
|
+
private tracker;
|
|
339
|
+
constructor(tracker: BehaviorTracker);
|
|
340
|
+
/** Calculate overall adoption score (0-100) */
|
|
341
|
+
getAdoptionScore(manifest: readonly FeatureEntry[]): AdoptionScore;
|
|
342
|
+
/** Get adoption status for a specific feature */
|
|
343
|
+
getFeatureAdoption(featureId: string): FeatureAdoptionStatus;
|
|
344
|
+
private toGrade;
|
|
345
|
+
private detectTrend;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/** Configuration for creating an AdoptionEngine */
|
|
349
|
+
interface AdoptionEngineConfig {
|
|
350
|
+
/** Feature manifest (required for adoption scoring) */
|
|
351
|
+
manifest: readonly FeatureEntry[];
|
|
352
|
+
/** Timing optimizer settings */
|
|
353
|
+
timing?: Partial<TimingOptimizerConfig>;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Client-side behavioral intelligence engine for FeatureDrop.
|
|
357
|
+
*
|
|
358
|
+
* Tracks user interactions, optimizes announcement timing,
|
|
359
|
+
* recommends display formats, and scores feature adoption —
|
|
360
|
+
* all client-side with zero data transfer.
|
|
361
|
+
*
|
|
362
|
+
* @example
|
|
363
|
+
* ```ts
|
|
364
|
+
* import { createAdoptionEngine } from 'featuredrop/engine'
|
|
365
|
+
*
|
|
366
|
+
* const engine = createAdoptionEngine({
|
|
367
|
+
* manifest: features,
|
|
368
|
+
* timing: { cooldownMs: 30_000 },
|
|
369
|
+
* })
|
|
370
|
+
*
|
|
371
|
+
* <FeatureDropProvider manifest={features} engine={engine}>
|
|
372
|
+
* <App />
|
|
373
|
+
* </FeatureDropProvider>
|
|
374
|
+
* ```
|
|
375
|
+
*/
|
|
376
|
+
declare class AdoptionEngine implements FeatureDropEngine {
|
|
377
|
+
private tracker;
|
|
378
|
+
private timing;
|
|
379
|
+
private format;
|
|
380
|
+
private scorer;
|
|
381
|
+
private manifest;
|
|
382
|
+
constructor(config: AdoptionEngineConfig);
|
|
383
|
+
/** Initialize the engine (called by FeatureDropProvider on mount) */
|
|
384
|
+
initialize(): void;
|
|
385
|
+
/** Cleanup resources (called by FeatureDropProvider on unmount) */
|
|
386
|
+
destroy(): void;
|
|
387
|
+
/** Decide whether to show a feature announcement now */
|
|
388
|
+
shouldShow(featureId: string, context: DeliveryContext): TimingDecision;
|
|
389
|
+
/** Recommend the best display format for a feature */
|
|
390
|
+
recommendFormat(featureId: string): FormatRecommendation;
|
|
391
|
+
/** Get the user's overall adoption score */
|
|
392
|
+
getAdoptionScore(): AdoptionScore;
|
|
393
|
+
/** Track a user interaction with a feature */
|
|
394
|
+
trackInteraction(featureId: string, type: InteractionType): void;
|
|
395
|
+
/** Get adoption status for a specific feature */
|
|
396
|
+
getFeatureAdoption(featureId: string): FeatureAdoptionStatus;
|
|
397
|
+
/** Access the behavior tracker for advanced usage */
|
|
398
|
+
getBehaviorTracker(): BehaviorTracker;
|
|
399
|
+
/** Clear all behavior data */
|
|
400
|
+
clearProfile(): void;
|
|
401
|
+
/** Update the manifest (e.g., if features change at runtime) */
|
|
402
|
+
updateManifest(manifest: readonly FeatureEntry[]): void;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Create a new AdoptionEngine instance.
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
* ```ts
|
|
409
|
+
* import { createAdoptionEngine } from 'featuredrop/engine'
|
|
410
|
+
*
|
|
411
|
+
* const engine = createAdoptionEngine({
|
|
412
|
+
* manifest: features,
|
|
413
|
+
* timing: {
|
|
414
|
+
* cooldownMs: 30_000,
|
|
415
|
+
* excludePaths: ['/checkout', '/login'],
|
|
416
|
+
* },
|
|
417
|
+
* })
|
|
418
|
+
* ```
|
|
419
|
+
*/
|
|
420
|
+
declare function createAdoptionEngine(config: AdoptionEngineConfig): AdoptionEngine;
|
|
421
|
+
|
|
422
|
+
export { AdoptionEngine, type AdoptionEngineConfig, AdoptionScorer, type BehaviorProfile, BehaviorTracker, FormatSelector, TimingOptimizer, type TimingOptimizerConfig, createAdoptionEngine };
|