featuredrop 2.6.1 → 2.7.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/preact.d.cts CHANGED
@@ -199,6 +199,94 @@ interface AnalyticsCallbacks {
199
199
  /** Fired when all features are dismissed at once */
200
200
  onAllDismissed?: () => void;
201
201
  }
202
+ /** Display format hint from the engine */
203
+ type DisplayFormat = "badge" | "toast" | "modal" | "banner" | "inline" | "spotlight";
204
+ /** Interaction type tracked by the engine */
205
+ type InteractionType = "seen" | "dismissed" | "clicked" | "completed" | "snoozed" | "hovered" | "expanded";
206
+ /** Timing decision returned by the engine */
207
+ interface TimingDecision {
208
+ /** Whether to show the announcement now */
209
+ show: boolean;
210
+ /** Reason for the decision */
211
+ reason: string;
212
+ /** Suggested delay in ms if not showing now */
213
+ delayMs?: number;
214
+ /** Confidence level (0-1) */
215
+ confidence: number;
216
+ }
217
+ /** Format recommendation from the engine */
218
+ interface FormatRecommendation {
219
+ /** Recommended display format */
220
+ primary: DisplayFormat;
221
+ /** Fallback format if primary component isn't used */
222
+ fallback: DisplayFormat;
223
+ /** Reason for the recommendation */
224
+ reason: string;
225
+ }
226
+ /** Adoption score breakdown */
227
+ interface AdoptionScore {
228
+ /** Overall score (0-100) */
229
+ score: number;
230
+ /** Letter grade */
231
+ grade: "A" | "B" | "C" | "D" | "F";
232
+ /** Score breakdown */
233
+ breakdown: {
234
+ /** % of features the user has explored */
235
+ featuresExplored: number;
236
+ /** Rate of dismissals (lower is better) */
237
+ dismissRate: number;
238
+ /** Rate of tour/checklist completion */
239
+ completionRate: number;
240
+ /** Whether engagement is rising, stable, or declining */
241
+ engagementTrend: "rising" | "stable" | "declining";
242
+ };
243
+ /** Actionable recommendations */
244
+ recommendations: string[];
245
+ }
246
+ /** Per-feature adoption status */
247
+ interface FeatureAdoptionStatus {
248
+ featureId: string;
249
+ status: "unseen" | "seen" | "explored" | "adopted" | "dismissed";
250
+ firstSeen?: string;
251
+ lastInteraction?: string;
252
+ interactionCount: number;
253
+ }
254
+ /** Delivery context passed to the engine for timing decisions */
255
+ interface DeliveryContext {
256
+ /** Current route/path */
257
+ currentPath: string;
258
+ /** Seconds since session start */
259
+ sessionAge: number;
260
+ /** Dismissals in last 5 minutes */
261
+ recentDismissals: number;
262
+ /** Feature priority */
263
+ featurePriority: FeaturePriority;
264
+ }
265
+ /**
266
+ * Plugin interface for the FeatureDrop engine.
267
+ *
268
+ * The open-source library defines this interface.
269
+ * The proprietary @featuredrop/engine implements it.
270
+ * Users can also build their own engine implementation.
271
+ *
272
+ * The free library works perfectly without any engine.
273
+ */
274
+ interface FeatureDropEngine {
275
+ /** Decide whether to show a feature announcement now */
276
+ shouldShow(featureId: string, context: DeliveryContext): TimingDecision;
277
+ /** Recommend the best display format for a feature */
278
+ recommendFormat(featureId: string): FormatRecommendation;
279
+ /** Get the user's overall adoption score */
280
+ getAdoptionScore(): AdoptionScore;
281
+ /** Track a user interaction with a feature */
282
+ trackInteraction(featureId: string, type: InteractionType): void;
283
+ /** Get adoption status for a specific feature */
284
+ getFeatureAdoption(featureId: string): FeatureAdoptionStatus;
285
+ /** Initialize the engine (called by provider on mount) */
286
+ initialize?(): void;
287
+ /** Cleanup resources (called by provider on unmount) */
288
+ destroy?(): void;
289
+ }
202
290
 
