@useinsider/guido 3.21.0-beta.27e5667 → 3.21.0-beta.7e166b5

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.
@@ -1,22 +1,22 @@
1
- var D = Object.defineProperty;
2
- var A = (l, c, e) => c in l ? D(l, c, { enumerable: !0, configurable: !0, writable: !0, value: e }) : l[c] = e;
3
- var m = (l, c, e) => A(l, typeof c != "symbol" ? c + "" : c, e);
4
- import { useConfig as u } from "../../../composables/useConfig.js";
5
- import { BlockId as C } from "../../../enums/block.js";
6
- import { getMigrationBannerHtml as E } from "../../../utils/migrationBannerHtml.js";
1
+ var A = Object.defineProperty;
2
+ var b = (c, l, e) => l in c ? A(c, l, { enumerable: !0, configurable: !0, writable: !0, value: e }) : c[l] = e;
3
+ var m = (c, l, e) => b(c, typeof l != "symbol" ? l + "" : l, e);
4
+ import { useConfig as d } from "../../../composables/useConfig.js";
5
+ import { BlockId as E } from "../../../enums/block.js";
6
+ import { getMigrationBannerHtml as C } from "../../../utils/migrationBannerHtml.js";
7
7
  import { Block as S, BlockCompositionType as N, ModificationDescription as p } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
8
- import { CURRENT_CONFIG_VERSION as v, PRE_RRS_CONFIG_VERSION as M } from "./constants/defaultConfig.js";
9
- import { RECOMMENDATION_ID_ATTR as d } from "./constants/selectors.js";
10
- import { regenerateMobileProductRows as w } from "./controls/main/utils.js";
11
- import { ensureMobileCssRulesExist as I, setMobileLayoutOptOut as k, hasMobileLayoutOptOut as O } from "./controls/mobileLayout/cssRules.js";
8
+ import { CURRENT_CONFIG_VERSION as v, PRE_RRS_CONFIG_VERSION as w } from "./constants/defaultConfig.js";
9
+ import { RECOMMENDATION_ID_ATTR as h } from "./constants/selectors.js";
10
+ import { regenerateMobileProductRows as M } from "./controls/main/utils.js";
11
+ import { ensureMobileCssRulesExist as I, setMobileLayoutOptOut as R, hasMobileLayoutOptOut as O } from "./controls/mobileLayout/cssRules.js";
12
12
  import { RecommendationConfigService as o } from "./services/configService.js";
13
13
  import { useRecommendationExtensionStore as f } from "./store/recommendation.js";
14
14
  import { getDefaultTemplate as T } from "./templates/grid/template.js";
15
15
  import { useRecommendationBlockWarning as x } from "./useRecommendationBlockWarning.js";
