featuredrop 1.2.0 → 1.3.0
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/README.md +171 -0
- package/dist/admin.cjs +212 -0
- package/dist/admin.cjs.map +1 -0
- package/dist/admin.d.cts +176 -0
- package/dist/admin.d.ts +176 -0
- package/dist/admin.js +207 -0
- package/dist/admin.js.map +1 -0
- package/dist/angular.cjs +13 -3
- package/dist/angular.cjs.map +1 -1
- package/dist/angular.d.cts +4 -0
- package/dist/angular.d.ts +4 -0
- package/dist/angular.js +13 -3
- package/dist/angular.js.map +1 -1
- package/dist/bridges.cjs +401 -0
- package/dist/bridges.cjs.map +1 -0
- package/dist/bridges.d.cts +194 -0
- package/dist/bridges.d.ts +194 -0
- package/dist/bridges.js +394 -0
- package/dist/bridges.js.map +1 -0
- package/dist/ci.cjs +328 -0
- package/dist/ci.cjs.map +1 -0
- package/dist/ci.d.cts +176 -0
- package/dist/ci.d.ts +176 -0
- package/dist/ci.js +324 -0
- package/dist/ci.js.map +1 -0
- package/dist/featuredrop.cjs +139 -18
- package/dist/featuredrop.cjs.map +1 -1
- package/dist/flags.cjs +51 -0
- package/dist/flags.cjs.map +1 -0
- package/dist/flags.d.cts +48 -0
- package/dist/flags.d.ts +48 -0
- package/dist/flags.js +47 -0
- package/dist/flags.js.map +1 -0
- package/dist/index.cjs +2583 -665
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +743 -206
- package/dist/index.d.ts +743 -206
- package/dist/index.js +2552 -666
- package/dist/index.js.map +1 -1
- package/dist/preact.cjs +710 -209
- package/dist/preact.cjs.map +1 -1
- package/dist/preact.d.cts +67 -120
- package/dist/preact.d.ts +67 -120
- package/dist/preact.js +696 -195
- package/dist/preact.js.map +1 -1
- package/dist/react.cjs +710 -209
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +67 -120
- package/dist/react.d.ts +67 -120
- package/dist/react.js +696 -195
- package/dist/react.js.map +1 -1
- package/dist/schema.cjs +78 -1
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +142 -0
- package/dist/schema.d.ts +142 -0
- package/dist/schema.js +78 -1
- package/dist/schema.js.map +1 -1
- package/dist/solid.cjs +13 -3
- package/dist/solid.cjs.map +1 -1
- package/dist/solid.d.cts +4 -0
- package/dist/solid.d.ts +4 -0
- package/dist/solid.js +13 -3
- package/dist/solid.js.map +1 -1
- package/dist/svelte.cjs +13 -3
- package/dist/svelte.cjs.map +1 -1
- package/dist/svelte.js +13 -3
- package/dist/svelte.js.map +1 -1
- package/dist/testing.cjs +136 -15
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +22 -0
- package/dist/testing.d.ts +22 -0
- package/dist/testing.js +136 -15
- package/dist/testing.js.map +1 -1
- package/dist/vue.cjs +13 -3
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.js +13 -3
- package/dist/vue.js.map +1 -1
- package/dist/web-components.cjs +14 -4
- package/dist/web-components.cjs.map +1 -1
- package/dist/web-components.d.cts +4 -0
- package/dist/web-components.d.ts +4 -0
- package/dist/web-components.js +14 -4
- package/dist/web-components.js.map +1 -1
- package/package.json +59 -1
package/dist/react.js
CHANGED
|
@@ -1,10 +1,138 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { createContext, useRef, useState, useMemo, useCallback, useEffect, useContext } from 'react';
|
|
2
|
+
import { createContext, useRef, useState, useMemo, useCallback, useEffect, useContext, Component } from 'react';
|
|
3
3
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
4
4
|
import { createRequire } from 'module';
|
|
5
5
|
|
|
6
6
|
// src/react/provider.tsx
|
|
7
7
|
|
|
8
|
+
// src/animation.ts
|
|
9
|
+
var injectedAnimationStyles = false;
|
|
10
|
+
function ensureFeatureDropAnimationStyles() {
|
|
11
|
+
if (injectedAnimationStyles || typeof document === "undefined") return;
|
|
12
|
+
injectedAnimationStyles = true;
|
|
13
|
+
const style = document.createElement("style");
|
|
14
|
+
style.setAttribute("data-featuredrop-animations", "true");
|
|
15
|
+
style.textContent = `
|
|
16
|
+
@keyframes featuredrop-enter-fade-up {
|
|
17
|
+
from { opacity: 0; transform: translateY(8px); }
|
|
18
|
+
to { opacity: 1; transform: translateY(0); }
|
|
19
|
+
}
|
|
20
|
+
@keyframes featuredrop-enter-scale {
|
|
21
|
+
from { opacity: 0; transform: scale(0.96); }
|
|
22
|
+
to { opacity: 1; transform: scale(1); }
|
|
23
|
+
}
|
|
24
|
+
@keyframes featuredrop-enter-panel {
|
|
25
|
+
from { opacity: 0; transform: translateX(14px); }
|
|
26
|
+
to { opacity: 1; transform: translateX(0); }
|
|
27
|
+
}
|
|
28
|
+
@keyframes featuredrop-enter-pop {
|
|
29
|
+
0% { opacity: 0; transform: translateY(12px) scale(0.94); }
|
|
30
|
+
70% { opacity: 1; transform: translateY(-2px) scale(1.02); }
|
|
31
|
+
100% { opacity: 1; transform: translateY(0) scale(1); }
|
|
32
|
+
}
|
|
33
|
+
@keyframes featuredrop-pulse {
|
|
34
|
+
0%, 100% { opacity: 1; }
|
|
35
|
+
50% { opacity: 0.55; }
|
|
36
|
+
}
|
|
37
|
+
@keyframes featuredrop-pulse-playful {
|
|
38
|
+
0%, 100% { opacity: 1; transform: scale(1); }
|
|
39
|
+
40% { opacity: 0.7; transform: scale(1.08); }
|
|
40
|
+
70% { opacity: 0.9; transform: scale(0.96); }
|
|
41
|
+
}
|
|
42
|
+
@keyframes featuredrop-beacon-pulse {
|
|
43
|
+
0%, 100% { transform: scale(1); opacity: 0.65; }
|
|
44
|
+
50% { transform: scale(1.5); opacity: 0; }
|
|
45
|
+
}
|
|
46
|
+
@keyframes featuredrop-beacon-pop-pulse {
|
|
47
|
+
0%, 100% { transform: scale(1); opacity: 0.72; }
|
|
48
|
+
45% { transform: scale(1.65); opacity: 0.08; }
|
|
49
|
+
75% { transform: scale(0.95); opacity: 0.28; }
|
|
50
|
+
}
|
|
51
|
+
@keyframes featuredrop-exit-fade-down {
|
|
52
|
+
from { opacity: 1; transform: translateY(0); }
|
|
53
|
+
to { opacity: 0; transform: translateY(8px); }
|
|
54
|
+
}
|
|
55
|
+
@keyframes featuredrop-exit-scale {
|
|
56
|
+
from { opacity: 1; transform: scale(1); }
|
|
57
|
+
to { opacity: 0; transform: scale(0.96); }
|
|
58
|
+
}
|
|
59
|
+
@keyframes featuredrop-exit-panel {
|
|
60
|
+
from { opacity: 1; transform: translateX(0); }
|
|
61
|
+
to { opacity: 0; transform: translateX(14px); }
|
|
62
|
+
}
|
|
63
|
+
@keyframes featuredrop-exit-pop {
|
|
64
|
+
from { opacity: 1; transform: translateY(0) scale(1); }
|
|
65
|
+
to { opacity: 0; transform: translateY(10px) scale(0.96); }
|
|
66
|
+
}
|
|
67
|
+
`;
|
|
68
|
+
document.head.appendChild(style);
|
|
69
|
+
}
|
|
70
|
+
function prefersReducedMotion() {
|
|
71
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
75
|
+
}
|
|
76
|
+
function resolveAnimationPreset(preset = "normal", options) {
|
|
77
|
+
if (options?.reducedMotion) return "none";
|
|
78
|
+
return preset;
|
|
79
|
+
}
|
|
80
|
+
function getEnterAnimation(preset, surface) {
|
|
81
|
+
if (preset === "none") return void 0;
|
|
82
|
+
if (preset === "subtle") {
|
|
83
|
+
if (surface === "panel") return "featuredrop-enter-panel 180ms ease-out";
|
|
84
|
+
if (surface === "modal") return "featuredrop-enter-scale 180ms ease-out";
|
|
85
|
+
return "featuredrop-enter-fade-up 170ms ease-out";
|
|
86
|
+
}
|
|
87
|
+
if (preset === "playful") {
|
|
88
|
+
if (surface === "panel") return "featuredrop-enter-panel 320ms cubic-bezier(0.2, 0.9, 0.2, 1)";
|
|
89
|
+
return "featuredrop-enter-pop 300ms cubic-bezier(0.22, 1.4, 0.36, 1)";
|
|
90
|
+
}
|
|
91
|
+
if (surface === "panel") return "featuredrop-enter-panel 240ms cubic-bezier(0.2, 0.9, 0.2, 1)";
|
|
92
|
+
if (surface === "modal") return "featuredrop-enter-scale 220ms cubic-bezier(0.2, 0.9, 0.2, 1)";
|
|
93
|
+
return "featuredrop-enter-fade-up 210ms cubic-bezier(0.2, 0.9, 0.2, 1)";
|
|
94
|
+
}
|
|
95
|
+
function getExitAnimation(preset, surface) {
|
|
96
|
+
if (preset === "none") return void 0;
|
|
97
|
+
if (preset === "subtle") {
|
|
98
|
+
if (surface === "panel") return "featuredrop-exit-panel 150ms ease-in forwards";
|
|
99
|
+
if (surface === "modal") return "featuredrop-exit-scale 150ms ease-in forwards";
|
|
100
|
+
return "featuredrop-exit-fade-down 140ms ease-in forwards";
|
|
101
|
+
}
|
|
102
|
+
if (preset === "playful") {
|
|
103
|
+
if (surface === "panel") return "featuredrop-exit-panel 260ms ease-in forwards";
|
|
104
|
+
return "featuredrop-exit-pop 240ms ease-in forwards";
|
|
105
|
+
}
|
|
106
|
+
if (surface === "panel") return "featuredrop-exit-panel 200ms ease-in forwards";
|
|
107
|
+
if (surface === "modal") return "featuredrop-exit-scale 190ms ease-in forwards";
|
|
108
|
+
return "featuredrop-exit-fade-down 180ms ease-in forwards";
|
|
109
|
+
}
|
|
110
|
+
function getPulseAnimation(preset, surface = "beacon") {
|
|
111
|
+
if (preset === "none") return void 0;
|
|
112
|
+
if (surface === "dot") {
|
|
113
|
+
if (preset === "subtle") return "featuredrop-pulse 2.6s ease-in-out infinite";
|
|
114
|
+
if (preset === "playful") {
|
|
115
|
+
return "featuredrop-pulse-playful 1.8s cubic-bezier(0.22, 1.4, 0.36, 1) infinite";
|
|
116
|
+
}
|
|
117
|
+
return "featuredrop-pulse 2s ease-in-out infinite";
|
|
118
|
+
}
|
|
119
|
+
if (preset === "subtle") return "featuredrop-beacon-pulse 2.6s ease-in-out infinite";
|
|
120
|
+
if (preset === "playful") {
|
|
121
|
+
return "featuredrop-beacon-pop-pulse 1.8s cubic-bezier(0.22, 1.4, 0.36, 1) infinite";
|
|
122
|
+
}
|
|
123
|
+
return "featuredrop-beacon-pulse 2s ease-in-out infinite";
|
|
124
|
+
}
|
|
125
|
+
function getAnimationDurationMs(preset, surface, phase) {
|
|
126
|
+
if (preset === "none") return 0;
|
|
127
|
+
const animation = getExitAnimation(preset, surface);
|
|
128
|
+
if (!animation) return 0;
|
|
129
|
+
const msMatch = animation.match(/(\d+)ms/);
|
|
130
|
+
if (msMatch?.[1]) return Number(msMatch[1]);
|
|
131
|
+
const sMatch = animation.match(/(\d+(?:\.\d+)?)s/);
|
|
132
|
+
if (sMatch?.[1]) return Math.round(Number(sMatch[1]) * 1e3);
|
|
133
|
+
return 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
8
136
|
// src/semver.ts
|
|
9
137
|
var SEMVER_REGEX = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/;
|
|
10
138
|
function parseSemver(input) {
|
|
@@ -226,6 +354,20 @@ function isVersionMatch(feature, appVersion) {
|
|
|
226
354
|
if (v.showNewUntil && compareSemver(appVersion, v.showNewUntil) >= 0) return false;
|
|
227
355
|
return true;
|
|
228
356
|
}
|
|
357
|
+
function isFlagMatch(feature, flagBridge, userContext) {
|
|
358
|
+
if (!feature.flagKey) return true;
|
|
359
|
+
if (!flagBridge) return false;
|
|
360
|
+
try {
|
|
361
|
+
return flagBridge.isEnabled(feature.flagKey, userContext);
|
|
362
|
+
} catch {
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
function isProductMatch(feature, product) {
|
|
367
|
+
if (!feature.product || feature.product === "*") return true;
|
|
368
|
+
if (!product) return false;
|
|
369
|
+
return feature.product === product;
|
|
370
|
+
}
|
|
229
371
|
function isDependencyMatch(feature, dismissedIds, dependencyState) {
|
|
230
372
|
const dependsOn = feature.dependsOn;
|
|
231
373
|
if (!dependsOn) return true;
|
|
@@ -250,11 +392,13 @@ function isDependencyMatch(feature, dismissedIds, dependencyState) {
|
|
|
250
392
|
}
|
|
251
393
|
return true;
|
|
252
394
|
}
|
|
253
|
-
function isNew(feature, watermark, dismissedIds, now = /* @__PURE__ */ new Date(), userContext, matchAudience, appVersion, dependencyState, triggerContext) {
|
|
395
|
+
function isNew(feature, watermark, dismissedIds, now = /* @__PURE__ */ new Date(), userContext, matchAudience, appVersion, dependencyState, triggerContext, flagBridge, product) {
|
|
254
396
|
if (dismissedIds.has(feature.id)) return false;
|
|
255
397
|
if (!isAudienceMatch(feature, userContext, matchAudience)) return false;
|
|
256
398
|
if (!isDependencyMatch(feature, dismissedIds, dependencyState)) return false;
|
|
257
399
|
if (!isVersionMatch(feature, appVersion)) return false;
|
|
400
|
+
if (!isFlagMatch(feature, flagBridge, userContext)) return false;
|
|
401
|
+
if (!isProductMatch(feature, product)) return false;
|
|
258
402
|
if (!isTriggerMatch(feature.trigger, triggerContext)) return false;
|
|
259
403
|
const nowMs = now.getTime();
|
|
260
404
|
if (feature.publishAt) {
|
|
@@ -270,7 +414,7 @@ function isNew(feature, watermark, dismissedIds, now = /* @__PURE__ */ new Date(
|
|
|
270
414
|
}
|
|
271
415
|
return true;
|
|
272
416
|
}
|
|
273
|
-
function getNewFeatures(manifest, storage, now = /* @__PURE__ */ new Date(), userContext, matchAudience, appVersion, dependencyState, triggerContext) {
|
|
417
|
+
function getNewFeatures(manifest, storage, now = /* @__PURE__ */ new Date(), userContext, matchAudience, appVersion, dependencyState, triggerContext, flagBridge, product) {
|
|
274
418
|
const watermark = storage.getWatermark();
|
|
275
419
|
const dismissedIds = storage.getDismissedIds();
|
|
276
420
|
return manifest.filter(
|
|
@@ -283,7 +427,9 @@ function getNewFeatures(manifest, storage, now = /* @__PURE__ */ new Date(), use
|
|
|
283
427
|
matchAudience,
|
|
284
428
|
appVersion,
|
|
285
429
|
dependencyState,
|
|
286
|
-
triggerContext
|
|
430
|
+
triggerContext,
|
|
431
|
+
flagBridge,
|
|
432
|
+
product
|
|
287
433
|
)
|
|
288
434
|
);
|
|
289
435
|
}
|
|
@@ -343,6 +489,7 @@ var EN_TRANSLATIONS = {
|
|
|
343
489
|
loadMore: "Load more",
|
|
344
490
|
share: "Share",
|
|
345
491
|
skipToEntries: "Skip to changelog entries",
|
|
492
|
+
newFeatureCount: (count) => count === 0 ? "No new features" : `${count} new feature${count === 1 ? "" : "s"}`,
|
|
346
493
|
stepOf: (current, total) => `Step ${current} of ${total}`,
|
|
347
494
|
back: "Back",
|
|
348
495
|
next: "Next",
|
|
@@ -593,16 +740,133 @@ var SIMPLE_TRANSLATIONS = {
|
|
|
593
740
|
askLater: "\u092C\u093E\u0926 \u092E\u0947\u0902 \u092A\u0942\u091B\u0947\u0902"
|
|
594
741
|
}
|
|
595
742
|
};
|
|
743
|
+
var RTL_LANGUAGES = /* @__PURE__ */ new Set(["ar", "fa", "he", "ur"]);
|
|
744
|
+
var STEP_OF_TRANSLATIONS = {
|
|
745
|
+
en: EN_TRANSLATIONS.stepOf,
|
|
746
|
+
es: (current, total) => `Paso ${current} de ${total}`,
|
|
747
|
+
fr: (current, total) => `Etape ${current} sur ${total}`,
|
|
748
|
+
de: (current, total) => `Schritt ${current} von ${total}`,
|
|
749
|
+
pt: (current, total) => `Etapa ${current} de ${total}`,
|
|
750
|
+
"zh-cn": (current, total) => `\u7B2C ${current} / ${total} \u6B65`,
|
|
751
|
+
ja: (current, total) => `${total}\u4E2D${current}\u756A\u76EE`,
|
|
752
|
+
ko: (current, total) => `${total}\uB2E8\uACC4 \uC911 ${current}\uB2E8\uACC4`,
|
|
753
|
+
ar: (current, total) => `\u0627\u0644\u062E\u0637\u0648\u0629 ${current} \u0645\u0646 ${total}`,
|
|
754
|
+
hi: (current, total) => `${total} \u092E\u0947\u0902 \u0938\u0947 \u091A\u0930\u0923 ${current}`
|
|
755
|
+
};
|
|
756
|
+
var NEW_FEATURE_COUNT_TRANSLATIONS = {
|
|
757
|
+
en: EN_TRANSLATIONS.newFeatureCount,
|
|
758
|
+
es: (count) => count === 0 ? "Sin novedades" : `${count} novedad${count === 1 ? "" : "es"}`,
|
|
759
|
+
fr: (count) => count === 0 ? "Aucune nouveaute" : `${count} nouveaute${count === 1 ? "" : "s"}`,
|
|
760
|
+
de: (count) => count === 0 ? "Keine neuen Features" : `${count} ${count === 1 ? "neues Feature" : "neue Features"}`,
|
|
761
|
+
pt: (count) => count === 0 ? "Sem novidades" : `${count} novidade${count === 1 ? "" : "s"}`,
|
|
762
|
+
"zh-cn": (count) => count === 0 ? "\u6682\u65E0\u66F4\u65B0" : `${count} \u6761\u65B0\u66F4\u65B0`,
|
|
763
|
+
ja: (count) => count === 0 ? "\u65B0\u7740\u306F\u3042\u308A\u307E\u305B\u3093" : `\u65B0\u7740 ${count} \u4EF6`,
|
|
764
|
+
ko: (count) => count === 0 ? "\uC0C8 \uC18C\uC2DD \uC5C6\uC74C" : `\uC0C8 \uC18C\uC2DD ${count}\uAC1C`,
|
|
765
|
+
ar: (count) => {
|
|
766
|
+
if (count === 0) return "\u0644\u0627 \u062A\u0648\u062C\u062F \u0645\u064A\u0632\u0627\u062A \u062C\u062F\u064A\u062F\u0629";
|
|
767
|
+
const category = new Intl.PluralRules("ar").select(count);
|
|
768
|
+
if (category === "one") return "\u0645\u064A\u0632\u0629 \u062C\u062F\u064A\u062F\u0629 \u0648\u0627\u062D\u062F\u0629";
|
|
769
|
+
if (category === "two") return "\u0645\u064A\u0632\u062A\u0627\u0646 \u062C\u062F\u064A\u062F\u062A\u0627\u0646";
|
|
770
|
+
return `${count} \u0645\u064A\u0632\u0627\u062A \u062C\u062F\u064A\u062F\u0629`;
|
|
771
|
+
},
|
|
772
|
+
hi: (count) => count === 0 ? "\u0915\u094B\u0908 \u0928\u092F\u093E \u0905\u092A\u0921\u0947\u091F \u0928\u0939\u0940\u0902" : `${count} ${count === 1 ? "\u0928\u092F\u093E \u0905\u092A\u0921\u0947\u091F" : "\u0928\u090F \u0905\u092A\u0921\u0947\u091F"}`
|
|
773
|
+
};
|
|
774
|
+
function resolveLocale(locale) {
|
|
775
|
+
const normalized = (locale ?? "en").toLowerCase();
|
|
776
|
+
if (normalized === "en" || normalized.startsWith("en-")) return "en";
|
|
777
|
+
if (Object.prototype.hasOwnProperty.call(SIMPLE_TRANSLATIONS, normalized)) {
|
|
778
|
+
return normalized;
|
|
779
|
+
}
|
|
780
|
+
const base = normalized.split("-")[0];
|
|
781
|
+
if (base === "en") return "en";
|
|
782
|
+
if (Object.prototype.hasOwnProperty.call(SIMPLE_TRANSLATIONS, base)) {
|
|
783
|
+
return base;
|
|
784
|
+
}
|
|
785
|
+
return "en";
|
|
786
|
+
}
|
|
787
|
+
function getLocaleDirection(locale) {
|
|
788
|
+
const resolved = resolveLocale(locale);
|
|
789
|
+
const base = resolved.split("-")[0];
|
|
790
|
+
return RTL_LANGUAGES.has(base) ? "rtl" : "ltr";
|
|
791
|
+
}
|
|
792
|
+
function formatDateForLocale(value, locale, options = {
|
|
793
|
+
month: "short",
|
|
794
|
+
day: "numeric",
|
|
795
|
+
year: "numeric"
|
|
796
|
+
}) {
|
|
797
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
798
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
799
|
+
const resolved = resolveLocale(locale);
|
|
800
|
+
try {
|
|
801
|
+
return new Intl.DateTimeFormat(resolved, options).format(date);
|
|
802
|
+
} catch {
|
|
803
|
+
return date.toLocaleDateString(void 0, options);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
function formatRelativeTimeForLocale(value, locale, options) {
|
|
807
|
+
const target = value instanceof Date ? value : new Date(value);
|
|
808
|
+
if (Number.isNaN(target.getTime())) return "";
|
|
809
|
+
const nowInput = options?.now;
|
|
810
|
+
const nowDate = nowInput instanceof Date ? nowInput : /* @__PURE__ */ new Date();
|
|
811
|
+
if (Number.isNaN(nowDate.getTime())) return "";
|
|
812
|
+
const diffMs = target.getTime() - nowDate.getTime();
|
|
813
|
+
const absDiff = Math.abs(diffMs);
|
|
814
|
+
const minute = 6e4;
|
|
815
|
+
const hour = 60 * minute;
|
|
816
|
+
const day = 24 * hour;
|
|
817
|
+
const week = 7 * day;
|
|
818
|
+
const month = 30 * day;
|
|
819
|
+
const year = 365 * day;
|
|
820
|
+
let unit = "second";
|
|
821
|
+
let divisor = 1e3;
|
|
822
|
+
if (absDiff >= year) {
|
|
823
|
+
unit = "year";
|
|
824
|
+
divisor = year;
|
|
825
|
+
} else if (absDiff >= month) {
|
|
826
|
+
unit = "month";
|
|
827
|
+
divisor = month;
|
|
828
|
+
} else if (absDiff >= week) {
|
|
829
|
+
unit = "week";
|
|
830
|
+
divisor = week;
|
|
831
|
+
} else if (absDiff >= day) {
|
|
832
|
+
unit = "day";
|
|
833
|
+
divisor = day;
|
|
834
|
+
} else if (absDiff >= hour) {
|
|
835
|
+
unit = "hour";
|
|
836
|
+
divisor = hour;
|
|
837
|
+
} else if (absDiff >= minute) {
|
|
838
|
+
unit = "minute";
|
|
839
|
+
divisor = minute;
|
|
840
|
+
}
|
|
841
|
+
const relativeValue = Math.round(diffMs / divisor);
|
|
842
|
+
const resolvedLocale = resolveLocale(locale);
|
|
843
|
+
try {
|
|
844
|
+
const formatter = new Intl.RelativeTimeFormat(resolvedLocale, {
|
|
845
|
+
numeric: options?.numeric ?? "auto",
|
|
846
|
+
style: options?.style ?? "long"
|
|
847
|
+
});
|
|
848
|
+
return formatter.format(relativeValue, unit);
|
|
849
|
+
} catch {
|
|
850
|
+
const fallback = formatDateForLocale(target, resolvedLocale);
|
|
851
|
+
return fallback || target.toISOString();
|
|
852
|
+
}
|
|
853
|
+
}
|
|
596
854
|
function resolveTranslations(locale, overrides) {
|
|
597
|
-
const
|
|
598
|
-
const base =
|
|
855
|
+
const resolvedLocale = resolveLocale(locale);
|
|
856
|
+
const base = resolvedLocale === "en" ? {} : SIMPLE_TRANSLATIONS[resolvedLocale] ?? {};
|
|
857
|
+
const stepOf = overrides?.stepOf ?? STEP_OF_TRANSLATIONS[resolvedLocale] ?? STEP_OF_TRANSLATIONS.en;
|
|
858
|
+
const newFeatureCount = overrides?.newFeatureCount ?? NEW_FEATURE_COUNT_TRANSLATIONS[resolvedLocale] ?? NEW_FEATURE_COUNT_TRANSLATIONS.en;
|
|
599
859
|
return {
|
|
600
860
|
...EN_TRANSLATIONS,
|
|
601
861
|
...base,
|
|
602
862
|
...overrides ?? {},
|
|
603
|
-
stepOf
|
|
863
|
+
stepOf,
|
|
864
|
+
newFeatureCount
|
|
604
865
|
};
|
|
605
866
|
}
|
|
867
|
+
({
|
|
868
|
+
...SIMPLE_TRANSLATIONS
|
|
869
|
+
});
|
|
606
870
|
|
|
607
871
|
// src/variants.ts
|
|
608
872
|
var VARIANT_META_KEY = "featuredropVariant";
|
|
@@ -756,12 +1020,14 @@ function computeFeatureState({
|
|
|
756
1020
|
userContext,
|
|
757
1021
|
matchAudience,
|
|
758
1022
|
appVersion,
|
|
1023
|
+
product,
|
|
759
1024
|
throttle,
|
|
760
1025
|
sessionStartedAt,
|
|
761
1026
|
quietMode,
|
|
762
1027
|
seenFeatureIds,
|
|
763
1028
|
clickedFeatureIds,
|
|
764
|
-
triggerContext
|
|
1029
|
+
triggerContext,
|
|
1030
|
+
flagBridge
|
|
765
1031
|
}) {
|
|
766
1032
|
const dismissedIds = storage.getDismissedIds();
|
|
767
1033
|
const allFeatures = getNewFeatures(
|
|
@@ -776,7 +1042,9 @@ function computeFeatureState({
|
|
|
776
1042
|
clickedIds: clickedFeatureIds,
|
|
777
1043
|
dismissedIds
|
|
778
1044
|
},
|
|
779
|
-
triggerContext
|
|
1045
|
+
triggerContext,
|
|
1046
|
+
flagBridge,
|
|
1047
|
+
product
|
|
780
1048
|
);
|
|
781
1049
|
const throttled = applyAnnouncementThrottle(
|
|
782
1050
|
allFeatures,
|
|
@@ -797,13 +1065,17 @@ function FeatureDropProvider({
|
|
|
797
1065
|
manifest,
|
|
798
1066
|
storage,
|
|
799
1067
|
analytics,
|
|
1068
|
+
onError,
|
|
800
1069
|
userContext,
|
|
801
1070
|
matchAudience: matchAudienceFn,
|
|
802
1071
|
appVersion,
|
|
1072
|
+
product,
|
|
803
1073
|
throttle,
|
|
804
1074
|
variantKey,
|
|
805
1075
|
collector,
|
|
1076
|
+
flagBridge,
|
|
806
1077
|
locale = "en",
|
|
1078
|
+
animation = "normal",
|
|
807
1079
|
translations: translationOverrides,
|
|
808
1080
|
children
|
|
809
1081
|
}) {
|
|
@@ -832,9 +1104,15 @@ function FeatureDropProvider({
|
|
|
832
1104
|
() => readIdSet(CLICKED_FEATURES_STORAGE_KEY)
|
|
833
1105
|
);
|
|
834
1106
|
const resolvedVariantKey = useMemo(() => getOrCreateVariantKey(variantKey), [variantKey]);
|
|
1107
|
+
const resolvedLocale = useMemo(() => resolveLocale(locale), [locale]);
|
|
1108
|
+
const direction = useMemo(() => getLocaleDirection(resolvedLocale), [resolvedLocale]);
|
|
1109
|
+
const resolvedAnimation = useMemo(
|
|
1110
|
+
() => resolveAnimationPreset(animation, { reducedMotion: prefersReducedMotion() }),
|
|
1111
|
+
[animation]
|
|
1112
|
+
);
|
|
835
1113
|
const translations = useMemo(
|
|
836
|
-
() => resolveTranslations(
|
|
837
|
-
[
|
|
1114
|
+
() => resolveTranslations(resolvedLocale, translationOverrides),
|
|
1115
|
+
[resolvedLocale, translationOverrides]
|
|
838
1116
|
);
|
|
839
1117
|
const resolvedManifest = useMemo(
|
|
840
1118
|
() => applyFeatureVariants(manifest, resolvedVariantKey),
|
|
@@ -848,6 +1126,7 @@ function FeatureDropProvider({
|
|
|
848
1126
|
userContext,
|
|
849
1127
|
matchAudience: matchAudienceFn,
|
|
850
1128
|
appVersion,
|
|
1129
|
+
product,
|
|
851
1130
|
throttle,
|
|
852
1131
|
sessionStartedAt: sessionStartedAtRef.current,
|
|
853
1132
|
quietMode: readQuietMode(),
|
|
@@ -858,7 +1137,8 @@ function FeatureDropProvider({
|
|
|
858
1137
|
if (!engine) return void 0;
|
|
859
1138
|
engine.setElapsedMs(Date.now() - sessionStartedAtRef.current);
|
|
860
1139
|
return engine.getContext();
|
|
861
|
-
})()
|
|
1140
|
+
})(),
|
|
1141
|
+
flagBridge
|
|
862
1142
|
})
|
|
863
1143
|
);
|
|
864
1144
|
const recompute = useCallback(() => {
|
|
@@ -876,12 +1156,14 @@ function FeatureDropProvider({
|
|
|
876
1156
|
userContext,
|
|
877
1157
|
matchAudience: matchAudienceFn,
|
|
878
1158
|
appVersion,
|
|
1159
|
+
product,
|
|
879
1160
|
throttle,
|
|
880
1161
|
sessionStartedAt: sessionStartedAtRef.current,
|
|
881
1162
|
quietMode,
|
|
882
1163
|
seenFeatureIds,
|
|
883
1164
|
clickedFeatureIds,
|
|
884
|
-
triggerContext
|
|
1165
|
+
triggerContext,
|
|
1166
|
+
flagBridge
|
|
885
1167
|
})
|
|
886
1168
|
);
|
|
887
1169
|
}, [
|
|
@@ -890,11 +1172,13 @@ function FeatureDropProvider({
|
|
|
890
1172
|
userContext,
|
|
891
1173
|
matchAudienceFn,
|
|
892
1174
|
appVersion,
|
|
1175
|
+
product,
|
|
893
1176
|
throttle,
|
|
894
1177
|
quietMode,
|
|
895
1178
|
seenFeatureIds,
|
|
896
1179
|
clickedFeatureIds,
|
|
897
|
-
triggerVersion
|
|
1180
|
+
triggerVersion,
|
|
1181
|
+
flagBridge
|
|
898
1182
|
]);
|
|
899
1183
|
useEffect(() => {
|
|
900
1184
|
recompute();
|
|
@@ -1101,6 +1385,15 @@ function FeatureDropProvider({
|
|
|
1101
1385
|
variant: event.variant ?? (feature ? getFeatureVariantName(feature) : void 0)
|
|
1102
1386
|
});
|
|
1103
1387
|
}, [collector, resolvedManifest]);
|
|
1388
|
+
const reportError = useCallback(
|
|
1389
|
+
(error, context) => {
|
|
1390
|
+
onError?.(error, context);
|
|
1391
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
|
|
1392
|
+
console.warn("[featuredrop] component error", context?.component, error);
|
|
1393
|
+
}
|
|
1394
|
+
},
|
|
1395
|
+
[onError]
|
|
1396
|
+
);
|
|
1104
1397
|
const trackUsageEvent = useCallback((event, delta = 1) => {
|
|
1105
1398
|
if (!event) return;
|
|
1106
1399
|
triggerEngineRef.current?.trackUsage(event, delta);
|
|
@@ -1164,7 +1457,10 @@ function FeatureDropProvider({
|
|
|
1164
1457
|
releaseSpotlightSlot,
|
|
1165
1458
|
activeSpotlightCount: activeSpotlightIds.size,
|
|
1166
1459
|
trackAdoptionEvent,
|
|
1167
|
-
|
|
1460
|
+
reportError,
|
|
1461
|
+
locale: resolvedLocale,
|
|
1462
|
+
direction,
|
|
1463
|
+
animation: resolvedAnimation,
|
|
1168
1464
|
translations,
|
|
1169
1465
|
trackUsageEvent,
|
|
1170
1466
|
trackTriggerEvent,
|
|
@@ -1195,7 +1491,10 @@ function FeatureDropProvider({
|
|
|
1195
1491
|
releaseSpotlightSlot,
|
|
1196
1492
|
activeSpotlightIds.size,
|
|
1197
1493
|
trackAdoptionEvent,
|
|
1198
|
-
|
|
1494
|
+
reportError,
|
|
1495
|
+
resolvedLocale,
|
|
1496
|
+
direction,
|
|
1497
|
+
resolvedAnimation,
|
|
1199
1498
|
translations,
|
|
1200
1499
|
trackUsageEvent,
|
|
1201
1500
|
trackTriggerEvent,
|
|
@@ -1914,6 +2213,34 @@ function useSurvey(id) {
|
|
|
1914
2213
|
[askLater, hide, show, snapshot]
|
|
1915
2214
|
);
|
|
1916
2215
|
}
|
|
2216
|
+
var FeatureDropComponentBoundary = class extends Component {
|
|
2217
|
+
state = { hasError: false };
|
|
2218
|
+
componentDidCatch(error, info) {
|
|
2219
|
+
this.setState({ hasError: true });
|
|
2220
|
+
this.props.onError?.(error, info);
|
|
2221
|
+
}
|
|
2222
|
+
render() {
|
|
2223
|
+
if (this.state.hasError) return null;
|
|
2224
|
+
return this.props.children;
|
|
2225
|
+
}
|
|
2226
|
+
};
|
|
2227
|
+
function withFeatureDropBoundary(ComponentImpl, componentName) {
|
|
2228
|
+
function Wrapped(props) {
|
|
2229
|
+
const context = useContext(FeatureDropContext);
|
|
2230
|
+
const onError = useCallback(
|
|
2231
|
+
(error, info) => {
|
|
2232
|
+
context?.reportError(error, {
|
|
2233
|
+
component: componentName,
|
|
2234
|
+
componentStack: info.componentStack ?? void 0
|
|
2235
|
+
});
|
|
2236
|
+
},
|
|
2237
|
+
[context]
|
|
2238
|
+
);
|
|
2239
|
+
return /* @__PURE__ */ jsx(FeatureDropComponentBoundary, { onError, children: /* @__PURE__ */ jsx(ComponentImpl, { ...props }) });
|
|
2240
|
+
}
|
|
2241
|
+
Wrapped.displayName = `FeatureDropBoundary(${componentName})`;
|
|
2242
|
+
return Wrapped;
|
|
2243
|
+
}
|
|
1917
2244
|
var baseStyles = {
|
|
1918
2245
|
display: "inline-flex",
|
|
1919
2246
|
alignItems: "center",
|
|
@@ -1964,15 +2291,25 @@ function NewBadge({
|
|
|
1964
2291
|
style,
|
|
1965
2292
|
children
|
|
1966
2293
|
}) {
|
|
2294
|
+
const context = useContext(FeatureDropContext);
|
|
2295
|
+
const pulsePreset = useMemo(
|
|
2296
|
+
() => resolveAnimationPreset(context?.animation ?? "normal", {
|
|
2297
|
+
reducedMotion: prefersReducedMotion()
|
|
2298
|
+
}),
|
|
2299
|
+
[context?.animation]
|
|
2300
|
+
);
|
|
2301
|
+
const dotPulseAnimation = useMemo(() => getPulseAnimation(pulsePreset, "dot"), [pulsePreset]);
|
|
2302
|
+
useEffect(() => {
|
|
2303
|
+
ensureFeatureDropAnimationStyles();
|
|
2304
|
+
}, []);
|
|
1967
2305
|
if (children) {
|
|
1968
2306
|
return /* @__PURE__ */ jsx(Fragment, { children: children({ isNew: show }) });
|
|
1969
2307
|
}
|
|
1970
2308
|
if (!show) return null;
|
|
1971
2309
|
const handleClick = dismissOnClick && onDismiss ? onDismiss : void 0;
|
|
1972
|
-
const reduceMotion = typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
1973
2310
|
const variantStyles = variant === "dot" ? {
|
|
1974
2311
|
...dotStyles,
|
|
1975
|
-
animation:
|
|
2312
|
+
animation: dotPulseAnimation ?? "none"
|
|
1976
2313
|
} : variant === "count" ? countStyles : pillStyles;
|
|
1977
2314
|
const content = variant === "dot" ? null : variant === "count" ? count ?? 0 : label;
|
|
1978
2315
|
const ariaLabel = variant === "count" ? `${count ?? 0} new features` : "New feature";
|
|
@@ -2525,14 +2862,6 @@ var TYPE_COLORS = {
|
|
|
2525
2862
|
fix: { color: "#92400e", bg: "rgba(245, 158, 11, 0.15)" },
|
|
2526
2863
|
breaking: { color: "#991b1b", bg: "rgba(239, 68, 68, 0.15)" }
|
|
2527
2864
|
};
|
|
2528
|
-
function formatDate(iso) {
|
|
2529
|
-
const d = new Date(iso);
|
|
2530
|
-
return d.toLocaleDateString(void 0, {
|
|
2531
|
-
month: "short",
|
|
2532
|
-
day: "numeric",
|
|
2533
|
-
year: "numeric"
|
|
2534
|
-
});
|
|
2535
|
-
}
|
|
2536
2865
|
function getFocusableElements(container) {
|
|
2537
2866
|
const nodes = container.querySelectorAll(
|
|
2538
2867
|
[
|
|
@@ -2555,7 +2884,9 @@ function DefaultEntry({
|
|
|
2555
2884
|
reactions,
|
|
2556
2885
|
userReaction,
|
|
2557
2886
|
canReact,
|
|
2558
|
-
react
|
|
2887
|
+
react,
|
|
2888
|
+
locale,
|
|
2889
|
+
dateFormat
|
|
2559
2890
|
}) {
|
|
2560
2891
|
const typeStyle = feature.type ? TYPE_COLORS[feature.type] ?? TYPE_COLORS.feature : null;
|
|
2561
2892
|
const descriptionHtml = feature.description ? parseDescription(feature.description) : null;
|
|
@@ -2605,7 +2936,7 @@ function DefaultEntry({
|
|
|
2605
2936
|
}
|
|
2606
2937
|
),
|
|
2607
2938
|
feature.category && /* @__PURE__ */ jsx("span", { children: feature.category }),
|
|
2608
|
-
/* @__PURE__ */ jsx("span", { children:
|
|
2939
|
+
/* @__PURE__ */ jsx("span", { children: dateFormat === "relative" ? formatRelativeTimeForLocale(feature.releasedAt, locale) : formatDateForLocale(feature.releasedAt, locale) }),
|
|
2609
2940
|
versionLabel && /* @__PURE__ */ jsxs("span", { children: [
|
|
2610
2941
|
"v",
|
|
2611
2942
|
versionLabel
|
|
@@ -2652,6 +2983,7 @@ function ChangelogWidget({
|
|
|
2652
2983
|
showMarkAll = true,
|
|
2653
2984
|
emptyLabel,
|
|
2654
2985
|
maxHeight = "400px",
|
|
2986
|
+
dateFormat = "absolute",
|
|
2655
2987
|
analytics,
|
|
2656
2988
|
className,
|
|
2657
2989
|
style,
|
|
@@ -2671,14 +3003,19 @@ function ChangelogWidget({
|
|
|
2671
3003
|
markFeatureSeen,
|
|
2672
3004
|
markFeatureClicked,
|
|
2673
3005
|
trackAdoptionEvent,
|
|
3006
|
+
locale,
|
|
3007
|
+
direction,
|
|
3008
|
+
animation,
|
|
2674
3009
|
translations
|
|
2675
3010
|
} = useFeatureDrop();
|
|
2676
3011
|
const [isOpen, setIsOpen] = useState(false);
|
|
3012
|
+
const [isClosing, setIsClosing] = useState(false);
|
|
2677
3013
|
const [, setReactionVersion] = useState(0);
|
|
2678
3014
|
const containerRef = useRef(null);
|
|
2679
3015
|
const dialogRef = useRef(null);
|
|
2680
3016
|
const triggerRef = useRef(null);
|
|
2681
3017
|
const lastFocusedElementRef = useRef(null);
|
|
3018
|
+
const closeTimerRef = useRef(null);
|
|
2682
3019
|
const widgetIdRef = useRef(`featuredrop-widget-${Math.random().toString(36).slice(2, 10)}`);
|
|
2683
3020
|
const themeVariables = useThemeVariables(theme);
|
|
2684
3021
|
const resolvedTitle = title ?? translations.whatsNewTitle;
|
|
@@ -2687,7 +3024,27 @@ function ChangelogWidget({
|
|
|
2687
3024
|
const resolvedEmptyLabel = emptyLabel ?? translations.allCaughtUp;
|
|
2688
3025
|
const dialogId = `${widgetIdRef.current}-dialog`;
|
|
2689
3026
|
const titleId = `${widgetIdRef.current}-title`;
|
|
3027
|
+
const countLabel = translations.newFeatureCount(newCount);
|
|
3028
|
+
const dialogEnterAnimation = useMemo(
|
|
3029
|
+
() => getEnterAnimation(animation, variant),
|
|
3030
|
+
[animation, variant]
|
|
3031
|
+
);
|
|
3032
|
+
const dialogExitAnimation = useMemo(
|
|
3033
|
+
() => getExitAnimation(animation, variant),
|
|
3034
|
+
[animation, variant]
|
|
3035
|
+
);
|
|
3036
|
+
useEffect(() => {
|
|
3037
|
+
ensureFeatureDropAnimationStyles();
|
|
3038
|
+
return () => {
|
|
3039
|
+
if (closeTimerRef.current) clearTimeout(closeTimerRef.current);
|
|
3040
|
+
};
|
|
3041
|
+
}, []);
|
|
2690
3042
|
const open = useCallback(() => {
|
|
3043
|
+
if (closeTimerRef.current) {
|
|
3044
|
+
clearTimeout(closeTimerRef.current);
|
|
3045
|
+
closeTimerRef.current = null;
|
|
3046
|
+
}
|
|
3047
|
+
setIsClosing(false);
|
|
2691
3048
|
if (typeof document !== "undefined" && document.activeElement instanceof HTMLElement) {
|
|
2692
3049
|
lastFocusedElementRef.current = document.activeElement;
|
|
2693
3050
|
}
|
|
@@ -2695,7 +3052,21 @@ function ChangelogWidget({
|
|
|
2695
3052
|
analytics?.onWidgetOpened?.();
|
|
2696
3053
|
}, [analytics]);
|
|
2697
3054
|
const close = useCallback(() => {
|
|
3055
|
+
if (closeTimerRef.current) {
|
|
3056
|
+
clearTimeout(closeTimerRef.current);
|
|
3057
|
+
closeTimerRef.current = null;
|
|
3058
|
+
}
|
|
2698
3059
|
setIsOpen(false);
|
|
3060
|
+
const exitDuration = getAnimationDurationMs(animation, variant);
|
|
3061
|
+
if (exitDuration > 0) {
|
|
3062
|
+
setIsClosing(true);
|
|
3063
|
+
closeTimerRef.current = setTimeout(() => {
|
|
3064
|
+
setIsClosing(false);
|
|
3065
|
+
closeTimerRef.current = null;
|
|
3066
|
+
}, exitDuration);
|
|
3067
|
+
} else {
|
|
3068
|
+
setIsClosing(false);
|
|
3069
|
+
}
|
|
2699
3070
|
analytics?.onWidgetClosed?.();
|
|
2700
3071
|
const returnTarget = triggerRef.current ?? lastFocusedElementRef.current;
|
|
2701
3072
|
if (returnTarget) {
|
|
@@ -2707,7 +3078,7 @@ function ChangelogWidget({
|
|
|
2707
3078
|
returnTarget.focus();
|
|
2708
3079
|
}
|
|
2709
3080
|
}
|
|
2710
|
-
}, [analytics]);
|
|
3081
|
+
}, [animation, analytics, variant]);
|
|
2711
3082
|
const toggle = useCallback(() => {
|
|
2712
3083
|
if (isOpen) {
|
|
2713
3084
|
close();
|
|
@@ -2844,6 +3215,7 @@ function ChangelogWidget({
|
|
|
2844
3215
|
"data-featuredrop-widget": true,
|
|
2845
3216
|
className,
|
|
2846
3217
|
style: widgetRootStyle,
|
|
3218
|
+
dir: direction,
|
|
2847
3219
|
children: [
|
|
2848
3220
|
renderTrigger ? renderTrigger({ count: newCount, onClick: toggle }) : /* @__PURE__ */ jsxs(
|
|
2849
3221
|
"button",
|
|
@@ -2852,7 +3224,7 @@ function ChangelogWidget({
|
|
|
2852
3224
|
onClick: toggle,
|
|
2853
3225
|
style: triggerButtonStyles,
|
|
2854
3226
|
"data-featuredrop-trigger": true,
|
|
2855
|
-
"aria-label": `${resolvedTriggerLabel}${newCount > 0 ? ` \u2014 ${
|
|
3227
|
+
"aria-label": `${resolvedTriggerLabel}${newCount > 0 ? ` \u2014 ${countLabel}` : ""}`,
|
|
2856
3228
|
"aria-haspopup": "dialog",
|
|
2857
3229
|
"aria-expanded": isOpen,
|
|
2858
3230
|
"aria-controls": dialogId,
|
|
@@ -2862,8 +3234,8 @@ function ChangelogWidget({
|
|
|
2862
3234
|
]
|
|
2863
3235
|
}
|
|
2864
3236
|
),
|
|
2865
|
-
/* @__PURE__ */ jsx("span", { style: srOnlyStyles, "aria-live": "polite", "aria-atomic": "true", children:
|
|
2866
|
-
isOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3237
|
+
/* @__PURE__ */ jsx("span", { style: srOnlyStyles, "aria-live": "polite", "aria-atomic": "true", children: countLabel }),
|
|
3238
|
+
(isOpen || isClosing) && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2867
3239
|
variant !== "popover" && /* @__PURE__ */ jsx(
|
|
2868
3240
|
"div",
|
|
2869
3241
|
{
|
|
@@ -2878,7 +3250,10 @@ function ChangelogWidget({
|
|
|
2878
3250
|
{
|
|
2879
3251
|
id: dialogId,
|
|
2880
3252
|
ref: dialogRef,
|
|
2881
|
-
style:
|
|
3253
|
+
style: {
|
|
3254
|
+
...dialogContainerStyles,
|
|
3255
|
+
animation: isClosing ? dialogExitAnimation : dialogEnterAnimation
|
|
3256
|
+
},
|
|
2882
3257
|
"data-featuredrop-container": variant,
|
|
2883
3258
|
role: "dialog",
|
|
2884
3259
|
"aria-labelledby": titleId,
|
|
@@ -2917,6 +3292,8 @@ function ChangelogWidget({
|
|
|
2917
3292
|
feature,
|
|
2918
3293
|
dismiss: () => handleDismiss(feature.id),
|
|
2919
3294
|
onFeatureClick: () => handleFeatureClick(feature),
|
|
3295
|
+
locale,
|
|
3296
|
+
dateFormat,
|
|
2920
3297
|
reactions: showReactions ? getReactionCounts(feature.id, reactions) : void 0,
|
|
2921
3298
|
userReaction: showReactions ? getUserReaction(feature.id) : null,
|
|
2922
3299
|
canReact: showReactions ? !getUserReaction(feature.id) : void 0,
|
|
@@ -2954,8 +3331,7 @@ var beaconPulseStyles = {
|
|
|
2954
3331
|
inset: "-4px",
|
|
2955
3332
|
borderRadius: "50%",
|
|
2956
3333
|
border: "2px solid var(--featuredrop-beacon-color, #f59e0b)",
|
|
2957
|
-
opacity: 0.6
|
|
2958
|
-
animation: "featuredrop-spotlight-pulse 2s ease-in-out infinite"
|
|
3334
|
+
opacity: 0.6
|
|
2959
3335
|
};
|
|
2960
3336
|
var tooltipStyles = {
|
|
2961
3337
|
position: "absolute",
|
|
@@ -2991,29 +3367,6 @@ var tooltipDismissStyles = {
|
|
|
2991
3367
|
backgroundColor: "var(--featuredrop-tooltip-dismiss-bg, #f3f4f6)",
|
|
2992
3368
|
color: "var(--featuredrop-tooltip-dismiss-color, #374151)"
|
|
2993
3369
|
};
|
|
2994
|
-
var injectedKeyframes = false;
|
|
2995
|
-
function injectKeyframes() {
|
|
2996
|
-
if (injectedKeyframes || typeof document === "undefined") return;
|
|
2997
|
-
injectedKeyframes = true;
|
|
2998
|
-
const style = document.createElement("style");
|
|
2999
|
-
style.textContent = `
|
|
3000
|
-
@keyframes featuredrop-spotlight-pulse {
|
|
3001
|
-
0%, 100% { transform: scale(1); opacity: 0.6; }
|
|
3002
|
-
50% { transform: scale(1.6); opacity: 0; }
|
|
3003
|
-
}
|
|
3004
|
-
@keyframes featuredrop-pulse {
|
|
3005
|
-
0%, 100% { opacity: 1; }
|
|
3006
|
-
50% { opacity: 0.5; }
|
|
3007
|
-
}
|
|
3008
|
-
`;
|
|
3009
|
-
document.head.appendChild(style);
|
|
3010
|
-
}
|
|
3011
|
-
function prefersReducedMotion() {
|
|
3012
|
-
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
3013
|
-
return false;
|
|
3014
|
-
}
|
|
3015
|
-
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
3016
|
-
}
|
|
3017
3370
|
function Spotlight({
|
|
3018
3371
|
featureId,
|
|
3019
3372
|
targetRef,
|
|
@@ -3033,7 +3386,9 @@ function Spotlight({
|
|
|
3033
3386
|
markFeatureSeen,
|
|
3034
3387
|
acquireSpotlightSlot,
|
|
3035
3388
|
releaseSpotlightSlot,
|
|
3036
|
-
activeSpotlightCount
|
|
3389
|
+
activeSpotlightCount,
|
|
3390
|
+
animation,
|
|
3391
|
+
translations
|
|
3037
3392
|
} = useFeatureDrop();
|
|
3038
3393
|
const feature = newFeatures.find((f) => f.id === featureId);
|
|
3039
3394
|
const [isTooltipOpen, setTooltipOpen] = useState(false);
|
|
@@ -3042,13 +3397,20 @@ function Spotlight({
|
|
|
3042
3397
|
const timerRef = useRef(null);
|
|
3043
3398
|
const beaconRef = useRef(null);
|
|
3044
3399
|
const instanceIdRef = useRef(`featuredrop-spotlight-${Math.random().toString(36).slice(2, 10)}`);
|
|
3045
|
-
const
|
|
3400
|
+
const beaconPulseAnimation = useMemo(
|
|
3401
|
+
() => getPulseAnimation(animation, "beacon"),
|
|
3402
|
+
[animation]
|
|
3403
|
+
);
|
|
3404
|
+
const tooltipEnterAnimation = useMemo(
|
|
3405
|
+
() => getEnterAnimation(animation, "popover"),
|
|
3406
|
+
[animation]
|
|
3407
|
+
);
|
|
3046
3408
|
const isActive = !!feature;
|
|
3047
3409
|
const tooltipId = `${instanceIdRef.current}-tooltip`;
|
|
3048
3410
|
const tooltipTitleId = `${instanceIdRef.current}-title`;
|
|
3049
3411
|
const tooltipDescId = `${instanceIdRef.current}-description`;
|
|
3050
3412
|
useEffect(() => {
|
|
3051
|
-
|
|
3413
|
+
ensureFeatureDropAnimationStyles();
|
|
3052
3414
|
}, []);
|
|
3053
3415
|
useEffect(() => {
|
|
3054
3416
|
if (!isActive) {
|
|
@@ -3205,7 +3567,7 @@ function Spotlight({
|
|
|
3205
3567
|
{
|
|
3206
3568
|
style: {
|
|
3207
3569
|
...beaconPulseStyles,
|
|
3208
|
-
animation:
|
|
3570
|
+
animation: beaconPulseAnimation ?? "none"
|
|
3209
3571
|
}
|
|
3210
3572
|
}
|
|
3211
3573
|
)
|
|
@@ -3215,7 +3577,12 @@ function Spotlight({
|
|
|
3215
3577
|
"div",
|
|
3216
3578
|
{
|
|
3217
3579
|
id: tooltipId,
|
|
3218
|
-
style: {
|
|
3580
|
+
style: {
|
|
3581
|
+
...tooltipStyles,
|
|
3582
|
+
position: "fixed",
|
|
3583
|
+
...tooltipPosition,
|
|
3584
|
+
animation: tooltipEnterAnimation
|
|
3585
|
+
},
|
|
3219
3586
|
"data-featuredrop-tooltip": true,
|
|
3220
3587
|
role: "dialog",
|
|
3221
3588
|
"aria-modal": "false",
|
|
@@ -3237,7 +3604,7 @@ function Spotlight({
|
|
|
3237
3604
|
type: "button",
|
|
3238
3605
|
onClick: handleDismiss,
|
|
3239
3606
|
style: tooltipDismissStyles,
|
|
3240
|
-
children:
|
|
3607
|
+
children: translations.gotIt
|
|
3241
3608
|
}
|
|
3242
3609
|
)
|
|
3243
3610
|
] })
|
|
@@ -3438,8 +3805,7 @@ var toastStyles = {
|
|
|
3438
3805
|
border: "1px solid var(--featuredrop-toast-border, #e5e7eb)",
|
|
3439
3806
|
width: "var(--featuredrop-toast-width, 340px)",
|
|
3440
3807
|
maxWidth: "calc(100vw - 32px)",
|
|
3441
|
-
fontFamily: "var(--featuredrop-font-family, inherit)"
|
|
3442
|
-
animation: "featuredrop-toast-enter 0.3s ease-out"
|
|
3808
|
+
fontFamily: "var(--featuredrop-font-family, inherit)"
|
|
3443
3809
|
};
|
|
3444
3810
|
var toastBodyStyles = {
|
|
3445
3811
|
flex: 1,
|
|
@@ -3486,25 +3852,6 @@ var TYPE_INDICATORS = {
|
|
|
3486
3852
|
fix: { color: "#f59e0b", icon: "\u{1F527}" },
|
|
3487
3853
|
breaking: { color: "#ef4444", icon: "\u26A0\uFE0F" }
|
|
3488
3854
|
};
|
|
3489
|
-
var injectedToastKeyframes = false;
|
|
3490
|
-
function injectToastKeyframes() {
|
|
3491
|
-
if (injectedToastKeyframes || typeof document === "undefined") return;
|
|
3492
|
-
injectedToastKeyframes = true;
|
|
3493
|
-
const style = document.createElement("style");
|
|
3494
|
-
style.textContent = `
|
|
3495
|
-
@keyframes featuredrop-toast-enter {
|
|
3496
|
-
from { opacity: 0; transform: translateY(8px) scale(0.96); }
|
|
3497
|
-
to { opacity: 1; transform: translateY(0) scale(1); }
|
|
3498
|
-
}
|
|
3499
|
-
`;
|
|
3500
|
-
document.head.appendChild(style);
|
|
3501
|
-
}
|
|
3502
|
-
function prefersReducedMotion2() {
|
|
3503
|
-
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
3504
|
-
return false;
|
|
3505
|
-
}
|
|
3506
|
-
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
3507
|
-
}
|
|
3508
3855
|
function Toast({
|
|
3509
3856
|
featureIds,
|
|
3510
3857
|
maxVisible = 3,
|
|
@@ -3523,14 +3870,21 @@ function Toast({
|
|
|
3523
3870
|
markFeatureClicked,
|
|
3524
3871
|
trackAdoptionEvent,
|
|
3525
3872
|
getRemainingToastSlots,
|
|
3526
|
-
markToastsShown
|
|
3873
|
+
markToastsShown,
|
|
3874
|
+
animation
|
|
3527
3875
|
} = useFeatureDrop();
|
|
3528
3876
|
const [localDismissed, setLocalDismissed] = useState(/* @__PURE__ */ new Set());
|
|
3877
|
+
const [closingIds, setClosingIds] = useState(/* @__PURE__ */ new Set());
|
|
3529
3878
|
const timersRef = useRef(/* @__PURE__ */ new Map());
|
|
3530
3879
|
const shownIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
3531
|
-
const
|
|
3880
|
+
const toastEnterAnimation = useMemo(() => getEnterAnimation(animation, "toast"), [animation]);
|
|
3881
|
+
const toastExitAnimation = useMemo(() => getExitAnimation(animation, "toast"), [animation]);
|
|
3882
|
+
const toastExitDuration = useMemo(
|
|
3883
|
+
() => getAnimationDurationMs(animation, "toast"),
|
|
3884
|
+
[animation]
|
|
3885
|
+
);
|
|
3532
3886
|
useEffect(() => {
|
|
3533
|
-
|
|
3887
|
+
ensureFeatureDropAnimationStyles();
|
|
3534
3888
|
}, []);
|
|
3535
3889
|
const toastFeatures = newFeaturesSorted.filter((f) => {
|
|
3536
3890
|
if (localDismissed.has(f.id)) return false;
|
|
@@ -3550,8 +3904,14 @@ function Toast({
|
|
|
3550
3904
|
return true;
|
|
3551
3905
|
});
|
|
3552
3906
|
}, [baseVisible, remainingSlots]);
|
|
3553
|
-
const
|
|
3907
|
+
const finalizeDismiss = useCallback(
|
|
3554
3908
|
(id) => {
|
|
3909
|
+
setClosingIds((previous) => {
|
|
3910
|
+
if (!previous.has(id)) return previous;
|
|
3911
|
+
const next = new Set(previous);
|
|
3912
|
+
next.delete(id);
|
|
3913
|
+
return next;
|
|
3914
|
+
});
|
|
3555
3915
|
setLocalDismissed((prev) => new Set(prev).add(id));
|
|
3556
3916
|
dismiss(id);
|
|
3557
3917
|
const feature = newFeaturesSorted.find((f) => f.id === id);
|
|
@@ -3561,9 +3921,40 @@ function Toast({
|
|
|
3561
3921
|
clearTimeout(timer);
|
|
3562
3922
|
timersRef.current.delete(id);
|
|
3563
3923
|
}
|
|
3924
|
+
const exitTimer = timersRef.current.get(`exit:${id}`);
|
|
3925
|
+
if (exitTimer) {
|
|
3926
|
+
clearTimeout(exitTimer);
|
|
3927
|
+
timersRef.current.delete(`exit:${id}`);
|
|
3928
|
+
}
|
|
3564
3929
|
},
|
|
3565
3930
|
[dismiss, newFeaturesSorted, analytics]
|
|
3566
3931
|
);
|
|
3932
|
+
const handleDismiss = useCallback((id) => {
|
|
3933
|
+
if (closingIds.has(id)) return;
|
|
3934
|
+
if (toastExitDuration > 0 && toastExitAnimation) {
|
|
3935
|
+
const existingAutoTimer = timersRef.current.get(id);
|
|
3936
|
+
if (existingAutoTimer) {
|
|
3937
|
+
clearTimeout(existingAutoTimer);
|
|
3938
|
+
timersRef.current.delete(id);
|
|
3939
|
+
}
|
|
3940
|
+
setClosingIds((previous) => {
|
|
3941
|
+
if (previous.has(id)) return previous;
|
|
3942
|
+
const next = new Set(previous);
|
|
3943
|
+
next.add(id);
|
|
3944
|
+
return next;
|
|
3945
|
+
});
|
|
3946
|
+
const existing = timersRef.current.get(`exit:${id}`);
|
|
3947
|
+
if (existing) clearTimeout(existing);
|
|
3948
|
+
timersRef.current.set(
|
|
3949
|
+
`exit:${id}`,
|
|
3950
|
+
setTimeout(() => {
|
|
3951
|
+
finalizeDismiss(id);
|
|
3952
|
+
}, toastExitDuration)
|
|
3953
|
+
);
|
|
3954
|
+
return;
|
|
3955
|
+
}
|
|
3956
|
+
finalizeDismiss(id);
|
|
3957
|
+
}, [closingIds, finalizeDismiss, toastExitAnimation, toastExitDuration]);
|
|
3567
3958
|
const handleDismissAllLocal = useCallback(() => {
|
|
3568
3959
|
for (const f of visibleToasts) {
|
|
3569
3960
|
handleDismiss(f.id);
|
|
@@ -3572,14 +3963,14 @@ function Toast({
|
|
|
3572
3963
|
useEffect(() => {
|
|
3573
3964
|
if (autoDismissMs <= 0) return;
|
|
3574
3965
|
for (const f of visibleToasts) {
|
|
3575
|
-
if (!timersRef.current.has(f.id)) {
|
|
3966
|
+
if (!timersRef.current.has(f.id) && !closingIds.has(f.id)) {
|
|
3576
3967
|
timersRef.current.set(
|
|
3577
3968
|
f.id,
|
|
3578
3969
|
setTimeout(() => handleDismiss(f.id), autoDismissMs)
|
|
3579
3970
|
);
|
|
3580
3971
|
}
|
|
3581
3972
|
}
|
|
3582
|
-
}, [visibleToasts, autoDismissMs, handleDismiss]);
|
|
3973
|
+
}, [visibleToasts, autoDismissMs, closingIds, handleDismiss]);
|
|
3583
3974
|
useEffect(() => {
|
|
3584
3975
|
const newlyShownIds = [];
|
|
3585
3976
|
for (const feature of visibleToasts) {
|
|
@@ -3635,7 +4026,7 @@ function Toast({
|
|
|
3635
4026
|
"data-featuredrop-toast": feature.id,
|
|
3636
4027
|
style: {
|
|
3637
4028
|
...toastStyles,
|
|
3638
|
-
animation:
|
|
4029
|
+
animation: closingIds.has(feature.id) ? toastExitAnimation : toastEnterAnimation
|
|
3639
4030
|
},
|
|
3640
4031
|
role: "status",
|
|
3641
4032
|
children: [
|
|
@@ -3774,17 +4165,12 @@ var reactionButtonStyles2 = {
|
|
|
3774
4165
|
cursor: "pointer",
|
|
3775
4166
|
fontSize: "12px"
|
|
3776
4167
|
};
|
|
3777
|
-
function defaultFormatDate(date) {
|
|
3778
|
-
|
|
3779
|
-
return d.toLocaleDateString(void 0, {
|
|
3780
|
-
month: "short",
|
|
3781
|
-
day: "numeric",
|
|
3782
|
-
year: "numeric"
|
|
3783
|
-
});
|
|
4168
|
+
function defaultFormatDate(date, locale) {
|
|
4169
|
+
return formatDateForLocale(date, locale);
|
|
3784
4170
|
}
|
|
3785
4171
|
function EntryCard({
|
|
3786
4172
|
entry,
|
|
3787
|
-
formatDate
|
|
4173
|
+
formatDate,
|
|
3788
4174
|
basePath,
|
|
3789
4175
|
shareLabel,
|
|
3790
4176
|
showReactions,
|
|
@@ -3840,7 +4226,7 @@ function EntryCard({
|
|
|
3840
4226
|
)
|
|
3841
4227
|
] }),
|
|
3842
4228
|
/* @__PURE__ */ jsxs("div", { style: metaRowStyles, children: [
|
|
3843
|
-
/* @__PURE__ */ jsx("span", { children:
|
|
4229
|
+
/* @__PURE__ */ jsx("span", { children: formatDate(entry.releasedAt) }),
|
|
3844
4230
|
entry.version && /* @__PURE__ */ jsxs("span", { children: [
|
|
3845
4231
|
"v",
|
|
3846
4232
|
typeof entry.version === "string" ? entry.version : entry.version.introduced ?? entry.version.showNewUntil ?? ""
|
|
@@ -3907,7 +4293,8 @@ function ChangelogPage({
|
|
|
3907
4293
|
categories,
|
|
3908
4294
|
emptyState,
|
|
3909
4295
|
renderEntry,
|
|
3910
|
-
formatDate
|
|
4296
|
+
formatDate,
|
|
4297
|
+
dateFormat = "absolute",
|
|
3911
4298
|
basePath,
|
|
3912
4299
|
manifest: manifestProp,
|
|
3913
4300
|
className,
|
|
@@ -3917,7 +4304,7 @@ function ChangelogPage({
|
|
|
3917
4304
|
reactions = [...DEFAULT_REACTIONS],
|
|
3918
4305
|
onReaction
|
|
3919
4306
|
}) {
|
|
3920
|
-
const { manifest: contextManifest, translations } = useFeatureDrop();
|
|
4307
|
+
const { manifest: contextManifest, locale, direction, translations } = useFeatureDrop();
|
|
3921
4308
|
const themeVariables = useThemeVariables(theme);
|
|
3922
4309
|
const manifest = useMemo(
|
|
3923
4310
|
() => manifestProp ?? contextManifest ?? [],
|
|
@@ -3981,6 +4368,10 @@ function ChangelogPage({
|
|
|
3981
4368
|
if (typeof window !== "undefined") return window.location.pathname;
|
|
3982
4369
|
return "";
|
|
3983
4370
|
}, [basePath]);
|
|
4371
|
+
const resolvedFormatDate = useMemo(
|
|
4372
|
+
() => formatDate ?? ((value) => dateFormat === "relative" ? formatRelativeTimeForLocale(value, locale) : defaultFormatDate(value, locale)),
|
|
4373
|
+
[dateFormat, formatDate, locale]
|
|
4374
|
+
);
|
|
3984
4375
|
useEffect(() => {
|
|
3985
4376
|
if (typeof window === "undefined") return;
|
|
3986
4377
|
const hash = window.location.hash;
|
|
@@ -4014,7 +4405,7 @@ function ChangelogPage({
|
|
|
4014
4405
|
EntryCard,
|
|
4015
4406
|
{
|
|
4016
4407
|
entry,
|
|
4017
|
-
formatDate:
|
|
4408
|
+
formatDate: resolvedFormatDate,
|
|
4018
4409
|
basePath: resolvedBasePath,
|
|
4019
4410
|
showReactions,
|
|
4020
4411
|
shareLabel: translations.share,
|
|
@@ -4059,60 +4450,69 @@ function ChangelogPage({
|
|
|
4059
4450
|
() => ({ ...themeVariables ?? {}, ...pageStyles, ...style ?? {} }),
|
|
4060
4451
|
[themeVariables, style]
|
|
4061
4452
|
);
|
|
4062
|
-
return /* @__PURE__ */ jsxs(
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4453
|
+
return /* @__PURE__ */ jsxs(
|
|
4454
|
+
"div",
|
|
4455
|
+
{
|
|
4456
|
+
"data-featuredrop-changelog-page": true,
|
|
4457
|
+
className,
|
|
4458
|
+
style: containerStyles2,
|
|
4459
|
+
dir: direction,
|
|
4460
|
+
children: [
|
|
4461
|
+
/* @__PURE__ */ jsx("a", { href: `#${listId}`, style: skipLinkStyles, children: translations.skipToEntries }),
|
|
4462
|
+
/* @__PURE__ */ jsxs("div", { style: headerStyles2, children: [
|
|
4463
|
+
/* @__PURE__ */ jsx("h2", { style: { margin: 0 }, children: translations.changelogTitle }),
|
|
4464
|
+
showSearch && /* @__PURE__ */ jsx(
|
|
4465
|
+
"input",
|
|
4466
|
+
{
|
|
4467
|
+
style: searchStyles,
|
|
4468
|
+
type: "search",
|
|
4469
|
+
placeholder: translations.searchPlaceholder,
|
|
4470
|
+
value: query,
|
|
4471
|
+
onChange: (e) => setQuery(e.target.value),
|
|
4472
|
+
"aria-label": "Search changelog updates"
|
|
4473
|
+
}
|
|
4474
|
+
)
|
|
4475
|
+
] }),
|
|
4476
|
+
showFilters && /* @__PURE__ */ jsxs("div", { style: filterBarStyles, children: [
|
|
4477
|
+
allCategories.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4478
|
+
/* @__PURE__ */ jsx(
|
|
4479
|
+
"button",
|
|
4480
|
+
{
|
|
4481
|
+
type: "button",
|
|
4482
|
+
style: activeCategory ? pillStyles2 : pillActiveStyles,
|
|
4483
|
+
onClick: () => setActiveCategory(null),
|
|
4484
|
+
children: translations.allCategories
|
|
4485
|
+
}
|
|
4486
|
+
),
|
|
4487
|
+
allCategories.map((cat) => /* @__PURE__ */ jsx(
|
|
4488
|
+
"button",
|
|
4489
|
+
{
|
|
4490
|
+
type: "button",
|
|
4491
|
+
style: activeCategory === cat ? pillActiveStyles : pillStyles2,
|
|
4492
|
+
onClick: () => setActiveCategory(cat),
|
|
4493
|
+
children: cat
|
|
4494
|
+
},
|
|
4495
|
+
cat
|
|
4496
|
+
))
|
|
4497
|
+
] }),
|
|
4498
|
+
["feature", "improvement", "fix", "breaking"].map((t) => /* @__PURE__ */ jsx(
|
|
4499
|
+
"button",
|
|
4500
|
+
{
|
|
4501
|
+
type: "button",
|
|
4502
|
+
style: activeType === t ? pillActiveStyles : pillStyles2,
|
|
4503
|
+
onClick: () => setActiveType((prev) => prev === t ? null : t),
|
|
4504
|
+
children: t
|
|
4505
|
+
},
|
|
4506
|
+
t
|
|
4507
|
+
))
|
|
4508
|
+
] }),
|
|
4509
|
+
visible.length === 0 ? /* @__PURE__ */ jsx("div", { style: { padding: "32px 0", textAlign: "center", color: "#6b7280" }, children: emptyState ?? translations.noUpdatesYet }) : /* @__PURE__ */ jsxs("div", { id: listId, onKeyDown: handleListKeyDown, children: [
|
|
4510
|
+
renderList(),
|
|
4511
|
+
paginationControls()
|
|
4512
|
+
] })
|
|
4513
|
+
]
|
|
4514
|
+
}
|
|
4515
|
+
);
|
|
4116
4516
|
}
|
|
4117
4517
|
var tourBoxStyles = {
|
|
4118
4518
|
position: "fixed",
|
|
@@ -4235,6 +4635,10 @@ function Tour({
|
|
|
4235
4635
|
children
|
|
4236
4636
|
}) {
|
|
4237
4637
|
const context = useContext(FeatureDropContext);
|
|
4638
|
+
const dialogAnimation = useMemo(
|
|
4639
|
+
() => getEnterAnimation(context?.animation ?? "normal", "popover"),
|
|
4640
|
+
[context?.animation]
|
|
4641
|
+
);
|
|
4238
4642
|
const [isActive, setIsActive] = useState(false);
|
|
4239
4643
|
const [stepIndex, setStepIndex] = useState(-1);
|
|
4240
4644
|
const [targetRect, setTargetRect] = useState(null);
|
|
@@ -4347,6 +4751,9 @@ function Tour({
|
|
|
4347
4751
|
void openStep(next);
|
|
4348
4752
|
context?.markTourShown();
|
|
4349
4753
|
}, [context, findValidStep, id, openStep, persistence]);
|
|
4754
|
+
useEffect(() => {
|
|
4755
|
+
ensureFeatureDropAnimationStyles();
|
|
4756
|
+
}, []);
|
|
4350
4757
|
useEffect(() => {
|
|
4351
4758
|
if (!isActive || !step) return;
|
|
4352
4759
|
const updateRect = () => {
|
|
@@ -4500,9 +4907,11 @@ function Tour({
|
|
|
4500
4907
|
"aria-labelledby": titleId,
|
|
4501
4908
|
"aria-describedby": showProgress ? `${contentId} ${progressId}` : contentId,
|
|
4502
4909
|
"data-featuredrop-tour": id,
|
|
4910
|
+
dir: context?.direction,
|
|
4503
4911
|
tabIndex: -1,
|
|
4504
4912
|
style: {
|
|
4505
4913
|
...tourBoxStyles,
|
|
4914
|
+
animation: dialogAnimation,
|
|
4506
4915
|
top: tooltipPos.top,
|
|
4507
4916
|
left: tooltipPos.left
|
|
4508
4917
|
},
|
|
@@ -4960,6 +5369,7 @@ function Hotspot({
|
|
|
4960
5369
|
frequency = "once",
|
|
4961
5370
|
children
|
|
4962
5371
|
}) {
|
|
5372
|
+
const featureDrop = useContext(FeatureDropContext);
|
|
4963
5373
|
const group = useContext(TooltipGroupContext);
|
|
4964
5374
|
const [open, setOpen] = useState(false);
|
|
4965
5375
|
const [dismissed, setDismissed] = useState(false);
|
|
@@ -4967,6 +5377,23 @@ function Hotspot({
|
|
|
4967
5377
|
const hoverTimer = useRef(null);
|
|
4968
5378
|
const beaconRef = useRef(null);
|
|
4969
5379
|
const instanceIdRef = useRef(`featuredrop-hotspot-${Math.random().toString(36).slice(2, 10)}`);
|
|
5380
|
+
const animation = useMemo(
|
|
5381
|
+
() => resolveAnimationPreset(featureDrop?.animation ?? "normal", {
|
|
5382
|
+
reducedMotion: prefersReducedMotion()
|
|
5383
|
+
}),
|
|
5384
|
+
[featureDrop?.animation]
|
|
5385
|
+
);
|
|
5386
|
+
const beaconPulseAnimation = useMemo(
|
|
5387
|
+
() => getPulseAnimation(animation, "dot"),
|
|
5388
|
+
[animation]
|
|
5389
|
+
);
|
|
5390
|
+
const tooltipEnterAnimation = useMemo(
|
|
5391
|
+
() => getEnterAnimation(animation, "popover"),
|
|
5392
|
+
[animation]
|
|
5393
|
+
);
|
|
5394
|
+
useEffect(() => {
|
|
5395
|
+
ensureFeatureDropAnimationStyles();
|
|
5396
|
+
}, []);
|
|
4970
5397
|
useEffect(() => {
|
|
4971
5398
|
if (frequency === "once" && isDismissedOnce(id)) {
|
|
4972
5399
|
setDismissed(true);
|
|
@@ -5075,6 +5502,7 @@ function Hotspot({
|
|
|
5075
5502
|
boxShadow: "0 0 0 2px rgba(17,24,39,0.1)",
|
|
5076
5503
|
cursor: "pointer",
|
|
5077
5504
|
zIndex: "var(--featuredrop-hotspot-beacon-z-index, 10000)",
|
|
5505
|
+
animation: beaconPulseAnimation ?? "none",
|
|
5078
5506
|
...beaconTypeStyles[type]
|
|
5079
5507
|
}
|
|
5080
5508
|
}
|
|
@@ -5086,7 +5514,12 @@ function Hotspot({
|
|
|
5086
5514
|
role: "dialog",
|
|
5087
5515
|
"aria-modal": "false",
|
|
5088
5516
|
"data-featuredrop-hotspot-tooltip": id,
|
|
5089
|
-
style: {
|
|
5517
|
+
style: {
|
|
5518
|
+
...tooltipStyles2,
|
|
5519
|
+
top: tooltipTop,
|
|
5520
|
+
left: tooltipLeft,
|
|
5521
|
+
animation: tooltipEnterAnimation
|
|
5522
|
+
},
|
|
5090
5523
|
onMouseLeave: closeTooltip,
|
|
5091
5524
|
children: [
|
|
5092
5525
|
/* @__PURE__ */ jsx("div", { style: { fontSize: "13px", color: "#374151", lineHeight: 1.5 }, children }),
|
|
@@ -5172,7 +5605,7 @@ function FeedbackWidget({
|
|
|
5172
5605
|
style,
|
|
5173
5606
|
children
|
|
5174
5607
|
}) {
|
|
5175
|
-
const { trackAdoptionEvent, translations } = useFeatureDrop();
|
|
5608
|
+
const { trackAdoptionEvent, direction, animation, translations } = useFeatureDrop();
|
|
5176
5609
|
const [isOpen, setIsOpen] = useState(false);
|
|
5177
5610
|
const [text, setText] = useState("");
|
|
5178
5611
|
const [category, setCategory] = useState(categories[0] ?? "other");
|
|
@@ -5186,6 +5619,7 @@ function FeedbackWidget({
|
|
|
5186
5619
|
const lastFocusedElementRef = useRef(null);
|
|
5187
5620
|
const instanceIdRef = useRef(`featuredrop-feedback-${Math.random().toString(36).slice(2, 10)}`);
|
|
5188
5621
|
const rateLimitKey = useMemo(() => getRateLimitKey(featureId), [featureId]);
|
|
5622
|
+
const panelAnimation = useMemo(() => getEnterAnimation(animation, "popover"), [animation]);
|
|
5189
5623
|
const resolvedTriggerLabel = triggerLabel ?? translations.feedbackTrigger;
|
|
5190
5624
|
const resolvedTitle = title ?? translations.feedbackTitle;
|
|
5191
5625
|
const isRateLimited = useMemo(() => {
|
|
@@ -5222,6 +5656,9 @@ function FeedbackWidget({
|
|
|
5222
5656
|
window.removeEventListener("keydown", onKeyDown);
|
|
5223
5657
|
};
|
|
5224
5658
|
}, [close, isOpen]);
|
|
5659
|
+
useEffect(() => {
|
|
5660
|
+
ensureFeatureDropAnimationStyles();
|
|
5661
|
+
}, []);
|
|
5225
5662
|
const captureScreenshot = useCallback(async () => {
|
|
5226
5663
|
if (!showScreenshot) return;
|
|
5227
5664
|
try {
|
|
@@ -5341,10 +5778,11 @@ function FeedbackWidget({
|
|
|
5341
5778
|
id: `${instanceIdRef.current}-panel`,
|
|
5342
5779
|
"data-featuredrop-feedback-widget": true,
|
|
5343
5780
|
className,
|
|
5344
|
-
style: { ...panelStyles, ...style },
|
|
5781
|
+
style: { ...panelStyles, animation: panelAnimation, ...style },
|
|
5345
5782
|
role: "dialog",
|
|
5346
5783
|
"aria-modal": "false",
|
|
5347
5784
|
"aria-labelledby": titleId,
|
|
5785
|
+
dir: direction,
|
|
5348
5786
|
children: [
|
|
5349
5787
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", gap: "8px" }, children: [
|
|
5350
5788
|
/* @__PURE__ */ jsx("strong", { id: titleId, children: resolvedTitle }),
|
|
@@ -5354,7 +5792,7 @@ function FeedbackWidget({
|
|
|
5354
5792
|
type: "button",
|
|
5355
5793
|
onClick: close,
|
|
5356
5794
|
style: { border: "none", background: "transparent", cursor: "pointer" },
|
|
5357
|
-
"aria-label":
|
|
5795
|
+
"aria-label": translations.close,
|
|
5358
5796
|
children: "x"
|
|
5359
5797
|
}
|
|
5360
5798
|
)
|
|
@@ -5586,6 +6024,7 @@ function AnnouncementModal({
|
|
|
5586
6024
|
}) {
|
|
5587
6025
|
const context = useContext(FeatureDropContext);
|
|
5588
6026
|
const [isOpen, setIsOpen] = useState(defaultOpen);
|
|
6027
|
+
const [isClosing, setIsClosing] = useState(false);
|
|
5589
6028
|
const [slideIndex, setSlideIndex] = useState(0);
|
|
5590
6029
|
const [blockedByFrequency, setBlockedByFrequency] = useState(false);
|
|
5591
6030
|
const [isMobile, setIsMobile] = useState(
|
|
@@ -5593,6 +6032,7 @@ function AnnouncementModal({
|
|
|
5593
6032
|
);
|
|
5594
6033
|
const modalRef = useRef(null);
|
|
5595
6034
|
const lastFocusedElementRef = useRef(null);
|
|
6035
|
+
const closeTimerRef = useRef(null);
|
|
5596
6036
|
const instanceIdRef = useRef(`featuredrop-announcement-${Math.random().toString(36).slice(2, 10)}`);
|
|
5597
6037
|
const resolvedFeature = useMemo(() => {
|
|
5598
6038
|
if (feature) return feature;
|
|
@@ -5608,8 +6048,15 @@ function AnnouncementModal({
|
|
|
5608
6048
|
);
|
|
5609
6049
|
const currentSlide = resolvedSlides[slideIndex] ?? null;
|
|
5610
6050
|
const t = context?.translations;
|
|
6051
|
+
const enterAnimation = getEnterAnimation(context?.animation ?? "normal", "modal");
|
|
6052
|
+
const exitAnimation = getExitAnimation(context?.animation ?? "normal", "modal");
|
|
5611
6053
|
const open = useCallback(() => {
|
|
5612
6054
|
if (blockedByFrequency || resolvedSlides.length === 0) return;
|
|
6055
|
+
if (closeTimerRef.current) {
|
|
6056
|
+
clearTimeout(closeTimerRef.current);
|
|
6057
|
+
closeTimerRef.current = null;
|
|
6058
|
+
}
|
|
6059
|
+
setIsClosing(false);
|
|
5613
6060
|
if (typeof document !== "undefined" && document.activeElement instanceof HTMLElement) {
|
|
5614
6061
|
lastFocusedElementRef.current = document.activeElement;
|
|
5615
6062
|
}
|
|
@@ -5632,7 +6079,22 @@ function AnnouncementModal({
|
|
|
5632
6079
|
open();
|
|
5633
6080
|
}, [defaultOpen, open]);
|
|
5634
6081
|
const close = useCallback(() => {
|
|
6082
|
+
if (closeTimerRef.current) {
|
|
6083
|
+
clearTimeout(closeTimerRef.current);
|
|
6084
|
+
closeTimerRef.current = null;
|
|
6085
|
+
}
|
|
5635
6086
|
setIsOpen(false);
|
|
6087
|
+
const animationPreset = context?.animation ?? "normal";
|
|
6088
|
+
const exitDuration = getAnimationDurationMs(animationPreset, "modal");
|
|
6089
|
+
if (exitDuration > 0) {
|
|
6090
|
+
setIsClosing(true);
|
|
6091
|
+
closeTimerRef.current = setTimeout(() => {
|
|
6092
|
+
setIsClosing(false);
|
|
6093
|
+
closeTimerRef.current = null;
|
|
6094
|
+
}, exitDuration);
|
|
6095
|
+
} else {
|
|
6096
|
+
setIsClosing(false);
|
|
6097
|
+
}
|
|
5636
6098
|
const returnTarget = lastFocusedElementRef.current;
|
|
5637
6099
|
if (returnTarget) {
|
|
5638
6100
|
if (typeof requestAnimationFrame === "function") {
|
|
@@ -5641,10 +6103,10 @@ function AnnouncementModal({
|
|
|
5641
6103
|
returnTarget.focus();
|
|
5642
6104
|
}
|
|
5643
6105
|
}
|
|
5644
|
-
}, []);
|
|
6106
|
+
}, [context?.animation]);
|
|
5645
6107
|
const dismiss = useCallback(() => {
|
|
5646
|
-
close();
|
|
5647
6108
|
setBlockedByFrequency(true);
|
|
6109
|
+
close();
|
|
5648
6110
|
if (frequency === "once") {
|
|
5649
6111
|
setDismissedOnce2(modalId);
|
|
5650
6112
|
} else if (frequency === "every-session") {
|
|
@@ -5677,12 +6139,17 @@ function AnnouncementModal({
|
|
|
5677
6139
|
}, [frequency, modalId]);
|
|
5678
6140
|
useEffect(() => {
|
|
5679
6141
|
if (trigger !== "auto") return;
|
|
5680
|
-
if (blockedByFrequency || isOpen || resolvedSlides.length === 0) return;
|
|
6142
|
+
if (blockedByFrequency || isOpen || isClosing || resolvedSlides.length === 0) return;
|
|
6143
|
+
if (frequency === "once" && isDismissedOnce2(modalId)) return;
|
|
6144
|
+
if (frequency === "every-session" && sessionDismissed2.has(modalId)) return;
|
|
5681
6145
|
if (resolvedFeature && resolvedFeature.priority !== "critical") return;
|
|
5682
6146
|
open();
|
|
5683
6147
|
}, [
|
|
6148
|
+
frequency,
|
|
5684
6149
|
blockedByFrequency,
|
|
6150
|
+
isClosing,
|
|
5685
6151
|
isOpen,
|
|
6152
|
+
modalId,
|
|
5686
6153
|
open,
|
|
5687
6154
|
resolvedFeature,
|
|
5688
6155
|
resolvedSlides.length,
|
|
@@ -5699,6 +6166,12 @@ function AnnouncementModal({
|
|
|
5699
6166
|
window.removeEventListener("resize", updateViewportMode);
|
|
5700
6167
|
};
|
|
5701
6168
|
}, [mobileBreakpoint]);
|
|
6169
|
+
useEffect(() => {
|
|
6170
|
+
ensureFeatureDropAnimationStyles();
|
|
6171
|
+
return () => {
|
|
6172
|
+
if (closeTimerRef.current) clearTimeout(closeTimerRef.current);
|
|
6173
|
+
};
|
|
6174
|
+
}, []);
|
|
5702
6175
|
useEffect(() => {
|
|
5703
6176
|
if (!isOpen) return;
|
|
5704
6177
|
const modalEl = modalRef.current;
|
|
@@ -5766,7 +6239,7 @@ function AnnouncementModal({
|
|
|
5766
6239
|
if (children) {
|
|
5767
6240
|
return /* @__PURE__ */ jsx(Fragment, { children: children(renderProps) });
|
|
5768
6241
|
}
|
|
5769
|
-
if (!isOpen ||
|
|
6242
|
+
if (!(isOpen || isClosing) || !currentSlide) return null;
|
|
5770
6243
|
const embeddedVideo = toEmbedUrl(currentSlide.videoUrl);
|
|
5771
6244
|
const descriptionHtml = currentSlide.description ? parseDescription(currentSlide.description) : null;
|
|
5772
6245
|
const totalSlides = resolvedSlides.length;
|
|
@@ -5792,9 +6265,11 @@ function AnnouncementModal({
|
|
|
5792
6265
|
"aria-describedby": currentSlide.description ? descriptionId : void 0,
|
|
5793
6266
|
"data-featuredrop-announcement-modal": modalId,
|
|
5794
6267
|
className,
|
|
6268
|
+
dir: context?.direction,
|
|
5795
6269
|
tabIndex: -1,
|
|
5796
6270
|
style: {
|
|
5797
6271
|
...isMobile ? mobileModalStyles : desktopModalStyles,
|
|
6272
|
+
animation: isClosing ? exitAnimation : enterAnimation,
|
|
5798
6273
|
...style
|
|
5799
6274
|
},
|
|
5800
6275
|
children: /* @__PURE__ */ jsxs("div", { style: { padding: isMobile ? "16px" : "20px" }, children: [
|
|
@@ -5964,8 +6439,7 @@ var beaconStyles2 = {
|
|
|
5964
6439
|
border: "2px solid #fff",
|
|
5965
6440
|
background: "#f59e0b",
|
|
5966
6441
|
boxShadow: "0 0 0 2px rgba(17,24,39,0.12)",
|
|
5967
|
-
zIndex: "var(--featuredrop-spotlight-chain-beacon-z-index, 10010)"
|
|
5968
|
-
animation: "featuredrop-chain-pulse 1.8s ease-in-out infinite"
|
|
6442
|
+
zIndex: "var(--featuredrop-spotlight-chain-beacon-z-index, 10010)"
|
|
5969
6443
|
};
|
|
5970
6444
|
var tooltipStyles3 = {
|
|
5971
6445
|
position: "fixed",
|
|
@@ -5977,25 +6451,6 @@ var tooltipStyles3 = {
|
|
|
5977
6451
|
boxShadow: "0 10px 30px rgba(0,0,0,0.16)",
|
|
5978
6452
|
width: "min(90vw, 320px)"
|
|
5979
6453
|
};
|
|
5980
|
-
var injectedKeyframes2 = false;
|
|
5981
|
-
function injectKeyframes2() {
|
|
5982
|
-
if (injectedKeyframes2 || typeof document === "undefined") return;
|
|
5983
|
-
injectedKeyframes2 = true;
|
|
5984
|
-
const style = document.createElement("style");
|
|
5985
|
-
style.textContent = `
|
|
5986
|
-
@keyframes featuredrop-chain-pulse {
|
|
5987
|
-
0%, 100% { transform: scale(1); opacity: 1; }
|
|
5988
|
-
50% { transform: scale(1.35); opacity: 0.65; }
|
|
5989
|
-
}
|
|
5990
|
-
`;
|
|
5991
|
-
document.head.appendChild(style);
|
|
5992
|
-
}
|
|
5993
|
-
function prefersReducedMotion3() {
|
|
5994
|
-
if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
|
|
5995
|
-
return false;
|
|
5996
|
-
}
|
|
5997
|
-
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
5998
|
-
}
|
|
5999
6454
|
function getFocusableElements4(container) {
|
|
6000
6455
|
const nodes = container.querySelectorAll(
|
|
6001
6456
|
[
|
|
@@ -6024,12 +6479,26 @@ function SpotlightChain({
|
|
|
6024
6479
|
onSkip,
|
|
6025
6480
|
children
|
|
6026
6481
|
}) {
|
|
6482
|
+
const featureDrop = useContext(FeatureDropContext);
|
|
6027
6483
|
const [isActive, setIsActive] = useState(false);
|
|
6028
6484
|
const [stepIndex, setStepIndex] = useState(-1);
|
|
6029
6485
|
const [rect, setRect] = useState(null);
|
|
6030
6486
|
const autoTimerRef = useRef(null);
|
|
6031
6487
|
const dialogRef = useRef(null);
|
|
6032
|
-
const
|
|
6488
|
+
const animation = useMemo(
|
|
6489
|
+
() => resolveAnimationPreset(featureDrop?.animation ?? "normal", {
|
|
6490
|
+
reducedMotion: prefersReducedMotion()
|
|
6491
|
+
}),
|
|
6492
|
+
[featureDrop?.animation]
|
|
6493
|
+
);
|
|
6494
|
+
const beaconPulseAnimation = useMemo(
|
|
6495
|
+
() => getPulseAnimation(animation, "beacon"),
|
|
6496
|
+
[animation]
|
|
6497
|
+
);
|
|
6498
|
+
const tooltipEnterAnimation = useMemo(
|
|
6499
|
+
() => getEnterAnimation(animation, "popover"),
|
|
6500
|
+
[animation]
|
|
6501
|
+
);
|
|
6033
6502
|
const instanceIdRef = useRef(`featuredrop-spotlight-chain-${Math.random().toString(36).slice(2, 10)}`);
|
|
6034
6503
|
const step = stepIndex >= 0 ? steps[stepIndex] ?? null : null;
|
|
6035
6504
|
const findValidStep = useCallback((start2) => {
|
|
@@ -6079,7 +6548,7 @@ function SpotlightChain({
|
|
|
6079
6548
|
setRect(null);
|
|
6080
6549
|
}, [onSkip, step, stepIndex]);
|
|
6081
6550
|
useEffect(() => {
|
|
6082
|
-
|
|
6551
|
+
ensureFeatureDropAnimationStyles();
|
|
6083
6552
|
}, []);
|
|
6084
6553
|
useEffect(() => {
|
|
6085
6554
|
if (!startOnMount) return;
|
|
@@ -6186,7 +6655,7 @@ function SpotlightChain({
|
|
|
6186
6655
|
"data-featuredrop-spotlight-chain-beacon": step.id ?? stepIndex,
|
|
6187
6656
|
style: {
|
|
6188
6657
|
...beaconStyles2,
|
|
6189
|
-
animation:
|
|
6658
|
+
animation: beaconPulseAnimation ?? "none",
|
|
6190
6659
|
top: rect.top - 7,
|
|
6191
6660
|
left: rect.right - 7
|
|
6192
6661
|
}
|
|
@@ -6202,7 +6671,12 @@ function SpotlightChain({
|
|
|
6202
6671
|
"aria-describedby": contentId,
|
|
6203
6672
|
"data-featuredrop-spotlight-chain": step.id ?? stepIndex,
|
|
6204
6673
|
tabIndex: -1,
|
|
6205
|
-
style: {
|
|
6674
|
+
style: {
|
|
6675
|
+
...tooltipStyles3,
|
|
6676
|
+
top: tooltipTop,
|
|
6677
|
+
left: tooltipLeft,
|
|
6678
|
+
animation: tooltipEnterAnimation
|
|
6679
|
+
},
|
|
6206
6680
|
children: [
|
|
6207
6681
|
step.title && /* @__PURE__ */ jsx("p", { id: titleId, style: { margin: "0 0 6px", fontWeight: 700, fontSize: "15px" }, children: step.title }),
|
|
6208
6682
|
/* @__PURE__ */ jsx("div", { id: contentId, style: { margin: "0 0 10px", fontSize: "14px", color: "#4b5563" }, children: step.content }),
|
|
@@ -6219,7 +6693,7 @@ function SpotlightChain({
|
|
|
6219
6693
|
padding: "6px 10px",
|
|
6220
6694
|
cursor: "pointer"
|
|
6221
6695
|
},
|
|
6222
|
-
children: "Skip"
|
|
6696
|
+
children: featureDrop?.translations.skip ?? "Skip"
|
|
6223
6697
|
}
|
|
6224
6698
|
),
|
|
6225
6699
|
/* @__PURE__ */ jsx(
|
|
@@ -6235,7 +6709,7 @@ function SpotlightChain({
|
|
|
6235
6709
|
padding: "6px 10px",
|
|
6236
6710
|
cursor: "pointer"
|
|
6237
6711
|
},
|
|
6238
|
-
children: stepIndex >= steps.length - 1 ? "Got it" : "Next"
|
|
6712
|
+
children: stepIndex >= steps.length - 1 ? featureDrop?.translations.gotIt ?? "Got it" : featureDrop?.translations.next ?? "Next"
|
|
6239
6713
|
}
|
|
6240
6714
|
)
|
|
6241
6715
|
] })
|
|
@@ -6422,6 +6896,11 @@ function Survey({
|
|
|
6422
6896
|
const askLaterCooldownDays = triggerRules?.askLaterCooldownDays ?? DEFAULT_ASK_LATER_DAYS;
|
|
6423
6897
|
const scale = useMemo(() => resolveScale(type), [type]);
|
|
6424
6898
|
const translations = context?.translations;
|
|
6899
|
+
const direction = context?.direction ?? "ltr";
|
|
6900
|
+
const panelAnimation = useMemo(
|
|
6901
|
+
() => getEnterAnimation(context?.animation ?? "normal", "modal"),
|
|
6902
|
+
[context?.animation]
|
|
6903
|
+
);
|
|
6425
6904
|
const canShow = useMemo(() => {
|
|
6426
6905
|
const now = Date.now();
|
|
6427
6906
|
const cooldownUntil = parseIsoTime(readStorageValue3(cooldownStorageKey(id)));
|
|
@@ -6511,6 +6990,9 @@ function Survey({
|
|
|
6511
6990
|
if (!defaultOpen) return;
|
|
6512
6991
|
show({ force: true });
|
|
6513
6992
|
}, [defaultOpen, show]);
|
|
6993
|
+
useEffect(() => {
|
|
6994
|
+
ensureFeatureDropAnimationStyles();
|
|
6995
|
+
}, []);
|
|
6514
6996
|
useEffect(() => {
|
|
6515
6997
|
if (!isOpen) return;
|
|
6516
6998
|
const panel = panelRef.current;
|
|
@@ -6686,12 +7168,13 @@ function Survey({
|
|
|
6686
7168
|
ref: panelRef,
|
|
6687
7169
|
"data-featuredrop-survey": id,
|
|
6688
7170
|
className,
|
|
6689
|
-
style: { ...panelStyles2, ...style },
|
|
7171
|
+
style: { ...panelStyles2, animation: panelAnimation, ...style },
|
|
6690
7172
|
role: "dialog",
|
|
6691
7173
|
"aria-modal": "false",
|
|
6692
7174
|
"aria-labelledby": surveyTitleId,
|
|
6693
7175
|
"aria-describedby": prompt ? surveyDescriptionId : void 0,
|
|
6694
7176
|
tabIndex: -1,
|
|
7177
|
+
dir: direction,
|
|
6695
7178
|
children: [
|
|
6696
7179
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center", gap: "8px" }, children: [
|
|
6697
7180
|
/* @__PURE__ */ jsx("strong", { id: surveyTitleId, children: surveyTitle }),
|
|
@@ -7255,6 +7738,24 @@ function FeatureRequestForm({
|
|
|
7255
7738
|
);
|
|
7256
7739
|
}
|
|
7257
7740
|
|
|
7258
|
-
|
|
7741
|
+
// src/react/index.ts
|
|
7742
|
+
var NewBadge2 = withFeatureDropBoundary(NewBadge, "NewBadge");
|
|
7743
|
+
var ChangelogWidget2 = withFeatureDropBoundary(ChangelogWidget, "ChangelogWidget");
|
|
7744
|
+
var Spotlight2 = withFeatureDropBoundary(Spotlight, "Spotlight");
|
|
7745
|
+
var Banner2 = withFeatureDropBoundary(Banner, "Banner");
|
|
7746
|
+
var Toast2 = withFeatureDropBoundary(Toast, "Toast");
|
|
7747
|
+
var ChangelogPage2 = withFeatureDropBoundary(ChangelogPage, "ChangelogPage");
|
|
7748
|
+
var Tour2 = withFeatureDropBoundary(Tour, "Tour");
|
|
7749
|
+
var Checklist2 = withFeatureDropBoundary(Checklist, "Checklist");
|
|
7750
|
+
var Hotspot2 = withFeatureDropBoundary(Hotspot, "Hotspot");
|
|
7751
|
+
var TooltipGroup2 = withFeatureDropBoundary(TooltipGroup, "TooltipGroup");
|
|
7752
|
+
var FeedbackWidget2 = withFeatureDropBoundary(FeedbackWidget, "FeedbackWidget");
|
|
7753
|
+
var AnnouncementModal2 = withFeatureDropBoundary(AnnouncementModal, "AnnouncementModal");
|
|
7754
|
+
var SpotlightChain2 = withFeatureDropBoundary(SpotlightChain, "SpotlightChain");
|
|
7755
|
+
var Survey2 = withFeatureDropBoundary(Survey, "Survey");
|
|
7756
|
+
var FeatureRequestButton2 = withFeatureDropBoundary(FeatureRequestButton, "FeatureRequestButton");
|
|
7757
|
+
var FeatureRequestForm2 = withFeatureDropBoundary(FeatureRequestForm, "FeatureRequestForm");
|
|
7758
|
+
|
|
7759
|
+
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 };
|
|
7259
7760
|
//# sourceMappingURL=react.js.map
|
|
7260
7761
|
//# sourceMappingURL=react.js.map
|