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/.claude-plugin/plugin.json +21 -0
- package/README.md +77 -11
- package/context7.json +15 -0
- package/dist/index.d.cts +89 -1
- package/dist/index.d.ts +89 -1
- package/dist/preact.cjs +19 -10
- package/dist/preact.cjs.map +1 -1
- package/dist/preact.d.cts +93 -1
- package/dist/preact.d.ts +93 -1
- package/dist/preact.js +19 -10
- package/dist/preact.js.map +1 -1
- package/dist/react-hooks.cjs +472 -0
- package/dist/react-hooks.cjs.map +1 -0
- package/dist/react-hooks.d.cts +540 -0
- package/dist/react-hooks.d.ts +540 -0
- package/dist/react-hooks.js +461 -0
- package/dist/react-hooks.js.map +1 -0
- package/dist/react.cjs +19 -10
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +93 -1
- package/dist/react.d.ts +93 -1
- package/dist/react.js +19 -10
- package/dist/react.js.map +1 -1
- package/dist/tailwind.cjs +148 -0
- package/dist/tailwind.cjs.map +1 -0
- package/dist/tailwind.d.cts +38 -0
- package/dist/tailwind.d.ts +38 -0
- package/dist/tailwind.js +146 -0
- package/dist/tailwind.js.map +1 -0
- package/dist/testing.cjs +19 -10
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +90 -0
- package/dist/testing.d.ts +90 -0
- package/dist/testing.js +19 -10
- package/dist/testing.js.map +1 -1
- package/package.json +32 -1
- package/skills/featuredrop-setup/SKILL.md +124 -0
- package/src/ai/claude-skill.md +109 -0
- package/src/ai/cursorrules.txt +13 -0
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
|
|
1137
|
-
if (!
|
|
1138
|
-
|
|
1139
|
-
return
|
|
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
|
|
1146
|
+
const engine2 = triggerEngineRef.current;
|
|
1146
1147
|
let triggerContext;
|
|
1147
|
-
if (
|
|
1148
|
-
|
|
1149
|
-
triggerContext =
|
|
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 });
|