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