16
- import { registerNodeConfigWriter as R } from "./utils/nodeConfigWriter.js";
17
- import { refreshArrivedStrategyBlocks as H, refreshDuplicatedStrategyBlocks as $ } from "./utils/strategyCommit.js";
18
- const y = C.Recommendation, g = "recommendation-block-v2", B = "hide-price";
19
- let b = !1;
16
+ import { registerNodeConfigWriter as k } from "./utils/nodeConfigWriter.js";
17
+ import { refreshArrivedStrategyBlocks as $, refreshDuplicatedStrategyBlocks as H } from "./utils/strategyCommit.js";
18
+ const y = E.Recommendation, u = "recommendation-block-v2", B = "hide-price";
19
+ let D = !1;
20
20
  class Z extends S {
21
21
  constructor() {
22
22
  super();
@@ -30,6 +30,8 @@ class Z extends S {
30
30
  /** Ids handed to duplicates the document root does not show yet: a copied module renames all its blocks at once. */
31
31
  m(this, "_unsettledDuplicateIds", /* @__PURE__ */ new Set());
32
32
  m(this, "_arrivedNodes", []);
33
+ /** Ids whose arrival or duplicate refresh is in flight, so a second refresh of the same block does not race it. */
34
+ m(this, "_refreshingIds", /* @__PURE__ */ new Set());
33
35
  }
34
36
  getId() {
35
37
  return y;
@@ -49,7 +51,7 @@ class Z extends S {
49
51
  );
50
52
  }
51
53
  getSettingsPanelTitleHtml() {
52
- return E(
54
+ return C(
53
55
  y,
54
56
  this.api.translate("Recommendation Block"),
55
57
  this.api.translate("This block is switched from the Old Version to the New Version. We recommend you check the Recommendation block and test your message to ensure it works properly.")
@@ -89,10 +91,10 @@ class Z extends S {
89
91
  this._handleDuplicate(e, t), this._scheduleArrivalReset(e);
90
92
  return;
91
93
  }
92
- const h = this._pendingBlockId === null;
94
+ const g = this._pendingBlockId === null;
93
95
  setTimeout(() => {
94
96
  if (this._getBlockElement(e)) {
95
- if (h && this._detectDuplicate(t)) {
97
+ if (g && this._detectDuplicate(t)) {
96
98
  this._handleDuplicate(e, t);
97
99
  return;
98
100
  }
@@ -103,28 +105,37 @@ class Z extends S {
103
105
  }
104
106
  const i = this._pendingBlockId ?? this._generateNextId();
105
107
  this._pendingBlockId = null, this._assignRecommendationId(e, i);
106
- const r = u().isFeatureEnabled("reusableRecommendationStrategy"), n = r && !o.hasConfig(e), { config: s, wasFreshDrop: a } = o.initializeConfig(
108
+ const r = d().isFeatureEnabled("reusableRecommendationStrategy"), s = r && !o.hasConfig(e), { config: n, wasFreshDrop: a } = o.initializeConfig(
107
109
  this.api,
108
110
  e,
109
111
  {
110
112
  recommendationId: i,
111
- configVersion: r ? v : M,
112
- ...n ? { partnerName: u().partnerName.value } : {},
113
+ configVersion: r ? v : w,
114
+ ...s ? { partnerName: d().partnerName.value } : {},
113
115
  // An RRS block picks a strategy, not an algorithm, and its algorithm control is
114
116
  // hidden. Keeping the `mostPopular` default would bake a most-popular feed URL
115
117
  // at save for a block the user never configured.
116
- ...n ? { strategy: "" } : {}
118
+ ...s ? { strategy: "" } : {}
117
119
  }
118
120
  ), _ = f();
119
- if (_.setCurrentBlock(i), this._stampHidePrice(e, s.priceHideIfSameAsDiscounted), a) {
121
+ if (_.setCurrentBlock(i), this._stampHidePrice(e, n.priceHideIfSameAsDiscounted), a) {
120
122
  I(this.api);
121
- const h = this._getBlockElement(e);
122
- h && (k(this.api, h, !0), w({
123
+ const g = this._getBlockElement(e);
124
+ g && (R(this.api, g, !0), M({
123
125
  currentNode: e,
124
126
  documentModifier: this.api.getDocumentModifier()
125
127
  }));
126
128
  }
127
- _.patchCurrentBlockConfig({ language: s.language }, { triggerRefetch: !1 }), this._warnIfMultipleBlocks();
129
+ _.patchCurrentBlockConfig({ language: n.language }, { triggerRefetch: !1 }), this._warnIfMultipleBlocks();
130
+ }
131
+ /** Refreshes every block of an opened template: Stripo restores a stored document without `onCreated`. */
132
+ onDocumentInit() {
133
+ try {
134
+ const e = this.api.getDocumentRoot();
135
+ e && "querySelectorAll" in e && e.querySelectorAll(`.${u}`).forEach((t) => this._queueArrivalRefresh(t));
136
+ } catch (e) {
137
+ console.error("[recommendation] refreshing an opened strategy failed", e);
138
+ }
128
139
  }
129
140
  /**
130
141
  * Called when the document changes or template is loaded
@@ -146,11 +157,11 @@ class Z extends S {
146
157
  }
147
158
  this._healLingeringDuplicate(e), o.needsMigration(e) && this._migrateFromLegacy(e), this._healHidePriceAttr(e);
148
159
  try {
149
- b || (I(this.api), b = !0);
160
+ D || (I(this.api), D = !0);
150
161
  const t = o.getConfig(e), i = this._getBlockElement(e);
151
162
  if (i) {
152
163
  const r = !t.mobileLayoutEnabled;
153
- O(i) !== r && k(this.api, i, r);
164
+ O(i) !== r && R(this.api, i, r);
154
165
  }
155
166
  } catch {
156
167
  }
@@ -193,9 +204,9 @@ class Z extends S {
193
204
  const t = /* @__PURE__ */ new Set();
194
205
  try {
195
206
  const i = this.api.getDocumentRoot();
196
- i && "querySelectorAll" in i && i.querySelectorAll(`.${g}`).forEach((n) => {
197
- if ("getAttribute" in n) {
198
- const s = n.getAttribute(d), a = s ? parseInt(s) : 0;
207
+ i && "querySelectorAll" in i && i.querySelectorAll(`.${u}`).forEach((s) => {
208
+ if ("getAttribute" in s) {
209
+ const n = s.getAttribute(h), a = n ? parseInt(n) : 0;
199
210
  t.add(a), a > e && (e = a);
200
211
  }
201
212
  });
@@ -213,17 +224,17 @@ class Z extends S {
213
224
  * the renamed one depending on where the module was dropped (SD-149916).
214
225
  */
215
226
  _scheduleArrivalReset(e) {
216
- u().isFeatureEnabled("reusableRecommendationStrategy") && setTimeout(() => {
227
+ d().isFeatureEnabled("reusableRecommendationStrategy") && setTimeout(() => {
217
228
  const t = this._getRecommendationId(e);
218
229
  t !== null && t > 0 && !this._resetSourceIds.delete(t) && f().resetArrivedBlock(t);
219
230
  }, 0);
220
231
  }
221
232
  /**
222
- * Re-reads the strategy of a block that arrived with saved cards, without waiting for a click. Stripo
223
- * creates every block of an opened template or dropped module, so arrivals of one tick refresh together.
233
+ * Re-reads the strategy of a block that arrived with saved cards, without waiting for a click.
234
+ * Blocks of one opened template or dropped module arrive in one tick and refresh together.
224
235
  */
225
236
  _queueArrivalRefresh(e) {
226
- u().isFeatureEnabled("reusableRecommendationStrategy") && (this._arrivedNodes.push(e) > 1 || setTimeout(() => {
237
+ d().isFeatureEnabled("reusableRecommendationStrategy") && (this._arrivedNodes.push(e) > 1 || setTimeout(() => {
227
238
  const t = this._arrivedNodes;
228
239
  this._arrivedNodes = [];
229
240
  try {
@@ -235,10 +246,10 @@ class Z extends S {
235
246
  }
236
247
  _refreshArrivedBlocks(e) {
237
248
  const t = e.flatMap((i) => {
238
- const r = this._getRecommendationId(i), n = this._getBlockElement(i);
239
- return r && n ? [{ id: r, config: o.getConfig(n) }] : [];
249
+ const r = this._getRecommendationId(i), s = this._getBlockElement(i);
250
+ return !r || !s || this._refreshingIds.has(r) ? [] : (this._refreshingIds.add(r), [{ id: r, config: o.getConfig(s) }]);
240
251
  });
241
- R(this.api), H(t).catch((i) => console.error("[recommendation] refreshing an arrived strategy failed", i));
252
+ t.length && (k(this.api), $(t).catch((i) => console.error("[recommendation] refreshing an arrived strategy failed", i)).finally(() => t.forEach(({ id: i }) => this._refreshingIds.delete(i))));
242
253
  }
243
254
  /**
244
255
  * Heals a duplicate that slipped past the create-time `_detectDuplicate`
@@ -260,20 +271,20 @@ class Z extends S {
260
271
  if (!i || !("querySelectorAll" in i))
261
272
  return;
262
273
  const r = i.querySelectorAll(
263
- `.${g}[${d}="${t}"]`
274
+ `.${u}[${h}="${t}"]`
264
275
  );
265
276
  if (r.length <= 1)
266
277
  return;
267
- const n = this._getBlockElement(e);
268
- if (!n)
278
+ const s = this._getBlockElement(e);
279
+ if (!s)
269
280
  return;
270
- let s = -1;
281
+ let n = -1;
271
282
  for (let a = 0; a < r.length; a++)
272
- if (r[a] === n) {
273
- s = a;
283
+ if (r[a] === s) {
284
+ n = a;
274
285
  break;
275
286
  }
276
- if (s <= 0)
287
+ if (n <= 0)
277
288
  return;
278
289
  this._reassignDuplicateId(e, t);
279
290
  } catch {
@@ -285,7 +296,7 @@ class Z extends S {
285
296
  const t = this.api.getDocumentRoot();
286
297
  if (t && "querySelectorAll" in t)
287
298
  return t.querySelectorAll(
288
- `.${g}[${d}="${e}"]`
299
+ `.${u}[${h}="${e}"]`
289
300
  ).length > 1;
290
301
  } catch {
291
302
  }
@@ -294,7 +305,12 @@ class Z extends S {
294
305
  /** Assigns a fresh id to a duplicated block and syncs DOM, node config and store. */
295
306
  _handleDuplicate(e, t) {
296
307
  const i = this._reassignDuplicateId(e, t), r = f();
297
- r.cloneBlockState(t, i), r.setCurrentBlock(i), u().isFeatureEnabled("reusableRecommendationStrategy") && (this._resetSourceIds.add(t), R(this.api), $(t, i, o.getConfig(e)).catch((n) => console.error("[recommendation] refreshing a duplicated strategy failed", n))), this._warnIfMultipleBlocks();
308
+ if (r.cloneBlockState(t, i), r.setCurrentBlock(i), d().isFeatureEnabled("reusableRecommendationStrategy")) {
309
+ this._resetSourceIds.add(t), k(this.api);
310
+ const s = [t, i].filter((n) => !this._refreshingIds.has(n));
311
+ s.forEach((n) => this._refreshingIds.add(n)), H(t, i, o.getConfig(e)).catch((n) => console.error("[recommendation] refreshing a duplicated strategy failed", n)).finally(() => s.forEach((n) => this._refreshingIds.delete(n)));
312
+ }
313
+ this._warnIfMultipleBlocks();
298
314
  }
299
315
  /**
300
316
  * Core id-reassignment for a duplicated block: rewrites the DOM
@@ -326,9 +342,9 @@ class Z extends S {
326
342
  _reassignInstanceClass(e, t, i) {
327
343
  if (!("getAttribute" in e))
328
344
  return;
329
- const r = `ins-recommendation-v3-block-${t}`, n = `ins-recommendation-v3-block-${i}`, s = this.api.getDocumentModifier();
330
- s.modifyHtml(e).removeClass(r).setClass(n), s.apply(new p(
331
- `Reassign recommendation instance class ${r} -> ${n}`
345
+ const r = `ins-recommendation-v3-block-${t}`, s = `ins-recommendation-v3-block-${i}`, n = this.api.getDocumentModifier();
346
+ n.modifyHtml(e).removeClass(r).setClass(s), n.apply(new p(
347
+ `Reassign recommendation instance class ${r} -> ${s}`
332
348
  ));
333
349
  }
334
350
  /**
@@ -342,7 +358,7 @@ class Z extends S {
342
358
  if (!i)
343
359
  return;
344
360
  const r = this.api.getDocumentModifier();
345
- r.modifyHtml(i).setAttribute(d, t.toString()), r.apply(new p(`Assign recommendation ID ${t}`));
361
+ r.modifyHtml(i).setAttribute(h, t.toString()), r.apply(new p(`Assign recommendation ID ${t}`));
346
362
  }
347
363
  /**
348
364
  * Stamps the `hide-price` attribute (read by email-service at send time) on
@@ -370,7 +386,7 @@ class Z extends S {
370
386
  const t = this._getBlockElement(e);
371
387
  if (!t || !("getAttribute" in t))
372
388
  return null;
373
- const i = t.getAttribute(d);
389
+ const i = t.getAttribute(h);
374
390
  if (!i)
375
391
  return null;
376
392
  const r = parseInt(i);
@@ -382,10 +398,10 @@ class Z extends S {
382
398
  _getBlockElement(e) {
383
399
  if ("getAttribute" in e) {
384
400
  const t = e.getAttribute("class");
385
- if (t && t.includes(g))
401
+ if (t && t.includes(u))
386
402
  return e;
387
403
  }
388
- return "querySelector" in e ? e.querySelector(`.${g}`) ?? null : null;
404
+ return "querySelector" in e ? e.querySelector(`.${u}`) ?? null : null;
389
405
  }
390
406
  /**
391
407
  * Migrate configuration from legacy format
@@ -20,6 +20,8 @@ export declare class RecommendationBlock extends Block {
20
20
  /** Ids handed to duplicates the document root does not show yet: a copied module renames all its blocks at once. */
21
21
  private _unsettledDuplicateIds;
22
22
  private _arrivedNodes;
23
+ /** Ids whose arrival or duplicate refresh is in flight, so a second refresh of the same block does not race it. */
24
+ private _refreshingIds;
23
25
  constructor();
24
26
  getId(): string;
25
27
  getIcon(): string;
@@ -45,6 +47,8 @@ export declare class RecommendationBlock extends Block {
45
47
  * @param node - The newly created block node
46
48
  */
47
49
  onCreated(node: ImmutableHtmlNode): void;
50
+ /** Refreshes every block of an opened template: Stripo restores a stored document without `onCreated`. */
51
+ onDocumentInit(): void;
48
52
  /**
49
53
  * Called when the document changes or template is loaded
50
54
  *
@@ -87,8 +91,8 @@ export declare class RecommendationBlock extends Block {
87
91
  */
88
92
  private _scheduleArrivalReset;
89
93
  /**
90
- * Re-reads the strategy of a block that arrived with saved cards, without waiting for a click. Stripo
91
- * creates every block of an opened template or dropped module, so arrivals of one tick refresh together.
94
+ * Re-reads the strategy of a block that arrived with saved cards, without waiting for a click.
95
+ * Blocks of one opened template or dropped module arrive in one tick and refresh together.
92
96
  */
93
97
  private _queueArrivalRefresh;
94
98
  private _refreshArrivedBlocks;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "3.21.0-beta.27e5667",
3
+ "version": "3.21.0-beta.7e166b5",
4
4
  "description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
5
5
  "main": "./dist/guido.umd.cjs",
6
6
  "module": "./dist/library.js",