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.
Files changed (52) hide show
  1. package/README.md +34 -1
  2. package/dist/astro.cjs +333 -0
  3. package/dist/astro.cjs.map +1 -0
  4. package/dist/astro.d.cts +242 -0
  5. package/dist/astro.d.ts +242 -0
  6. package/dist/astro.js +329 -0
  7. package/dist/astro.js.map +1 -0
  8. package/dist/engine.cjs +552 -0
  9. package/dist/engine.cjs.map +1 -0
  10. package/dist/engine.d.cts +422 -0
  11. package/dist/engine.d.ts +422 -0
  12. package/dist/engine.js +545 -0
  13. package/dist/engine.js.map +1 -0
  14. package/dist/featuredrop.cjs +208 -1
  15. package/dist/featuredrop.cjs.map +1 -1
  16. package/dist/next.cjs +336 -0
  17. package/dist/next.cjs.map +1 -0
  18. package/dist/next.d.cts +243 -0
  19. package/dist/next.d.ts +243 -0
  20. package/dist/next.js +332 -0
  21. package/dist/next.js.map +1 -0
  22. package/dist/nuxt.cjs +352 -0
  23. package/dist/nuxt.cjs.map +1 -0
  24. package/dist/nuxt.d.cts +282 -0
  25. package/dist/nuxt.d.ts +282 -0
  26. package/dist/nuxt.js +347 -0
  27. package/dist/nuxt.js.map +1 -0
  28. package/dist/preact.cjs +354 -0
  29. package/dist/preact.cjs.map +1 -1
  30. package/dist/preact.d.cts +170 -1
  31. package/dist/preact.d.ts +170 -1
  32. package/dist/preact.js +350 -1
  33. package/dist/preact.js.map +1 -1
  34. package/dist/react-hooks.cjs +82 -0
  35. package/dist/react-hooks.cjs.map +1 -1
  36. package/dist/react-hooks.d.cts +117 -1
  37. package/dist/react-hooks.d.ts +117 -1
  38. package/dist/react-hooks.js +80 -1
  39. package/dist/react-hooks.js.map +1 -1
  40. package/dist/react.cjs +354 -0
  41. package/dist/react.cjs.map +1 -1
  42. package/dist/react.d.cts +170 -1
  43. package/dist/react.d.ts +170 -1
  44. package/dist/react.js +350 -1
  45. package/dist/react.js.map +1 -1
  46. package/dist/remix.cjs +331 -0
  47. package/dist/remix.cjs.map +1 -0
  48. package/dist/remix.d.cts +305 -0
  49. package/dist/remix.d.ts +305 -0
  50. package/dist/remix.js +327 -0
  51. package/dist/remix.js.map +1 -0
  52. package/package.json +70 -2
package/dist/preact.js CHANGED
@@ -2221,6 +2221,111 @@ function useSurvey(id) {
2221
2221
  [askLater, hide, show, snapshot]
2222
2222
  );
2223
2223
  }
