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/react.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/react.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/react.js CHANGED
@@ -1077,6 +1077,7 @@ function FeatureDropProvider({
1077
1077
  locale = "en",
1078
1078
  animation = "normal",
1079
1079
  translations: translationOverrides,
1080
+ engine,
1080
1081
  children
1081
1082
  }) {
1082
1083
  const analyticsRef = useRef(analytics);
@@ -1133,20 +1134,20 @@ function FeatureDropProvider({
1133
1134
  seenFeatureIds: readIdSet(SEEN_FEATURES_STORAGE_KEY),
1134
1135
  clickedFeatureIds: readIdSet(CLICKED_FEATURES_STORAGE_KEY),
1135
1136
  triggerContext: (() => {
1136
- const engine = triggerEngineRef.current;
1137
- if (!engine) return void 0;
1138
- engine.setElapsedMs(Date.now() - sessionStartedAtRef.current);
1139
- return engine.getContext();
1137
+ const engine2 = triggerEngineRef.current;
1138
+ if (!engine2) return void 0;
1139
+ engine2.setElapsedMs(Date.now() - sessionStartedAtRef.current);
1140
+ return engine2.getContext();
1140
1141
  })(),
1141
1142
  flagBridge
1142
1143
  })
1143
1144
  );
1144
1145
  const recompute = useCallback(() => {
1145
- const engine = triggerEngineRef.current;
1146
+ const engine2 = triggerEngineRef.current;
1146
1147
  let triggerContext;
1147
- if (engine) {
1148
- engine.setElapsedMs(Date.now() - sessionStartedAtRef.current);
1149
- triggerContext = engine.getContext();
1148
+ if (engine2) {
1149
+ engine2.setElapsedMs(Date.now() - sessionStartedAtRef.current);
1150
+ triggerContext = engine2.getContext();
1150
1151
  }
1151
1152
  setFeatureState(
1152
1153
  computeFeatureState({
@@ -1183,6 +1184,12 @@ function FeatureDropProvider({
1183
1184
  useEffect(() => {
1184
1185
  recompute();
1185
1186
  }, [recompute]);
1187
+ useEffect(() => {
1188
+ engine?.initialize?.();
1189
+ return () => {
1190
+ engine?.destroy?.();
1191
+ };
1192
+ }, [engine]);
1186
1193
  const hasTimeTriggers = useMemo(
1187
1194
  () => resolvedManifest.some((feature) => feature.trigger?.type === "time"),
1188
1195
  [resolvedManifest]
@@ -1465,7 +1472,8 @@ function FeatureDropProvider({
1465
1472
  trackUsageEvent,
1466
1473
  trackTriggerEvent,
1467
1474
  trackMilestone,
1468
- setTriggerPath
1475
+ setTriggerPath,
1476
+ engine: engine ?? null
1469
1477
  }),
1470
1478
  [
1471
1479
  resolvedManifest,
@@ -1499,7 +1507,8 @@ function FeatureDropProvider({
1499
1507
  trackUsageEvent,
1500
1508
  trackTriggerEvent,
1501
1509
  trackMilestone,
1502
- setTriggerPath
1510
+ setTriggerPath,
1511
+ engine
1503
1512
  ]
1504
1513
  );
1505
1514
  return /* @__PURE__ */ jsx(FeatureDropContext.Provider, { value, children });