@useinsider/guido 3.16.0-beta.20cd2fe → 3.16.0-beta.77f2873

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/@types/config/schemas.js +23 -25
  2. package/dist/components/organisms/header/AutoSaveToggle.vue.js +22 -0
  3. package/dist/components/organisms/header/AutoSaveToggle.vue2.js +19 -0
  4. package/dist/components/organisms/header/EditorActions.vue.js +11 -11
  5. package/dist/components/organisms/header/EditorActions.vue2.js +50 -34
  6. package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
  7. package/dist/components/organisms/header/LeftSlot.vue2.js +23 -28
  8. package/dist/components/organisms/header/MiddleSlot.vue.js +4 -4
  9. package/dist/components/organisms/header/MiddleSlot.vue2.js +7 -8
  10. package/dist/components/organisms/header/RightSlot.vue.js +6 -6
  11. package/dist/components/organisms/header/RightSlot.vue2.js +15 -17
  12. package/dist/components/organisms/onboarding/OnboardingWrapper.vue2.js +34 -43
  13. package/dist/composables/useRecommendation.js +20 -19
  14. package/dist/config/i18n/en/labels.json.js +4 -28
  15. package/dist/config/migrator/itemsBlockMigrator.js +1 -1
  16. package/dist/enums/recommendation.js +17 -17
  17. package/dist/extensions/Blocks/Items/block.js +98 -49
  18. package/dist/extensions/Blocks/Items/constants/currency.js +11 -0
  19. package/dist/extensions/Blocks/Items/controls/price/currencyLocation.js +25 -24
  20. package/dist/extensions/Blocks/Items/controls/price/currencySymbol.js +12 -11
  21. package/dist/extensions/Blocks/Items/enums/productEnums.js +45 -45
  22. package/dist/extensions/Blocks/Items/template.js +103 -102
  23. package/dist/extensions/Blocks/Recommendation/controls/main/algorithm.js +37 -26
  24. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +21 -21
  25. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +13 -12
  26. package/dist/extensions/Blocks/Recommendation/utils/productIds.js +6 -0
  27. package/dist/guido.css +1 -1
  28. package/dist/node_modules/@vueuse/shared/index.js +28 -40
  29. package/dist/src/@types/config/schemas.d.ts +0 -4
  30. package/dist/src/composables/useActionsApi.d.ts +2 -2
  31. package/dist/src/composables/useConfig.d.ts +0 -2
  32. package/dist/src/extensions/Blocks/Items/block.d.ts +21 -0
  33. package/dist/src/extensions/Blocks/Items/constants/currency.d.ts +19 -0
  34. package/dist/src/extensions/Blocks/Recommendation/utils/productIds.d.ts +6 -0
  35. package/dist/src/stores/config.d.ts +0 -18
  36. package/dist/src/stores/editor.d.ts +0 -107
  37. package/dist/src/stores/onboarding.d.ts +0 -377
  38. package/dist/src/stores/version-history.d.ts +1 -1
  39. package/dist/src/utils/timeUtil.d.ts +0 -10
  40. package/dist/stores/editor.js +1 -5
  41. package/dist/stores/onboarding.js +11 -16
  42. package/dist/utils/pairProductVariables.js +60 -59
  43. package/dist/utils/timeUtil.js +17 -6
  44. package/package.json +1 -1
  45. package/dist/components/organisms/header/AutoSaveStatus.vue.js +0 -17
  46. package/dist/components/organisms/header/AutoSaveStatus.vue2.js +0 -21
  47. package/dist/components/organisms/header/EditorActionsMenu.vue.js +0 -20
  48. package/dist/components/organisms/header/EditorActionsMenu.vue2.js +0 -39
  49. package/dist/components/organisms/header/accessibility/AccessibilityToolbar.vue.js +0 -18
  50. package/dist/components/organisms/header/accessibility/AccessibilityToolbar.vue2.js +0 -37
  51. package/dist/components/organisms/header/accessibility/ColorVisionSelect.vue.js +0 -24
  52. package/dist/components/organisms/header/accessibility/ColorVisionSelect.vue2.js +0 -48
  53. package/dist/components/organisms/onboarding/EditorTabBarOnboarding.vue.js +0 -18
  54. package/dist/components/organisms/onboarding/EditorTabBarOnboarding.vue2.js +0 -74
  55. package/dist/composables/useAccessibilityApi.js +0 -31
  56. package/dist/node_modules/@vueuse/core/index.js +0 -102
  57. package/dist/src/components/organisms/header/EditorActionsMenu.vue.d.ts +0 -2
  58. package/dist/src/components/organisms/header/accessibility/AccessibilityToolbar.vue.d.ts +0 -2
  59. package/dist/src/components/organisms/header/accessibility/ColorVisionSelect.vue.d.ts +0 -2
  60. package/dist/src/components/organisms/onboarding/EditorTabBarOnboarding.vue.d.ts +0 -2
  61. package/dist/src/composables/useAccessibilityApi.d.ts +0 -15
  62. /package/dist/src/components/organisms/header/{AutoSaveStatus.vue.d.ts → AutoSaveToggle.vue.d.ts} +0 -0