2224
+ function useChangelog() {
2225
+ const ctx = useFeatureDrop();
2226
+ const markAllSeen = useCallback(() => {
2227
+ void ctx.dismissAll();
2228
+ }, [ctx]);
2229
+ const getByCategory = useCallback(
2230
+ (category) => {
2231
+ return ctx.newFeatures.filter((f) => f.category === category);
2232
+ },
2233
+ [ctx.newFeatures]
2234
+ );
2235
+ return useMemo(
2236
+ () => ({
2237
+ features: ctx.manifest,
2238
+ newFeatures: ctx.newFeatures,
2239
+ newCount: ctx.newCount,
2240
+ newFeaturesSorted: ctx.newFeaturesSorted,
2241
+ dismiss: ctx.dismiss,
2242
+ dismissAll: () => void ctx.dismissAll(),
2243
+ isNew: ctx.isNew,
2244
+ markAllSeen,
2245
+ getByCategory
2246
+ }),
2247
+ [ctx.manifest, ctx.newFeatures, ctx.newCount, ctx.newFeaturesSorted, ctx.dismiss, ctx.dismissAll, ctx.isNew, markAllSeen, getByCategory]
2248
+ );
2249
+ }
2250
+ function useSmartFeature(featureId) {
2251
+ const { engine, manifest, dismiss: providerDismiss } = useFeatureDrop();
2252
+ const sessionStartRef = useRef(Date.now());
2253
+ const feature = manifest.find((f) => f.id === featureId);
2254
+ const dismiss = useCallback(() => {
2255
+ engine?.trackInteraction(featureId, "dismissed");
2256
+ providerDismiss(featureId);
2257
+ }, [engine, featureId, providerDismiss]);
2258
+ if (!engine) {
2259
+ return {
2260
+ show: !!feature,
2261
+ format: "badge",
2262
+ fallbackFormat: "inline",
2263
+ feature,
2264
+ dismiss,
2265
+ confidence: 1,
2266
+ reason: "no_engine"
2267
+ };
2268
+ }
2269
+ const currentPath = typeof window !== "undefined" ? window.location.pathname : "/";
2270
+ const sessionAge = (Date.now() - sessionStartRef.current) / 1e3;
2271
+ const timing = engine.shouldShow(featureId, {
2272
+ currentPath,
2273
+ sessionAge,
2274
+ recentDismissals: 0,
2275
+ featurePriority: feature?.priority ?? "normal"
2276
+ });
2277
+ const formatRec = engine.recommendFormat(featureId);
2278
+ return {
2279
+ show: timing.show,
2280
+ format: formatRec.primary,
2281
+ fallbackFormat: formatRec.fallback,
2282
+ feature,
2283
+ dismiss,
2284
+ confidence: timing.confidence,
2285
+ reason: timing.reason
2286
+ };
2287
+ }
2288
+ var DEFAULT_SCORE = {
2289
+ score: 100,
2290
+ grade: "A",
2291
+ breakdown: {
2292
+ featuresExplored: 0,
2293
+ dismissRate: 0,
2294
+ completionRate: 0,
2295
+ engagementTrend: "stable"
2296
+ },
2297
+ recommendations: []
2298
+ };
2299
+ function useAdoptionScore() {
2300
+ const { engine } = useFeatureDrop();
2301
+ return useMemo(() => {
2302
+ if (!engine) return DEFAULT_SCORE;
2303
+ return engine.getAdoptionScore();
2304
+ }, [engine]);
2305
+ }
2306
+ var DEFAULT_PROFILE = {
2307
+ sessionCount: 0,
2308
+ dismissRate: 0,
2309
+ engagementRate: 0,
2310
+ preferredFormat: "badge",
2311
+ hasEngine: false
2312
+ };
2313
+ function useBehaviorProfile() {
2314
+ const { engine } = useFeatureDrop();
2315
+ return useMemo(() => {
2316
+ if (!engine) return DEFAULT_PROFILE;
2317
+ const score = engine.getAdoptionScore();
2318
+ return {
2319
+ sessionCount: 0,
2320
+ // Not directly exposed by FeatureDropEngine interface
2321
+ dismissRate: score.breakdown.dismissRate,
2322
+ engagementRate: 1 - score.breakdown.dismissRate,
2323
+ preferredFormat: "badge",
2324
+ // Default — full profile requires AdoptionEngine
2325
+ hasEngine: true
2326
+ };
2327
+ }, [engine]);
2328
+ }
2224
2329
  var FeatureDropComponentBoundary = class extends Component {
2225
2330
  state = { hasError: false };
2226
2331
  componentDidCatch(error, info) {
@@ -7750,6 +7855,249 @@ function FeatureRequestForm({
7750
7855
  }
7751
7856
  );
7752
7857
  }
7858
+ var badgeStyles = {
7859
+ display: "inline-flex",
7860
+ alignItems: "center",
7861
+ justifyContent: "center",
7862
+ padding: "2px 6px",
7863
+ borderRadius: "9999px",
7864
+ fontSize: "var(--featuredrop-font-size, 10px)",
7865
+ fontWeight: 700,
7866
+ textTransform: "uppercase",
7867
+ letterSpacing: "0.05em",
7868
+ lineHeight: 1,
7869
+ color: "var(--featuredrop-color, #b45309)",
7870
+ backgroundColor: "var(--featuredrop-bg, rgba(245, 158, 11, 0.15))",
7871
+ fontFamily: "inherit"
7872
+ };
7873
+ var toastStyles2 = {
7874
+ position: "fixed",
7875
+ bottom: 16,
7876
+ right: 16,
7877
+ zIndex: 9999,
7878
+ maxWidth: 360,
7879
+ padding: "12px 16px",
7880
+ borderRadius: "var(--featuredrop-toast-radius, 8px)",
7881
+ backgroundColor: "var(--featuredrop-toast-bg, white)",
7882
+ color: "var(--featuredrop-toast-color, #1f2937)",
7883
+ boxShadow: "var(--featuredrop-toast-shadow, 0 4px 12px rgba(0, 0, 0, 0.15))",
7884
+ border: "1px solid var(--featuredrop-toast-border, #e5e7eb)",
7885
+ fontFamily: "inherit",
7886
+ fontSize: 14,
7887
+ lineHeight: 1.5
7888
+ };
7889
+ var bannerStyles = {
7890
+ width: "100%",
7891
+ padding: "10px 16px",
7892
+ backgroundColor: "var(--featuredrop-banner-bg, #eff6ff)",
7893
+ borderBottom: "1px solid var(--featuredrop-banner-border, #bfdbfe)",
7894
+ color: "var(--featuredrop-banner-color, #1e40af)",
7895
+ fontFamily: "inherit",
7896
+ fontSize: 14,
7897
+ lineHeight: 1.5,
7898
+ display: "flex",
7899
+ alignItems: "center",
7900
+ justifyContent: "space-between"
7901
+ };
7902
+ var inlineStyles = {
7903
+ display: "inline",
7904
+ color: "var(--featuredrop-inline-color, #6b7280)",
7905
+ fontFamily: "inherit",
7906
+ fontSize: 13
7907
+ };
7908
+ var dismissButtonStyles = {
7909
+ background: "none",
7910
+ border: "none",
7911
+ cursor: "pointer",
7912
+ padding: "4px",
7913
+ fontSize: 16,
7914
+ lineHeight: 1,
7915
+ color: "inherit",
7916
+ opacity: 0.6
7917
+ };
7918
+ function SmartAnnouncement({
7919
+ id,
7920
+ format: formatOverride,
7921
+ className,
7922
+ style,
7923
+ children
7924
+ }) {
7925
+ const smartFeature = useSmartFeature(id);
7926
+ const { engine } = useFeatureDrop();
7927
+ const hasTrackedSeen = useRef(false);
7928
+ const resolvedFormat = formatOverride ?? smartFeature.format;
7929
+ useEffect(() => {
7930
+ ensureFeatureDropAnimationStyles();
7931
+ }, []);
7932
+ useEffect(() => {
7933
+ if (smartFeature.show && !hasTrackedSeen.current) {
7934
+ hasTrackedSeen.current = true;
7935
+ engine?.trackInteraction(id, "seen");
7936
+ }
7937
+ }, [smartFeature.show, engine, id]);
7938
+ if (children) {
7939
+ return /* @__PURE__ */ jsx(Fragment, { children: children({
7940
+ show: smartFeature.show,
7941
+ format: resolvedFormat,
7942
+ fallbackFormat: smartFeature.fallbackFormat,
7943
+ feature: smartFeature.feature,
7944
+ dismiss: smartFeature.dismiss,
7945
+ confidence: smartFeature.confidence,
7946
+ reason: smartFeature.reason
7947
+ }) });
7948
+ }
7949
+ if (!smartFeature.show || !smartFeature.feature) return null;
7950
+ const feature = smartFeature.feature;
7951
+ const description = parseDescription(feature.description ?? "");
7952
+ switch (resolvedFormat) {
7953
+ case "badge":
7954
+ return /* @__PURE__ */ jsx(
7955
+ "span",
7956
+ {
7957
+ "data-featuredrop": "smart-badge",
7958
+ className,
7959
+ style: { ...badgeStyles, ...style },
7960
+ role: "status",
7961
+ "aria-label": `New: ${feature.label}`,
7962
+ children: "New"
7963
+ }
7964
+ );
7965
+ case "toast":
7966
+ return /* @__PURE__ */ jsx(
7967
+ "div",
7968
+ {
7969
+ "data-featuredrop": "smart-toast",
7970
+ className,
7971
+ style: {
7972
+ ...toastStyles2,
7973
+ animation: getEnterAnimation("normal", "toast") ?? void 0,
7974
+ ...style
7975
+ },
7976
+ role: "alert",
7977
+ "aria-live": "polite",
7978
+ children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 8 }, children: [
7979
+ /* @__PURE__ */ jsxs("div", { children: [
7980
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 600, marginBottom: 2 }, children: feature.label }),
7981
+ /* @__PURE__ */ jsx(
7982
+ "div",
7983
+ {
7984
+ style: { fontSize: 13, opacity: 0.8 },
7985
+ dangerouslySetInnerHTML: { __html: description }
7986
+ }
7987
+ )
7988
+ ] }),
7989
+ /* @__PURE__ */ jsx(
7990
+ "button",
7991
+ {
7992
+ onClick: smartFeature.dismiss,
7993
+ style: dismissButtonStyles,
7994
+ "aria-label": "Dismiss",
7995
+ type: "button",
7996
+ children: "\xD7"
7997
+ }
7998
+ )
7999
+ ] })
8000
+ }
8001
+ );
8002
+ case "banner":
8003
+ return /* @__PURE__ */ jsxs(
8004
+ "div",
8005
+ {
8006
+ "data-featuredrop": "smart-banner",
8007
+ className,
8008
+ style: { ...bannerStyles, ...style },
8009
+ role: "alert",
8010
+ children: [
8011
+ /* @__PURE__ */ jsxs("span", { children: [
8012
+ /* @__PURE__ */ jsx("strong", { children: feature.label }),
8013
+ feature.description ? ` \u2014 ${feature.description}` : ""
8014
+ ] }),
8015
+ /* @__PURE__ */ jsx(
8016
+ "button",
8017
+ {
8018
+ onClick: smartFeature.dismiss,
8019
+ style: dismissButtonStyles,
8020
+ "aria-label": "Dismiss",
8021
+ type: "button",
8022
+ children: "\xD7"
8023
+ }
8024
+ )
8025
+ ]
8026
+ }
8027
+ );
8028
+ case "inline":
8029
+ return /* @__PURE__ */ jsx(
8030
+ "span",
8031
+ {
8032
+ "data-featuredrop": "smart-inline",
8033
+ className,
8034
+ style: { ...inlineStyles, ...style },
8035
+ children: feature.label
8036
+ }
8037
+ );
8038
+ case "modal":
8039
+ return /* @__PURE__ */ jsx(
8040
+ "div",
8041
+ {
8042
+ "data-featuredrop": "smart-toast",
8043
+ className,
8044
+ style: {
8045
+ ...toastStyles2,
8046
+ animation: getEnterAnimation("normal", "toast") ?? void 0,
8047
+ ...style
8048
+ },
8049
+ role: "alert",
8050
+ "aria-live": "polite",
8051
+ children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 8 }, children: [
8052
+ /* @__PURE__ */ jsxs("div", { children: [
8053
+ /* @__PURE__ */ jsx("div", { style: { fontWeight: 600, marginBottom: 2 }, children: feature.label }),
8054
+ /* @__PURE__ */ jsx(
8055
+ "div",
8056
+ {
8057
+ style: { fontSize: 13, opacity: 0.8 },
8058
+ dangerouslySetInnerHTML: { __html: description }
8059
+ }
8060
+ )
8061
+ ] }),
8062
+ /* @__PURE__ */ jsx(
8063
+ "button",
8064
+ {
8065
+ onClick: smartFeature.dismiss,
8066
+ style: dismissButtonStyles,
8067
+ "aria-label": "Dismiss",
8068
+ type: "button",
8069
+ children: "\xD7"
8070
+ }
8071
+ )
8072
+ ] })
8073
+ }
8074
+ );
8075
+ case "spotlight":
8076
+ return /* @__PURE__ */ jsx(
8077
+ "span",
8078
+ {
8079
+ "data-featuredrop": "smart-badge",
8080
+ className,
8081
+ style: { ...badgeStyles, ...style },
8082
+ role: "status",
8083
+ "aria-label": `New: ${feature.label}`,
8084
+ children: "New"
8085
+ }
8086
+ );
8087
+ default:
8088
+ return /* @__PURE__ */ jsx(
8089
+ "span",
8090
+ {
8091
+ "data-featuredrop": "smart-badge",
8092
+ className,
8093
+ style: { ...badgeStyles, ...style },
8094
+ role: "status",
8095
+ "aria-label": `New: ${feature.label}`,
8096
+ children: "New"
8097
+ }
8098
+ );
8099
+ }
8100
+ }
7753
8101
 