203
291
  interface ThrottleOptions {
204
292
  maxSimultaneousBadges?: number;
@@ -340,6 +428,8 @@ interface FeatureDropProviderProps {
340
428
  animation?: FeatureDropAnimationPreset;
341
429
  /** Custom translation overrides for built-in component strings */
342
430
  translations?: Partial<FeatureDropTranslations>;
431
+ /** Optional engine for AI-powered delivery intelligence (@featuredrop/engine) */
432
+ engine?: FeatureDropEngine;
343
433
  children: ReactNode;
344
434
  }
345
435
  /**
@@ -348,7 +438,7 @@ interface FeatureDropProviderProps {
348
438
  * Wrap your app (or a subtree) with this provider to enable
349
439
  * `useFeatureDrop`, `useNewFeature`, `useNewCount`, and other hooks.
350
440
  */
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;
441
+ declare function FeatureDropProvider({ manifest, storage, analytics, onError, userContext, matchAudience: matchAudienceFn, appVersion, product, throttle, variantKey, collector, flagBridge, locale, animation, translations: translationOverrides, engine, children, }: FeatureDropProviderProps): react_jsx_runtime.JSX.Element;
352
442
 
353
443
  interface FeatureDropTheme {
354
444
  colors: {
@@ -483,6 +573,8 @@ interface FeatureDropContextValue {
483
573
  trackMilestone: (event: string) => void;
484
574
  /** Manually override current path for page trigger rules */
485
575
  setTriggerPath: (path: string) => void;
576
+ /** Optional engine instance for AI-powered delivery intelligence */
577
+ engine: FeatureDropEngine | null;
486
578
  }
487
579
  declare const FeatureDropContext: react.Context<FeatureDropContextValue | null>;
488
580
 
package/dist/preact.d.ts CHANGED
@@ -199,6 +199,94 @@ interface AnalyticsCallbacks {
199
199
  /** Fired when all features are dismissed at once */
200
200
  onAllDismissed?: () => void;
201
201
  }
202
+ /** Display format hint from the engine */
203
+ type DisplayFormat = "badge" | "toast" | "modal" | "banner" | "inline" | "spotlight";
204
+ /** Interaction type tracked by the engine */
205
+ type InteractionType = "seen" | "dismissed" | "clicked" | "completed" | "snoozed" | "hovered" | "expanded";
206
+ /** Timing decision returned by the engine */
207
+ interface TimingDecision {
208
+ /** Whether to show the announcement now */
209
+ show: boolean;
210
+ /** Reason for the decision */
211
+ reason: string;
212
+ /** Suggested delay in ms if not showing now */
213
+ delayMs?: number;
214
+ /** Confidence level (0-1) */
215
+ confidence: number;
216
+ }
217
+ /** Format recommendation from the engine */
218
+ interface FormatRecommendation {
219
+ /** Recommended display format */
220
+ primary: DisplayFormat;
221
+ /** Fallback format if primary component isn't used */
222
+ fallback: DisplayFormat;
223
+ /** Reason for the recommendation */
224
+ reason: string;
225
+ }
226
+ /** Adoption score breakdown */
227
+ interface AdoptionScore {
228
+ /** Overall score (0-100) */
229
+ score: number;
230
+ /** Letter grade */
231
+ grade: "A" | "B" | "C" | "D" | "F";
232
+ /** Score breakdown */
233
+ breakdown: {
234
+ /** % of features the user has explored */
235
+ featuresExplored: number;
236
+ /** Rate of dismissals (lower is better) */
237
+ dismissRate: number;
238
+ /** Rate of tour/checklist completion */
239
+ completionRate: number;
240
+ /** Whether engagement is rising, stable, or declining */
241
+ engagementTrend: "rising" | "stable" | "declining";
242
+ };
243
+ /** Actionable recommendations */
244
+ recommendations: string[];
245
+ }
246
+ /** Per-feature adoption status */
247
+ interface FeatureAdoptionStatus {
248
+ featureId: string;
249
+ status: "unseen" | "seen" | "explored" | "adopted" | "dismissed";
250
+ firstSeen?: string;
251
+ lastInteraction?: string;
252
+ interactionCount: number;
253
+ }
254
+ /** Delivery context passed to the engine for timing decisions */
255
+ interface DeliveryContext {
256
+ /** Current route/path */
257
+ currentPath: string;
258
+ /** Seconds since session start */
259
+ sessionAge: number;
260
+ /** Dismissals in last 5 minutes */
261
+ recentDismissals: number;
262
+ /** Feature priority */
263
+ featurePriority: FeaturePriority;
264
+ }
265
+ /**
266
+ * Plugin interface for the FeatureDrop engine.
267
+ *
268
+ * The open-source library defines this interface.
269
+ * The proprietary @featuredrop/engine implements it.
270
+ * Users can also build their own engine implementation.
271
+ *
272
+ * The free library works perfectly without any engine.
273
+ */
274
+ interface FeatureDropEngine {
275
+ /** Decide whether to show a feature announcement now */
276
+ shouldShow(featureId: string, context: DeliveryContext): TimingDecision;
277
+ /** Recommend the best display format for a feature */
278
+ recommendFormat(featureId: string): FormatRecommendation;
279
+ /** Get the user's overall adoption score */
280
+ getAdoptionScore(): AdoptionScore;
281
+ /** Track a user interaction with a feature */
282
+ trackInteraction(featureId: string, type: InteractionType): void;
283
+ /** Get adoption status for a specific feature */
284
+ getFeatureAdoption(featureId: string): FeatureAdoptionStatus;
285
+ /** Initialize the engine (called by provider on mount) */
286
+ initialize?(): void;
287
+ /** Cleanup resources (called by provider on unmount) */
288
+ destroy?(): void;
289
+ }
202
290
 
203
291
  interface ThrottleOptions {
204
292
  maxSimultaneousBadges?: number;
@@ -340,6 +428,8 @@ interface FeatureDropProviderProps {
340
428
  animation?: FeatureDropAnimationPreset;
341
429
  /** Custom translation overrides for built-in component strings */
342
430
  translations?: Partial<FeatureDropTranslations>;
431
+ /** Optional engine for AI-powered delivery intelligence (@featuredrop/engine) */
432
+ engine?: FeatureDropEngine;
343
433
  children: ReactNode;
344
434
  }
345
435
  /**
@@ -348,7 +438,7 @@ interface FeatureDropProviderProps {
348
438
  * Wrap your app (or a subtree) with this provider to enable
349
439
  * `useFeatureDrop`, `useNewFeature`, `useNewCount`, and other hooks.
350
440
  */
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;
441
+ declare function FeatureDropProvider({ manifest, storage, analytics, onError, userContext, matchAudience: matchAudienceFn, appVersion, product, throttle, variantKey, collector, flagBridge, locale, animation, translations: translationOverrides, engine, children, }: FeatureDropProviderProps): react_jsx_runtime.JSX.Element;
352
442
 
353
443
  interface FeatureDropTheme {
354
444
  colors: {
@@ -483,6 +573,8 @@ interface FeatureDropContextValue {
483
573
  trackMilestone: (event: string) => void;
484
574
  /** Manually override current path for page trigger rules */
485
575
  setTriggerPath: (path: string) => void;
576
+ /** Optional engine instance for AI-powered delivery intelligence */
577
+ engine: FeatureDropEngine | null;
486
578
  }
487
579
  declare const FeatureDropContext: react.Context<FeatureDropContextValue | null>;
488
580
 
package/dist/preact.js CHANGED
@@ -1076,6 +1076,7 @@ function FeatureDropProvider({
1076
1076
  locale = "en",
1077
1077
  animation = "normal",
1078
1078
  translations: translationOverrides,
1079
+ engine,
1079
1080
  children
1080
1081
  }) {
1081
1082
  const analyticsRef = useRef(analytics);
@@ -1132,20 +1133,20 @@ function FeatureDropProvider({
1132
1133
  seenFeatureIds: readIdSet(SEEN_FEATURES_STORAGE_KEY),
1133
1134
  clickedFeatureIds: readIdSet(CLICKED_FEATURES_STORAGE_KEY),
1134
1135
  triggerContext: (() => {
1135
- const engine = triggerEngineRef.current;
1136
- if (!engine) return void 0;
1137
- engine.setElapsedMs(Date.now() - sessionStartedAtRef.current);
1138
- return engine.getContext();
1136
+ const engine2 = triggerEngineRef.current;
1137
+ if (!engine2) return void 0;
1138
+ engine2.setElapsedMs(Date.now() - sessionStartedAtRef.current);
1139
+ return engine2.getContext();
1139
1140
  })(),
1140
1141
  flagBridge
1141
1142
  })
1142
1143
  );
1143
1144
  const recompute = useCallback(() => {
1144
- const engine = triggerEngineRef.current;
1145
+ const engine2 = triggerEngineRef.current;
1145
1146
  let triggerContext;
1146
- if (engine) {
1147
- engine.setElapsedMs(Date.now() - sessionStartedAtRef.current);
1148
- triggerContext = engine.getContext();
1147
+ if (engine2) {
1148
+ engine2.setElapsedMs(Date.now() - sessionStartedAtRef.current);
1149
+ triggerContext = engine2.getContext();
1149
1150
  }
1150
1151
  setFeatureState(
1151
1152
  computeFeatureState({
@@ -1182,6 +1183,12 @@ function FeatureDropProvider({
1182
1183
  useEffect(() => {
1183
1184
  recompute();
1184
1185
  }, [recompute]);
1186
+ useEffect(() => {
1187
+ engine?.initialize?.();
1188
+ return () => {
1189
+ engine?.destroy?.();
1190
+ };
1191
+ }, [engine]);
1185
1192
  const hasTimeTriggers = useMemo(
1186
1193
  () => resolvedManifest.some((feature) => feature.trigger?.type === "time"),
1187
1194
  [resolvedManifest]
@@ -1464,7 +1471,8 @@ function FeatureDropProvider({
1464
1471
  trackUsageEvent,
1465
1472
  trackTriggerEvent,
1466
1473
  trackMilestone,
1467
- setTriggerPath
1474
+ setTriggerPath,
1475
+ engine: engine ?? null
1468
1476
  }),
1469
1477
  [
1470
1478
  resolvedManifest,
@@ -1498,7 +1506,8 @@ function FeatureDropProvider({
1498
1506
  trackUsageEvent,
1499
1507
  trackTriggerEvent,
1500
1508
  trackMilestone,
1501
- setTriggerPath
1509
+ setTriggerPath,
1510
+ engine
1502
1511
  ]
1503
1512
  );
1504
1513
  return /* @__PURE__ */ jsx(FeatureDropContext.Provider, { value, children });