ng-miam 9.1.29 → 9.1.30

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.
@@ -1838,6 +1838,178 @@
1838
1838
  analyticsEnabled: true // Only used in DEV mode
1839
1839
  };
1840
1840
 
1841
+ var WINDOW_SINGLETON_KEY = '__mealzRecipeCardShowTracker__';
1842
+ /**
1843
+ * Tracks recipe.show events and prevents duplicates for 5 minutes per recipe.
1844
+ * Shared across SDK and Lit recipe cards via {@link WINDOW_SINGLETON_KEY} on window.
1845
+ */
1846
+ var RecipeCardShowTracker = /** @class */ (function () {
1847
+ function RecipeCardShowTracker() {
1848
+ var _this = this;
1849
+ this.trackedRecipes = new Map();
1850
+ this.cleanupInterval = null;
1851
+ this.MAX_RECIPES = 1000;
1852
+ this.CLEANUP_INTERVAL = 5 * 60 * 1000;
1853
+ this.SHOW_COOLDOWN_MS = 5 * 60 * 1000;
1854
+ this.handlePageUnload = function () {
1855
+ _this.destroy();
1856
+ };
1857
+ this.startAutoCleanup();
1858
+ this.setupPageUnloadListener();
1859
+ }
1860
+ RecipeCardShowTracker.getInstance = function () {
1861
+ var w = typeof window !== 'undefined'
1862
+ ? window
1863
+ : undefined;
1864
+ var fromWindow = w === null || w === void 0 ? void 0 : w[WINDOW_SINGLETON_KEY];
1865
+ if (fromWindow) {
1866
+ RecipeCardShowTracker.instance = fromWindow;
1867
+ return fromWindow;
1868
+ }
1869
+ if (!RecipeCardShowTracker.instance) {
1870
+ RecipeCardShowTracker.instance = new RecipeCardShowTracker();
1871
+ if (w) {
1872
+ w[WINDOW_SINGLETON_KEY] = RecipeCardShowTracker.instance;
1873
+ }
1874
+ }
1875
+ return RecipeCardShowTracker.instance;
1876
+ };
1877
+ RecipeCardShowTracker.prototype.trackRecipeShow = function (recipeId, analyticsPath, categoryId) {
1878
+ var _a, _b;
1879
+ var now = Date.now();
1880
+ var lastShowTime = this.trackedRecipes.get(recipeId);
1881
+ if (lastShowTime && (now - lastShowTime) < this.SHOW_COOLDOWN_MS) {
1882
+ return;
1883
+ }
1884
+ if (this.trackedRecipes.size >= this.MAX_RECIPES) {
1885
+ this.cleanOldRecipes();
1886
+ }
1887
+ this.trackedRecipes.set(recipeId, now);
1888
+ (_b = (_a = window.mealzInternal) === null || _a === void 0 ? void 0 : _a.analytics) === null || _b === void 0 ? void 0 : _b.sendEvent('recipe.show', analyticsPath, {
1889
+ recipe_id: recipeId,
1890
+ category_id: categoryId
1891
+ });
1892
+ };
1893
+ RecipeCardShowTracker.prototype.cleanOldRecipes = function () {
1894
+ var e_1, _c;
1895
+ var now = Date.now();
1896
+ var oneHourAgo = now - (60 * 60 * 1000);
1897
+ try {
1898
+ for (var _d = __values(this.trackedRecipes.entries()), _e = _d.next(); !_e.done; _e = _d.next()) {
1899
+ var _f = __read(_e.value, 2), recipeId = _f[0], timestamp = _f[1];
1900
+ if (timestamp < oneHourAgo) {
1901
+ this.trackedRecipes.delete(recipeId);
1902
+ }
1903
+ }
1904
+ }
1905
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
1906
+ finally {
1907
+ try {
1908
+ if (_e && !_e.done && (_c = _d.return)) _c.call(_d);
1909
+ }
1910
+ finally { if (e_1) throw e_1.error; }
1911
+ }
1912
+ };
1913
+ RecipeCardShowTracker.prototype.clearAllRecipes = function () {
1914
+ this.trackedRecipes.clear();
1915
+ };
1916
+ RecipeCardShowTracker.prototype.destroy = function () {
1917
+ window.removeEventListener('beforeunload', this.handlePageUnload);
1918
+ if (this.cleanupInterval) {
1919
+ clearInterval(this.cleanupInterval);
1920
+ this.cleanupInterval = null;
1921
+ }
1922
+ this.trackedRecipes.clear();
1923
+ RecipeCardShowTracker.instance = null;
1924
+ if (typeof window !== 'undefined') {
1925
+ delete window[WINDOW_SINGLETON_KEY];
1926
+ }
1927
+ };
1928
+ RecipeCardShowTracker.prototype.startAutoCleanup = function () {
1929
+ var _this = this;
1930
+ this.cleanupInterval = window.setInterval(function () {
1931
+ _this.cleanOldRecipes();
1932
+ }, this.CLEANUP_INTERVAL);
1933
+ };
1934
+ RecipeCardShowTracker.prototype.setupPageUnloadListener = function () {
1935
+ window.addEventListener('beforeunload', this.handlePageUnload);
1936
+ };
1937
+ return RecipeCardShowTracker;
1938
+ }());
1939
+ RecipeCardShowTracker.instance = null;
1940
+
1941
+ var ViewportListenerParams = /** @class */ (function () {
1942
+ function ViewportListenerParams() {
1943
+ this.condition = true;
1944
+ this.threshold = 0;
1945
+ this.debounce = 0;
1946
+ }
1947
+ return ViewportListenerParams;
1948
+ }());
1949
+ var ViewportListener = /** @class */ (function () {
1950
+ function ViewportListener(element, callback, params) {
1951
+ var _this = this;
1952
+ if (params === void 0) { params = {}; }
1953
+ this.element = element;
1954
+ this.callback = callback;
1955
+ this.params = params;
1956
+ this.intersectionSubject = new rxjs.Subject();
1957
+ this.subscriptions = [];
1958
+ this.params = Object.assign(Object.assign({}, new ViewportListenerParams()), params);
1959
+ var options = {
1960
+ root: null,
1961
+ rootMargin: '0px',
1962
+ threshold: this.params.threshold
1963
+ };
1964
+ this.observer = new IntersectionObserver(function (entries) {
1965
+ entries.forEach(function (entry) { return _this.intersectionSubject.next(entry); });
1966
+ }, options);
1967
+ this.connect();
1968
+ }
1969
+ ViewportListener.prototype.connect = function () {
1970
+ var _this = this;
1971
+ this.subscriptions.push(this.intersectionSubject
1972
+ .pipe(operators.debounceTime(this.params.debounce))
1973
+ .subscribe(function (entry) { return _this.handleIntersection(entry); }));
1974
+ this.observer.observe(this.element);
1975
+ };
1976
+ ViewportListener.prototype.disconnect = function () {
1977
+ if (this.observer) {
1978
+ this.observer.disconnect();
1979
+ }
1980
+ this.intersectionSubject.complete();
1981
+ this.subscriptions.forEach(function (sub) { return sub.unsubscribe(); });
1982
+ };
1983
+ ViewportListener.prototype.handleIntersection = function (entry) {
1984
+ if (this.params.condition && entry.isIntersecting) {
1985
+ this.callback();
1986
+ }
1987
+ };
1988
+ return ViewportListener;
1989
+ }());
1990
+
1991
+ var RECIPE_CARD_SHOW_ANALYTICS_PATH = '/recipes';
1992
+ /** Same visibility rule as `mealz-recipe-card`: IntersectionObserver ratio ≥ this value. */
1993
+ var RECIPE_CARD_SHOW_VISIBILITY_THRESHOLD = 0.8;
1994
+ /** Same timing as `mealz-recipe-card`: debounce on intersection stream (ms). */
1995
+ var RECIPE_CARD_SHOW_DEBOUNCE_MS = 1000;
1996
+ /**
1997
+ * Same `recipe.show` pipeline as `mealz-recipe-card`: viewport visibility + deduped tracking.
1998
+ * Call `disconnect()` when the host node is removed (virtual lists, SPA navigation).
1999
+ */
2000
+ function attachRecipeCardShowTracking(options) {
2001
+ var element = options.element, recipeId = options.recipeId, _a = options.analyticsPath, analyticsPath = _a === void 0 ? RECIPE_CARD_SHOW_ANALYTICS_PATH : _a, _b = options.categoryId, categoryId = _b === void 0 ? '' : _b;
2002
+ var listener = new ViewportListener(element, function () {
2003
+ RecipeCardShowTracker.getInstance().trackRecipeShow(recipeId, analyticsPath, categoryId);
2004
+ }, {
2005
+ threshold: RECIPE_CARD_SHOW_VISIBILITY_THRESHOLD,
2006
+ debounce: RECIPE_CARD_SHOW_DEBOUNCE_MS
2007
+ });
2008
+ return {
2009
+ disconnect: function () { return listener.disconnect(); }
2010
+ };
2011
+ }
2012
+
1841
2013
  var Ingredient = /** @class */ (function (_super) {
1842
2014
  __extends(Ingredient, _super);
1843
2015
  function Ingredient() {
@@ -3651,7 +3823,7 @@
3651
3823
  EventJourney["EMPTY"] = "";
3652
3824
  })(EventJourney || (EventJourney = {}));
3653
3825
 
3654
- var VERSION = "9.1.29"; // TODO: replace by ##VERSION## and update it in the CI/CD
3826
+ var VERSION = "9.1.30"; // TODO: replace by ##VERSION## and update it in the CI/CD
3655
3827
 
3656
3828
  var ContextRegistryService = /** @class */ (function () {
3657
3829
  function ContextRegistryService() {
@@ -8130,7 +8302,8 @@
8130
8302
  _this.analyticsService.init(domain);
8131
8303
  },
8132
8304
  eventSent$: this.analyticsService.eventEmitter,
8133
- setAbTestKey: function (key) { return _this.analyticsService.setAbTestKey(key); }
8305
+ setAbTestKey: function (key) { return _this.analyticsService.setAbTestKey(key); },
8306
+ attachRecipeCardShowTracking: attachRecipeCardShowTracking
8134
8307
  },
8135
8308
  basket: {
8136
8309
  basketIsReady$: this.basketsService.basketStats$.pipe(operators.skipWhile(function (stats) { return !stats; }), operators.take(1), operators.map(function () { return true; })),