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/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
|
|
1136
|
-
if (!
|
|
1137
|
-
|
|
1138
|
-
return
|
|
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
|
|
1145
|
+
const engine2 = triggerEngineRef.current;
|
|
1145
1146
|
let triggerContext;
|
|
1146
|
-
if (
|
|
1147
|
-
|
|
1148
|
-
triggerContext =
|
|
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 });
|