@@ -1,23 +1,23 @@
1
- var c = Object.defineProperty;
2
- var l = (s, o, t) => o in s ? c(s, o, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[o] = t;
3
- var a = (s, o, t) => l(s, typeof o != "symbol" ? o + "" : o, t);
4
- import { UEAttr as h } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
- import { CommonControl as d } from "../../../common-control.js";
1
+ var d = Object.defineProperty;
2
+ var h = (r, s, t) => s in r ? d(r, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[s] = t;
3
+ var c = (r, s, t) => h(r, typeof s != "symbol" ? s + "" : s, t);
4
+ import { UEAttr as l } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
5
+ import { CommonControl as g } from "../../../common-control.js";
6
6
  import { RecommendationConfigService as n } from "../../services/configService.js";
7
7
  import { useRecommendationExtensionStore as m } from "../../store/recommendation.js";
8
- import { mapLegacyStrategy as g } from "../../utils/legacyStrategyMap.js";
9
- const u = "recommendation-algorithm-control", i = {
8
+ import { mapLegacyStrategy as u } from "../../utils/legacyStrategyMap.js";
9
+ const p = "recommendation-algorithm-control", i = {
10
10
  ALGORITHM: "strategy",
11
11
  PRODUCT_IDS: "productIds"
12
12
  };
13
- class R extends d {
13
+ class R extends g {
14
14
  constructor() {
15
15
  super(...arguments);
16
16
  // Store is used ONLY for API-fetched data (algorithms list), not for config
17
- a(this, "store", m());
17
+ c(this, "store", m());
18
18
  }
19
19
  getId() {
20
- return u;
20
+ return p;
21
21
  }
22
22
  getTemplate() {
23
23
  return `
@@ -46,11 +46,10 @@ class R extends d {
46
46
  super.onTemplateNodeUpdated(t), this._initializeSelectItems(), this._setFormValues();
47
47
  }
48
48
  _setFormValues() {
49
- const t = n.getConfig(this.currentNode), e = g(t.strategy) ?? t.strategy;
50
- this._setProductIdsVisibility(e), this.api.updateValues({
51
- [i.ALGORITHM]: e,
52
- [i.PRODUCT_IDS]: t.productIds.join(",")
53
- });
49
+ const t = n.getConfig(this.currentNode), e = u(t.strategy) ?? t.strategy;
50
+ this._setProductIdsVisibility(e);
51
+ const o = { [i.ALGORITHM]: e }, a = t.productIds.join(",");
52
+ this.api.getValues()[i.PRODUCT_IDS] !== a && (o[i.PRODUCT_IDS] = a), this.api.updateValues(o);
54
53
  }
55
54
  _initializeSelectItems() {
56
55
  var e;
@@ -59,35 +58,47 @@ class R extends d {
59
58
  try {
60
59
  this.api.setUIEAttribute(
61
60
  i.ALGORITHM,
62
- h.SELECTPICKER.items,
61
+ l.SELECTPICKER.items,
63
62
  t
64
63
  );
65
- } catch (r) {
66
- console.warn("[AlgorithmControl] Failed to set algorithm options:", r);
64
+ } catch (o) {
65
+ console.warn("[AlgorithmControl] Failed to set algorithm options:", o);
67
66
  }
68
67
  }
69
68
  _setProductIdsVisibility(t) {
70
- const r = (t ?? n.getConfig(this.currentNode).strategy) === "manualMerchandising";
71
- this.api.setVisibility(i.PRODUCT_IDS, r), this.api.setVisibility(`${i.PRODUCT_IDS}_label`, r);
69
+ const o = (t ?? n.getConfig(this.currentNode).strategy) === "manualMerchandising";
70
+ this.api.setVisibility(i.PRODUCT_IDS, o), this.api.setVisibility(`${i.PRODUCT_IDS}_label`, o);
72
71
  }
73
72
  _onAlgorithmChange(t) {
74
- !this.currentNode || n.getConfig(this.currentNode).strategy === t || (n.updateConfig(
73
+ if (!this.currentNode)
74
+ return;
75
+ const e = n.getConfig(this.currentNode);
76
+ if (e.strategy === t) {
77
+ this.store.recommendationConfigs.strategy !== t && this.store.patchCurrentBlockConfig({ strategy: e.strategy, filters: e.filters });
78
+ return;
79
+ }
80
+ n.updateConfig(
75
81
  this.api,
76
82
  this.currentNode,
77
83
  { strategy: t },
78
84
  `Changed algorithm to ${t}`
79
- ), this.store.patchCurrentBlockConfig({ strategy: t }), this._setProductIdsVisibility(t));
85
+ ), this.store.patchCurrentBlockConfig({ strategy: t }), this._setProductIdsVisibility(t);
80
86
  }
81
87
  _onProductIdsChange(t) {
82
88
  if (!this.currentNode)
83
89
  return;
84
- const e = t.split(",").map((r) => r.trim()).filter(Boolean);
90
+ const e = n.getConfig(this.currentNode);
91
+ if (e.productIds.join(",") === t) {
92
+ this.store.recommendationConfigs.productIds.join(",") !== t && this.store.patchCurrentBlockConfig({ productIds: e.productIds, filters: e.filters });
93
+ return;
94
+ }
95
+ const o = t === "" ? [] : t.split(",");
85
96
  n.updateConfig(
86
97
  this.api,
87
98
  this.currentNode,
88
- { productIds: e },
99
+ { productIds: o },
89
100
  "Updated product IDs"
90
- ), this.store.patchCurrentBlockConfig({ productIds: e });
101
+ ), this.store.patchCurrentBlockConfig({ productIds: o });
91
102
  }
92
103
  _listenToFormUpdates() {
93
104
  this.api.onValueChanged(i.ALGORITHM, (t) => {
@@ -98,6 +109,6 @@ class R extends d {
98
109
  }
99
110
  }
100
111
  export {
101
- u as ALGORITHM_CONTROL_ID,
112
+ p as ALGORITHM_CONTROL_ID,
102
113
  R as AlgorithmControl
103
114
  };
@@ -3,7 +3,7 @@ var p = (d, l, t) => l in d ? f(d, l, { enumerable: !0, configurable: !0, writab
3
3
  var s = (d, l, t) => p(d, typeof l != "symbol" ? l + "" : l, t);
4
4
  import { CommonControl as g } from "../../../common-control.js";
5
5
  import { DEFAULT_NODE_CONFIG as c } from "../../constants/defaultConfig.js";
6
- import { RecommendationConfigService as m } from "../../services/configService.js";
6
+ import { RecommendationConfigService as h } from "../../services/configService.js";
7
7
  import { useRecommendationExtensionStore as y } from "../../store/recommendation.js";
8
8
  import { AlgorithmControl as N } from "./algorithm.js";
9
9
  import { ALGORITHM_CONTROL_ID as tt } from "./algorithm.js";
@@ -17,15 +17,15 @@ import { LocaleControl as b } from "./locale.js";
17
17
  import { LOCALE_CONTROL_ID as lt } from "./locale.js";
18
18
  import { PricePlacementControl as T } from "./pricePlacement.js";
19
19
  import { PRICE_PLACEMENT_CONTROL_ID as ut } from "./pricePlacement.js";
20
- import { ProductCountControl as P } from "./productCount.js";
21
- import { PRODUCT_COUNT_CONTROL_ID as mt } from "./productCount.js";
22
- import { ProductLayoutControl as O } from "./productLayout.js";
20
+ import { ProductCountControl as O } from "./productCount.js";
21
+ import { PRODUCT_COUNT_CONTROL_ID as ht } from "./productCount.js";
22
+ import { ProductLayoutControl as P } from "./productLayout.js";
23
23
  import { PRODUCT_LAYOUT_CONTROL_ID as Ct } from "./productLayout.js";
24
- import { ShuffleControl as L } from "./shuffle.js";
24
+ import { ShuffleControl as S } from "./shuffle.js";
25
25
  import { SHUFFLE_CONTROL_ID as pt } from "./shuffle.js";
26
- import { setCurrencyAttributes as S, getBlockElement as k, isPartnerManagedBlock as D, updateProductContentInPlace as E, regenerateProductRowsWithStyles as A } from "./utils.js";
26
+ import { setCurrencyAttributes as L, getBlockElement as k, isPartnerManagedBlock as D, updateProductContentInPlace as E, regenerateProductRowsWithStyles as A } from "./utils.js";
27
27
  import { adjustProductsToSize as yt, formatProductPrice as Nt, getCardComposition as Rt, getCurrentLayout as It, regenerateMobileProductRows as _t, updatePricesInPlace as bt, updateSingleProductContent as Tt } from "./utils.js";
28
- import { useDebounceFn as h } from "../../../../../node_modules/@vueuse/shared/index.js";
28
+ import { useDebounceFn as m } from "../../../../../node_modules/@vueuse/shared/index.js";
29
29
  const v = "recommendation-id", w = "ui-elements-recommendation-block";
30
30
  class Q extends g {
31
31
  constructor() {
@@ -47,7 +47,7 @@ class Q extends g {
47
47
  /**
48
48
  * Debounced product fetch to prevent rapid API calls during config changes
49
49
  */
50
- s(this, "_debouncedFetchProducts", h(() => {
50
+ s(this, "_debouncedFetchProducts", m(() => {
51
51
  this.store.fetchRecommendationProducts();
52
52
  }, 500));
53
53
  /**
@@ -61,7 +61,7 @@ class Q extends g {
61
61
  * count. The store pads products to the configured size, so in-place only
62
62
  * fails when the size actually changed.
63
63
  */
64
- s(this, "_debouncedRegenerateWithProducts", h(() => {
64
+ s(this, "_debouncedRegenerateWithProducts", m(() => {
65
65
  const t = this.store.recommendationProducts;
66
66
  if (!this.currentNode || !this.api || D(this.currentNode))
67
67
  return;
@@ -81,7 +81,7 @@ class Q extends g {
81
81
  return w;
82
82
  }
83
83
  getTemplate() {
84
- return this.algorithmControl = new N(), this.localeControl = new b(), this.currencyControl = new R(), this.productCountControl = new P(), this.productLayoutControl = new O(), this.filtersControl = new I(), this.shuffleControl = new L(), this.pricePlacementControl = new T(), this.layoutOrientationControl = new _(), [
84
+ return this.algorithmControl = new N(), this.localeControl = new b(), this.currencyControl = new R(), this.productCountControl = new O(), this.productLayoutControl = new P(), this.filtersControl = new I(), this.shuffleControl = new S(), this.pricePlacementControl = new T(), this.layoutOrientationControl = new _(), [
85
85
  this.algorithmControl,
86
86
  this.localeControl,
87
87
  this.currencyControl,
@@ -186,7 +186,7 @@ class Q extends g {
186
186
  */
187
187
  _syncNodeConfigToStore() {
188
188
  var r;
189
- const t = m.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((r = this.store.blockStates[e]) == null ? void 0 : r.isInitialized);
189
+ const t = h.getConfig(this.currentNode), e = this.store.currentRecommendationId, o = e !== null && ((r = this.store.blockStates[e]) == null ? void 0 : r.isInitialized);
190
190
  this.store.patchCurrentBlockConfig({
191
191
  strategy: t.strategy,
192
192
  language: t.language,
@@ -249,7 +249,7 @@ class Q extends g {
249
249
  _applySmartDefaults() {
250
250
  if (!this.currentNode || !this.api)
251
251
  return;
252
- const t = m.getConfig(this.currentNode), e = {};
252
+ const t = h.getConfig(this.currentNode), e = {};
253
253
  let o = null, r = null, n = null;
254
254
  if (t.currency.code === c.currency.code) {
255
255
  const { currencyList: i } = this.store;
@@ -273,12 +273,12 @@ class Q extends g {
273
273
  (u) => u.value === c.language
274
274
  ) || (n = i[0].value, e.language = n));
275
275
  }
276
- !o && !r && !n || (m.updateConfig(
276
+ !o && !r && !n || (h.updateConfig(
277
277
  this.api,
278
278
  this.currentNode,
279
279
  e,
280
280
  "Applied smart defaults"
281
- ), o && e.currency && S({
281
+ ), o && e.currency && L({
282
282
  currentNode: this.currentNode,
283
283
  documentModifier: this.api.getDocumentModifier(),
284
284
  currency: e.currency
@@ -346,8 +346,8 @@ class Q extends g {
346
346
  _persistFiltersToNodeConfig() {
347
347
  if (!this.currentNode || !this.api)
348
348
  return;
349
- const { filters: t } = this.store.recommendationConfigs;
350
- m.updateConfig(
349
+ const { filters: t } = this.store.recommendationConfigs, e = h.getConfig(this.currentNode).filters;
350
+ JSON.stringify(e) !== JSON.stringify(t) && h.updateConfig(
351
351
  this.api,
352
352
  this.currentNode,
353
353
  { filters: t },
@@ -368,14 +368,14 @@ export {
368
368
  _ as LayoutOrientationControl,
369
369
  b as LocaleControl,
370
370
  ut as PRICE_PLACEMENT_CONTROL_ID,
371
- mt as PRODUCT_COUNT_CONTROL_ID,
371
+ ht as PRODUCT_COUNT_CONTROL_ID,
372
372
  Ct as PRODUCT_LAYOUT_CONTROL_ID,
373
373
  T as PricePlacementControl,
374
- P as ProductCountControl,
375
- O as ProductLayoutControl,
374
+ O as ProductCountControl,
375
+ P as ProductLayoutControl,
376
376
  Q as RecommendationBlockControl,
377
377
  pt as SHUFFLE_CONTROL_ID,
378
- L as ShuffleControl,
378
+ S as ShuffleControl,
379
379
  yt as adjustProductsToSize,
380
380
  Nt as formatProductPrice,
381
381
  k as getBlockElement,
@@ -384,7 +384,7 @@ export {
384
384
  D as isPartnerManagedBlock,
385
385
  _t as regenerateMobileProductRows,
386
386
  A as regenerateProductRowsWithStyles,
387
- S as setCurrencyAttributes,
387
+ L as setCurrencyAttributes,
388
388
  bt as updatePricesInPlace,
389
389
  E as updateProductContentInPlace,
390
390
  Tt as updateSingleProductContent
@@ -1,15 +1,16 @@
1
1
  import { getRecommendationFeedSourceMaps as g, getOperatorOptions as R, PriceAttributes as C } from "../../../../enums/extensions/recommendationBlock.js";
2
2
  import { useRecommendationApi as y } from "../../../../services/recommendationApi.js";
3
3
  import { useConfigStore as G } from "../../../../stores/config.js";
4
- import { defineStore as F } from "pinia";
4
+ import { defineStore as P } from "pinia";
5
5
  import "../constants/selectors.js";
6
- import { DEFAULT_MOBILE_CARDS_IN_ROW as P, DEFAULT_CARDS_IN_ROW as D } from "../constants/layout.js";
6
+ import { DEFAULT_MOBILE_CARDS_IN_ROW as F, DEFAULT_CARDS_IN_ROW as D } from "../constants/layout.js";
7
7
  import { EXCLUDED_ALGORITHM_IDS as w } from "../constants/defaultConfig.js";
8
8
  import { getDefaultProducts as S } from "../templates/utils.js";
9
9
  import { generateCompleteFilterQuery as b } from "../utils/filterUtil.js";
10
10
  import { getPartnerRecommendationParams as v } from "../utils/partnerCustomizations.js";
11
- import { isFilterValid as N } from "../validation/filterSchema.js";
12
- import { isConfigValid as x } from "../validation/requiredFields.js";
11
+ import { sanitizeProductIds as N } from "../utils/productIds.js";
12
+ import { isFilterValid as x } from "../validation/filterSchema.js";
13
+ import { isConfigValid as L } from "../validation/requiredFields.js";
13
14
  const h = y();
14
15
  let m = null, u = null, d = null;
15
16
  function k() {
@@ -28,7 +29,7 @@ function k() {
28
29
  productIds: [],
29
30
  id: 1,
30
31
  language: "en_US",
31
- mobileCardsInRow: P,
32
+ mobileCardsInRow: F,
32
33
  mobileLayoutEnabled: !1,
33
34
  orientation: "grid",
34
35
  recommendedProducts: [],
@@ -54,7 +55,7 @@ function I() {
54
55
  filterSnapshot: null
55
56
  };
56
57
  }
57
- const L = () => ({
58
+ const U = () => ({
58
59
  recommendationCampaignUrls: {},
59
60
  activePredictiveAlgorithms: [],
60
61
  languages: {},
@@ -63,8 +64,8 @@ const L = () => ({
63
64
  blockStates: {},
64
65
  currentRecommendationId: null,
65
66
  configVersion: 0
66
- }), $ = F("guidoRecommendationExtension", {
67
- state: () => L(),
67
+ }), H = P("guidoRecommendationExtension", {
68
+ state: () => U(),
68
69
  getters: {
69
70
  // ====================================================================
70
71
  // Proxy Getters — Backward Compatible Access to Current Block State
@@ -383,7 +384,7 @@ const L = () => ({
383
384
  const n = [...e.recommendationConfigs.filters];
384
385
  n[r] = {
385
386
  ...t,
386
- isValid: N(t)
387
+ isValid: x(t)
387
388
  }, e.recommendationConfigs.filters = n;
388
389
  }
389
390
  },
@@ -429,7 +430,7 @@ const L = () => ({
429
430
  * every block's recommendationConfigs across user edits.
430
431
  */
431
432
  hasInvalidBlock() {
432
- return Object.values(this.blockStates).some((t) => !x(t.recommendationConfigs, this));
433
+ return Object.values(this.blockStates).some((t) => !L(t.recommendationConfigs, this));
433
434
  },
434
435
  // ====================================================================
435
436
  // Per-Block Product Fetching
@@ -458,7 +459,7 @@ const L = () => ({
458
459
  details: !0,
459
460
  campaignId: o.variationId
460
461
  };
461
- r.strategy === "manualMerchandising" ? a.productId = r.productIds.join(",") : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), c && (a.filter = c), r.shuffleProducts && (a.shuffle = !0), Object.assign(
462
+ r.strategy === "manualMerchandising" ? a.productId = N(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), c && (a.filter = c), r.shuffleProducts && (a.shuffle = !0), Object.assign(
462
463
  a,
463
464
  v(o.partnerName, r.strategy)
464
465
  );
@@ -479,5 +480,5 @@ const L = () => ({
479
480
  }
480
481
  });
481
482
  export {
482
- $ as useRecommendationExtensionStore
483
+ H as useRecommendationExtensionStore
483
484
  };
@@ -0,0 +1,6 @@
1
+ function n(t) {
2
+ return t.map((i) => String(i ?? "").trim()).filter(Boolean).join(",");
3
+ }
4
+ export {
5
+ n as sanitizeProductIds
6
+ };
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- .gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-2f127fb6] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.color-vision-select__trigger[data-v-383f6378]{height:32px;padding:0 8px;border:none;border-radius:6px;background-color:#f1f3fe;cursor:pointer}.color-vision-select__trigger[data-v-383f6378]:disabled{cursor:not-allowed;opacity:.6}.color-vision-select__label[data-v-383f6378]{white-space:nowrap}.color-vision-select__menu[data-v-383f6378]{top:calc(100% + 4px);left:0;z-index:20;width:320px;padding:8px;border-radius:8px;background-color:#fff;box-shadow:0 4px 16px #0000001f}.color-vision-select__option[data-v-383f6378]{width:100%;padding:8px;border:none;border-radius:6px;background-color:transparent;text-align:left;cursor:pointer}.color-vision-select__option[data-v-383f6378]:hover,.color-vision-select__option_selected[data-v-383f6378]{background-color:#f1f3fe}.color-vision-select__option-description[data-v-383f6378]{margin-top:2px}.accessibility-toolbar[data-v-e222d603]{gap:8px}.accessibility-toolbar__divider[data-v-e222d603]{width:1px;height:24px;background-color:#e5e7f0}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-actions-menu__panel[data-v-cbfbc6ef]{top:calc(100% + 4px);right:0;z-index:20;width:222px;padding:8px;border-radius:8px;background-color:#fff;box-shadow:0 4px 16px #0000001f}.editor-actions-menu__section[data-v-cbfbc6ef]{padding:8px 8px 4px;text-transform:uppercase;letter-spacing:.4px}.editor-actions-menu__row[data-v-cbfbc6ef]{width:100%;padding:8px;border:none;border-radius:6px;background-color:transparent;text-align:left;cursor:pointer}.editor-actions-menu__row[data-v-cbfbc6ef]:not(.editor-actions-menu__row_static):hover{background-color:#f1f3fe}.editor-actions-menu__row_static[data-v-cbfbc6ef]{cursor:default}.editor-actions-menu__row[data-v-cbfbc6ef]:disabled{cursor:not-allowed;opacity:.6}.editor-actions-menu__divider[data-v-cbfbc6ef]{height:1px;margin:4px 0;background-color:#e5e7f0}.editor-actions[data-v-d51fb931]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-b0d3b445]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-b0d3b445]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-b0d3b445]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}
1
+ .gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-6e711fd7]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-b0d3b445]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-b0d3b445]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-b0d3b445]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}
@@ -1,57 +1,45 @@
1
1
  import "../../vue-demi/lib/index.js";
2
- import { unref as p, getCurrentScope as w, onScopeDispose as m } from "vue";
3
- function T(t) {
4
- return w() ? (m(t), !0) : !1;
5
- }
6
- function a(t) {
2
+ import { unref as p } from "vue";
3
+ function f(t) {
7
4
  return typeof t == "function" ? t() : p(t);
8
5
  }
9
- const g = typeof window < "u" && typeof document < "u";
10
6
  typeof WorkerGlobalScope < "u" && globalThis instanceof WorkerGlobalScope;
11
- const b = Object.prototype.toString, j = (t) => b.call(t) === "[object Object]", f = () => {
12
- }, x = /* @__PURE__ */ h();
13
- function h() {
14
- var t, n;
15
- return g && ((t = window == null ? void 0 : window.navigator) == null ? void 0 : t.userAgent) && (/iP(?:ad|hone|od)/.test(window.navigator.userAgent) || ((n = window == null ? void 0 : window.navigator) == null ? void 0 : n.maxTouchPoints) > 2 && /iPad|Macintosh/.test(window == null ? void 0 : window.navigator.userAgent));
16
- }
17
- function v(t, n) {
18
- function o(...e) {
19
- return new Promise((r, i) => {
20
- Promise.resolve(t(() => n.apply(this, e), { fn: n, thisArg: this, args: e })).then(r).catch(i);
7
+ const m = () => {
8
+ };
9
+ function h(t, n) {
10
+ function r(...e) {
11
+ return new Promise((i, o) => {
12
+ Promise.resolve(t(() => n.apply(this, e), { fn: n, thisArg: this, args: e })).then(i).catch(o);
21
13
  });
22
14
  }
23
- return o;
15
+ return r;
24
16
  }
25
- function S(t, n = {}) {
26
- let o, e, r = f;
27
- const i = (u) => {
28
- clearTimeout(u), r(), r = f;
17
+ function T(t, n = {}) {
18
+ let r, e, i = m;
19
+ const o = (u) => {
20
+ clearTimeout(u), i(), i = m;
29
21
  };
30
22
  return (u) => {
31
- const s = a(t), c = a(n.maxWait);
32
- return o && i(o), s <= 0 || c !== void 0 && c <= 0 ? (e && (i(e), e = null), Promise.resolve(u())) : new Promise((l, d) => {
33
- r = n.rejectOnCancel ? d : l, c && !e && (e = setTimeout(() => {
34
- o && i(o), e = null, l(u());
35
- }, c)), o = setTimeout(() => {
36
- e && i(e), e = null, l(u());
37
- }, s);
23
+ const a = f(t), l = f(n.maxWait);
24
+ return r && o(r), a <= 0 || l !== void 0 && l <= 0 ? (e && (o(e), e = null), Promise.resolve(u())) : new Promise((c, s) => {
25
+ i = n.rejectOnCancel ? s : c, l && !e && (e = setTimeout(() => {
26
+ r && o(r), e = null, c(u());
27
+ }, l)), r = setTimeout(() => {
28
+ e && o(e), e = null, c(u());
29
+ }, a);
38
30
  });
39
31
  };
40
32
  }
41
- function A(t, n = 200, o = {}) {
42
- return v(
43
- S(n, o),
33
+ function P(t, n = 200, r = {}) {
34
+ return h(
35
+ T(n, r),
44
36
  t
45
37
  );
46
38
  }
47
39
  export {
48
- v as createFilterWrapper,
49
- S as debounceFilter,
50
- g as isClient,
51
- x as isIOS,
52
- j as isObject,
53
- f as noop,
54
- a as toValue,
55
- T as tryOnScopeDispose,
56
- A as useDebounceFn
40
+ h as createFilterWrapper,
41
+ T as debounceFilter,
42
+ m as noop,
43
+ f as toValue,
44
+ P as useDebounceFn
57
45
  };
@@ -391,8 +391,6 @@ export declare const FeaturesSchema: v.ObjectSchema<{
391
391
  readonly liquidSyntax: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
392
392
  /** Enable autosave (3-min interval + tab-hide). User toggles on/off from the header. */
393
393
  readonly autosave: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
394
- /** Enable the Stripo Accessibility Checker control in the editor toolbar. */
395
- readonly accessibilityTesting: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
396
394
  /** Enable pre-save domain-allowlist validation (opt-in; Guido self-serves the block toaster) */
397
395
  readonly allowlistEnabled: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
398
396
  /** Enable persistent link tracking-id assignment for the click heatmap (opt-in) */
@@ -792,8 +790,6 @@ export declare const GuidoConfigSchema: v.ObjectSchema<{
792
790
  readonly liquidSyntax: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
793
791
  /** Enable autosave (3-min interval + tab-hide). User toggles on/off from the header. */
794
792
  readonly autosave: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
795
- /** Enable the Stripo Accessibility Checker control in the editor toolbar. */
796
- readonly accessibilityTesting: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
797
793
  /** Enable pre-save domain-allowlist validation (opt-in; Guido self-serves the block toaster) */
798
794
  readonly allowlistEnabled: v.OptionalSchema<v.BooleanSchema<undefined>, false>;
799
795
  /** Enable persistent link tracking-id assignment for the click heatmap (opt-in) */
@@ -1,5 +1,5 @@
1
- import type { CompileEmailOptions } from '@@/Types/api/actions-api';
2
- import { GetCompiledEmailOptions, CompiledEmailResult, TemplateData } from '@@/Types/api/actions-api';
1
+ import type { CompileEmailOptions } from '@@/Types/actions-api';
2
+ import { GetCompiledEmailOptions, CompiledEmailResult, TemplateData } from '@@/Types/actions-api';
3
3
  export declare const useActionsApi: () => {
4
4
  getCompiledEmail: (options?: GetCompiledEmailOptions) => Promise<CompiledEmailResult>;
5
5
  getTemplateData: () => Promise<TemplateData>;
@@ -97,7 +97,6 @@ export declare const useConfig: () => {
97
97
  modulesDisabled: boolean;
98
98
  liquidSyntax: boolean;
99
99
  autosave: boolean;
100
- accessibilityTesting: boolean;
101
100
  allowlistEnabled: boolean;
102
101
  linkTrackingIds: boolean;
103
102
  };
@@ -232,7 +231,6 @@ export declare const useConfig: () => {
232
231
  modulesDisabled: boolean;
233
232
  liquidSyntax: boolean;
234
233
  autosave: boolean;
235
- accessibilityTesting: boolean;
236
234
  allowlistEnabled: boolean;
237
235
  linkTrackingIds: boolean;
238
236
  } | null>;
@@ -16,6 +16,8 @@ export declare const BLOCK_ID: BlockId;
16
16
  * - Onboarding support
17
17
  */
18
18
  export declare class ItemsBlock extends Block {
19
+ /** Block instances whose currency attrs were already self-healed this session (SD-147588 — undo-safe). */
20
+ private _currencyHealed;
19
21
  getId(): string;
20
22
  getIcon(): string;
21
23
  getBlockCompositionType(): BlockCompositionType;
@@ -42,4 +44,23 @@ export declare class ItemsBlock extends Block {
42
44
  * relies on this td-level fallback in pairProductVariables.
43
45
  */
44
46
  private _stampProductTdDomAttributes;
47
+ /**
48
+ * Whether the currency self-heal should run for this block. Two guards (SD-147588):
49
+ * 1. Config is only authoritative when the symbol was actually customized — a symbol still at
50
+ * the 'USD' sentinel may be a migrator default, so we trust the DOM's real value over a
51
+ * defaulted config and never overwrite it.
52
+ * 2. Heal each instance at most once per session, so the auto-fix can't fight undo (undo
53
+ * re-drifts the attr, which would otherwise re-trigger the heal forever).
54
+ */
55
+ private _shouldReconcileCurrency;
56
+ /** Marks a block instance's currency as reconciled so it is not healed again (undo-safe). */
57
+ private _markCurrencyHealed;
58
+ /**
59
+ * Stamps the export-read currency attrs onto every price `<p>` from config, so a template whose
60
+ * attrs drifted (e.g. a location toggle before the sync fix) self-heals to match the editor.
61
+ * Config is the source of truth — never derive from visible text. Callers gate this with
62
+ * `_shouldReconcileCurrency`. Returns true only when an attr actually changed, so the caller can
63
+ * skip an empty apply that would otherwise re-trigger onDocumentChanged and loop (SD-147588).
64
+ */
65
+ private _reconcileCurrencyDomAttributes;
45
66
  }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Single owner for the Items price currency export contract (SD-147588).
3
+ *
4
+ * `data-curency` is deliberately misspelled (one `r`) — it is the attribute the
5
+ * server-side export transform (pairProductVariables) actually reads, so every
6
+ * layer that writes it and the live reader (template, controls, block self-heal,
7
+ * pairProductVariables) MUST go through these constants. A typo fix or mapping change
8
+ * in one of them would otherwise silently break sync with the others and ship the wrong
9
+ * currency position/token to the inbox. Mirrors the Recommendation block's `CURRENCY_ATTR`.
10
+ *
11
+ * Exception: the legacy migrator reads the raw misspelled string on purpose — it parses
12
+ * old templates frozen with that exact attr name, so it must NOT follow a future rename here.
13
+ */
14
+ export declare const ITEMS_CURRENCY_ATTR: {
15
+ readonly POSITION: "data-curency";
16
+ readonly SYMBOL: "data-currency_symbol";
17
+ };
18
+ /** Currency location select value `'1'` = after (price then symbol), anything else = before. */
19
+ export declare function currencyPositionFromLocation(location: string | undefined): 'after' | 'before';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Builds the request/URL `productId` value from raw product ID segments.
3
+ * Trimming happens here — NOT on input change — so the user's in-progress
4
+ * text (trailing commas, spaces) is never rewritten under the caret (SD-147111).
5
+ */
6
+ export declare function sanitizeProductIds(ids: readonly (string | number | null | undefined)[]): string;