7754
8102
  // src/react/index.ts
7755
8103
  var NewBadge2 = withFeatureDropBoundary(NewBadge, "NewBadge");
@@ -7768,7 +8116,8 @@ var SpotlightChain2 = withFeatureDropBoundary(SpotlightChain, "SpotlightChain");
7768
8116
  var Survey2 = withFeatureDropBoundary(Survey, "Survey");
7769
8117
  var FeatureRequestButton2 = withFeatureDropBoundary(FeatureRequestButton, "FeatureRequestButton");
7770
8118
  var FeatureRequestForm2 = withFeatureDropBoundary(FeatureRequestForm, "FeatureRequestForm");
8119
+ var SmartAnnouncement2 = withFeatureDropBoundary(SmartAnnouncement, "SmartAnnouncement");
7771
8120
 
7772
- export { AnnouncementModal2 as AnnouncementModal, Banner2 as Banner, ChangelogPage2 as ChangelogPage, ChangelogWidget2 as ChangelogWidget, Checklist2 as Checklist, FeatureDropContext, FeatureDropProvider, FeatureRequestButton2 as FeatureRequestButton, FeatureRequestForm2 as FeatureRequestForm, FeedbackWidget2 as FeedbackWidget, Hotspot2 as Hotspot, NewBadge2 as NewBadge, Spotlight2 as Spotlight, SpotlightChain2 as SpotlightChain, Survey2 as Survey, ThemeProvider, Toast2 as Toast, TooltipGroup2 as TooltipGroup, Tour2 as Tour, useAdoptionAnalytics, useChecklist, useFeatureDrop, useNewCount, useNewFeature, useSurvey, useTabNotification, useTour, useTourSequencer };
8121
+ export { AnnouncementModal2 as AnnouncementModal, Banner2 as Banner, ChangelogPage2 as ChangelogPage, ChangelogWidget2 as ChangelogWidget, Checklist2 as Checklist, FeatureDropContext, FeatureDropProvider, FeatureRequestButton2 as FeatureRequestButton, FeatureRequestForm2 as FeatureRequestForm, FeedbackWidget2 as FeedbackWidget, Hotspot2 as Hotspot, NewBadge2 as NewBadge, SmartAnnouncement2 as SmartAnnouncement, Spotlight2 as Spotlight, SpotlightChain2 as SpotlightChain, Survey2 as Survey, ThemeProvider, Toast2 as Toast, TooltipGroup2 as TooltipGroup, Tour2 as Tour, useAdoptionAnalytics, useAdoptionScore, useBehaviorProfile, useChangelog, useChecklist, useFeatureDrop, useNewCount, useNewFeature, useSmartFeature, useSurvey, useTabNotification, useTour, useTourSequencer };
7773
8122
  //# sourceMappingURL=preact.js.map
7774
8123
  //# sourceMappingURL=preact.js.map