@useinsider/guido 3.19.0-beta.e110e88 → 3.19.0-beta.e424587

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 (81) hide show
  1. package/dist/@types/config/schemas.js +104 -91
  2. package/dist/components/Guido.vue.js +6 -6
  3. package/dist/components/Guido.vue2.js +96 -85
  4. package/dist/components/organisms/base/AuthErrorModal.vue.js +18 -0
  5. package/dist/components/organisms/base/AuthErrorModal.vue2.js +42 -0
  6. package/dist/components/wrappers/WpModal.vue.js +1 -1
  7. package/dist/components/wrappers/WpModal.vue2.js +4 -3
  8. package/dist/composables/useAuthError.js +52 -0
  9. package/dist/composables/useAutoSave.js +11 -11
  10. package/dist/composables/useCortexBlueprintBridge.js +122 -54
  11. package/dist/composables/useEmailTemplateApplier.js +111 -50
  12. package/dist/composables/useHttp.js +64 -54
  13. package/dist/composables/useLegacyStrategyConversion.js +23 -19
  14. package/dist/composables/useStripo.js +24 -20
  15. package/dist/composables/useToaster.js +17 -15
  16. package/dist/composables/validators/useLiquidValidator.js +15 -15
  17. package/dist/config/compiler/itemsCompilerRules.js +14 -5
  18. package/dist/config/compiler/utils/itemsCompilerUtils.js +48 -21
  19. package/dist/config/migrator/index.js +14 -13
  20. package/dist/config/migrator/itemsBlockMigrator.js +245 -253
  21. package/dist/config/migrator/recommendationMigrator.js +28 -21
  22. package/dist/config/migrator/recommendationPartnerMigrator.js +56 -0
  23. package/dist/enums/extensions/recommendationBlock.js +30 -29
  24. package/dist/extensions/Blocks/Items/block.js +78 -67
  25. package/dist/extensions/Blocks/Items/constants/cardLayout.js +20 -0
  26. package/dist/extensions/Blocks/Items/constants/cardWidth.js +20 -0
  27. package/dist/extensions/Blocks/Items/controls/name/trimming.js +18 -17
  28. package/dist/extensions/Blocks/Items/controls/settingsControl.js +114 -105
  29. package/dist/extensions/Blocks/Items/enums/productEnums.js +14 -9
  30. package/dist/extensions/Blocks/Items/layouts/horizontal.html.js +11 -9
  31. package/dist/extensions/Blocks/Items/layouts/vertical.html.js +1 -1
  32. package/dist/extensions/Blocks/Items/template.js +219 -204
  33. package/dist/extensions/Blocks/Recommendation/block.js +21 -22
  34. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +97 -107
  35. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +72 -49
  36. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +203 -209
  37. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +67 -91
  38. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +21 -26
  39. package/dist/extensions/Blocks/Recommendation/utils/partnerCustomizations.js +3 -1
  40. package/dist/extensions/Blocks/Recommendation/utils/partnerScope.js +25 -0
  41. package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +16 -55
  42. package/dist/guido.css +1 -1
  43. package/dist/src/@types/config/schemas.d.ts +16 -0
  44. package/dist/src/components/organisms/base/AuthErrorModal.vue.d.ts +2 -0
  45. package/dist/src/components/wrappers/WpModal.vue.d.ts +5 -1
  46. package/dist/src/composables/useAuthError.d.ts +12 -0
  47. package/dist/src/composables/useConfig.d.ts +2 -0
  48. package/dist/src/composables/useCortexBlueprintBridge.d.ts +2 -3
  49. package/dist/src/composables/useEmailTemplateApplier.d.ts +18 -5
  50. package/dist/src/composables/useGuidoActions.d.ts +2 -0
  51. package/dist/src/composables/useHttp.d.ts +2 -0
  52. package/dist/src/config/compiler/utils/itemsCompilerUtils.d.ts +5 -0
  53. package/dist/src/config/migrator/index.d.ts +2 -1
  54. package/dist/src/config/migrator/recommendationPartnerMigrator.d.ts +19 -0
  55. package/dist/src/enums/extensions/recommendationBlock.d.ts +1 -1
  56. package/dist/src/extensions/Blocks/Items/block.d.ts +5 -0
  57. package/dist/src/extensions/Blocks/Items/constants/cardLayout.d.ts +44 -0
  58. package/dist/src/extensions/Blocks/Items/constants/cardWidth.d.ts +12 -0
  59. package/dist/src/extensions/Blocks/Items/enums/productEnums.d.ts +3 -0
  60. package/dist/src/extensions/Blocks/Items/template.d.ts +19 -0
  61. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +0 -2
  62. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +2 -13
  63. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +6 -0
  64. package/dist/src/extensions/Blocks/Recommendation/utils/nodeConfigWriter.d.ts +1 -3
  65. package/dist/src/extensions/Blocks/Recommendation/utils/partnerScope.d.ts +33 -0
  66. package/dist/src/extensions/Blocks/Recommendation/utils/strategyCommit.d.ts +0 -7
  67. package/dist/src/mock/cortexChatStore.d.ts +12 -0
  68. package/dist/src/stores/config.d.ts +20 -0
  69. package/dist/src/stores/guido-email-editor.d.ts +20 -10
  70. package/dist/src/stores/onboarding.d.ts +4 -0
  71. package/dist/src/stores/recommendation.d.ts +5 -0
  72. package/dist/src/utils/dateUtil.d.ts +10 -0
  73. package/dist/src/utils/genericUtil.d.ts +3 -0
  74. package/dist/src/utils/liquidProtection.d.ts +3 -0
  75. package/dist/static/styles/components/recommendation-strategy.css.js +9 -0
  76. package/dist/static/styles/components/version-history.css.js +2 -6
  77. package/dist/stores/guido-email-editor.js +3 -1
  78. package/dist/stores/onboarding.js +4 -0
  79. package/dist/utils/liquidProtection.js +5 -0
  80. package/dist/utils/pairProductVariables.js +71 -71
  81. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import { BlockId as f } from "../../enums/block.js";
2
- import { DEFAULT_NODE_CONFIG as b } from "../../extensions/Blocks/Recommendation/constants/defaultConfig.js";
3
- import { ATTR_RECOMMENDATION_TITLE as y } from "../../extensions/Blocks/Recommendation/constants/selectors.js";
2
+ import { DEFAULT_NODE_CONFIG as y } from "../../extensions/Blocks/Recommendation/constants/defaultConfig.js";
3
+ import { ATTR_RECOMMENDATION_TITLE as b } from "../../extensions/Blocks/Recommendation/constants/selectors.js";
4
4
  import { useTemplateStore as T } from "../../stores/template.js";
5
5
  import { mapComposition as v } from "./recommendation/compositionMapper.js";
6
6
  import { extractCurrencyFromBlock as C, extractTitleText as M, hasVisibleTitle as R, extractCardBgColor as S, isPartnerManagedBlock as h } from "./recommendation/extractors.js";
@@ -8,28 +8,28 @@ import { buildBlockHtml as w } from "./recommendation/htmlBuilder.js";
8
8
  import { parseRecommendationId as x, parseLegacyConfig as E } from "./recommendation/parseLegacyConfig.js";
9
9
  import { mapSettings as A } from "./recommendation/settingsMapper.js";
10
10
  const H = 'td[esd-dev-product-config][class*="ins-recommendation-v3-block-"]:not(.recommendation-block-v2), td.product-block[esd-handler-name*="EmailRecommendationV3"][esd-dev-product-config]:not(.recommendation-block-v2)';
11
- function B(n, t, a) {
11
+ function B(n, t, c) {
12
12
  var l;
13
- const o = x(t);
14
- if (o === null)
13
+ const r = x(t);
14
+ if (r === null)
15
15
  return console.warn(
16
16
  "[RecommendationMigrator] Skipping block — missing/invalid `ins-recommendation-v3-campaign-id`"
17
17
  ), !1;
18
- const r = E(t);
19
- if (!r)
18
+ const o = E(t);
19
+ if (!o)
20
20
  return console.warn(
21
- `[RecommendationMigrator] Aborting block id=${o} — \`esd-dev-product-config\` missing or unable to be parsed`
21
+ `[RecommendationMigrator] Aborting block id=${r} — \`esd-dev-product-config\` missing or unable to be parsed`
22
22
  ), !1;
23
- const i = a[String(o)] ?? {
23
+ const a = c[String(r)] ?? {
24
24
  currencySettings: C(t)
25
- }, c = A(i, r, o), e = v((l = r.composition) == null ? void 0 : l.variables), d = M(t);
26
- e.titleVariable || (e.visibility[y] = R(t));
25
+ }, i = A(a, o, r), e = v((l = o.composition) == null ? void 0 : l.variables), d = M(t);
26
+ e.titleVariable || (e.visibility[b] = R(t));
27
27
  const p = S(t), g = {
28
- ...c,
28
+ ...i,
29
29
  strategyId: "",
30
30
  composition: e.composition,
31
31
  visibility: e.visibility,
32
- previousTitleHtml: b.previousTitleHtml,
32
+ previousTitleHtml: y.previousTitleHtml,
33
33
  textTrimming: e.anyTextTrimming
34
34
  }, m = h(t), u = `
35
35
  <table>
@@ -56,30 +56,37 @@ function B(n, t, a) {
56
56
  </table>
57
57
  `, s = n.parseFromString(u, "text/html").querySelector("td.esd-structure");
58
58
  return !s || !t.parentNode ? (console.warn(
59
- `[RecommendationMigrator] Aborting block id=${o} — failed to construct new HTML element`
59
+ `[RecommendationMigrator] Aborting block id=${r} — failed to construct new HTML element`
60
60
  ), !1) : (t.parentNode.replaceChild(s, t), !0);
61
61
  }
62
62
  function G(n, t = {}) {
63
- const a = new DOMParser(), o = a.parseFromString(n, "text/html"), r = Array.from(o.querySelectorAll(H));
63
+ const c = new DOMParser();
64
+ let r;
65
+ try {
66
+ r = c.parseFromString(n, "text/html");
67
+ } catch (i) {
68
+ return console.error("[RecommendationMigrator] Failed to parse template:", i), n;
69
+ }
70
+ const o = Array.from(r.querySelectorAll(H));
64
71
  try {
65
72
  T().$patch((e) => {
66
73
  e.migrations = {
67
74
  ...e.migrations,
68
- [f.Recommendation]: r.length
75
+ [f.Recommendation]: o.length
69
76
  };
70
77
  });
71
78
  } catch {
72
79
  }
73
- if (r.length === 0)
80
+ if (o.length === 0)
74
81
  return n;
75
- let i = 0;
76
- return r.forEach((c) => {
82
+ let a = 0;
83
+ return o.forEach((i) => {
77
84
  try {
78
- B(a, c, t) && (i += 1);
85
+ B(c, i, t) && (a += 1);
79
86
  } catch (e) {
80
87
  console.error("[RecommendationMigrator] Unexpected error migrating block:", e);
81
88
  }
82
- }), i > 0 && console.info(`[RecommendationMigrator] Migrated ${i} legacy Recommendation block(s)`), o.documentElement.outerHTML;
89
+ }), a > 0 && console.info(`[RecommendationMigrator] Migrated ${a} legacy Recommendation block(s)`), r.documentElement.outerHTML;
83
90
  }
84
91
  export {
85
92
  G as migrateRecommendation
@@ -0,0 +1,56 @@
1
+ import { RECOMMENDATION_ID_ATTR as a, SELECTOR_ATTRIBUTE_ROW as f, ATTR_DATA_ATTRIBUTE_TYPE as _, ATTR_CUSTOM_PREFIX as g, ATTR_DATA_CARD_COMPOSITION as m, ATTR_DATA_CUSTOM_ATTRIBUTES as R } from "../../extensions/Blocks/Recommendation/constants/selectors.js";
2
+ import { carriesForeignPartnerConfig as O, canJudgeUnstampedBlock as d, withoutCustomAttributes as l } from "../../extensions/Blocks/Recommendation/utils/partnerScope.js";
3
+ const E = ".recommendation-block-v2[esd-ext-config]", T = "esd-ext-config";
4
+ function S(t) {
5
+ const r = t.getAttribute(T);
6
+ if (!r)
7
+ return null;
8
+ try {
9
+ const e = JSON.parse(r);
10
+ return e && typeof e == "object" && !Array.isArray(e) ? e : null;
11
+ } catch {
12
+ return null;
13
+ }
14
+ }
15
+ function p(t, r, e) {
16
+ const s = l(r.composition ?? []);
17
+ t.querySelectorAll(f).forEach((o) => {
18
+ var u;
19
+ (u = o.getAttribute(_)) != null && u.startsWith(g) && o.remove();
20
+ }), t.setAttribute(m, s.join(",")), t.setAttribute(R, "[]"), t.setAttribute(T, JSON.stringify({
21
+ ...r,
22
+ strategyId: "",
23
+ strategy: "",
24
+ filters: [],
25
+ productIds: [],
26
+ composition: s,
27
+ partnerName: e
28
+ }));
29
+ }
30
+ function I(t, { partnerName: r, campaignUrls: e, rrsEnabled: s }) {
31
+ if (!r)
32
+ return t;
33
+ let o;
34
+ try {
35
+ o = new DOMParser().parseFromString(t, "text/html");
36
+ } catch (n) {
37
+ return console.error("[RecommendationPartnerMigrator] Failed to parse template:", n), t;
38
+ }
39
+ const u = Array.from(o.querySelectorAll(E));
40
+ if (u.length === 0)
41
+ return t;
42
+ let c = 0;
43
+ return u.forEach((n) => {
44
+ const i = S(n), A = Number(n.getAttribute(a));
45
+ if (!(!i || !Number.isFinite(A))) {
46
+ if (O({ config: i, blockId: A, partnerName: r, campaignUrls: e, rrsEnabled: s })) {
47
+ p(n, i, r), c += 1;
48
+ return;
49
+ }
50
+ i.partnerName || !d({ config: i, campaignUrls: e, rrsEnabled: s }) || (n.setAttribute(T, JSON.stringify({ ...i, partnerName: r })), c += 1);
51
+ }
52
+ }), c > 0 ? o.documentElement.outerHTML : t;
53
+ }
54
+ export {
55
+ I as migrateRecommendationPartnerScope
56
+ };
@@ -1,5 +1,5 @@
1
1
  import { useTranslations as s } from "../../composables/useTranslations.js";
2
- const a = {
2
+ const t = {
3
3
  RECOMMENDATION_API_URL: "https://recommendationv2.api.useinsider.com",
4
4
  // Relative path → same-origin as the embedding inone dashboard.
5
5
  PRODUCT_ATTRIBUTES_PATH: "/product-attributes/get-attributes",
@@ -9,17 +9,17 @@ const a = {
9
9
  MIGRATE_STRATEGIES_PATH: "/newsletter/recommendations/migrate-strategies",
10
10
  // The template route narrows the recommendations resource before the action: the id
11
11
  // travels in the body, not the path.
12
- TEMPLATE_MIGRATE_STRATEGIES_PATH: "/newsletter/recommendations/template/migrate-strategies",
13
- // Smart Recommender hides the Email channel unless the URL asks for it, so a strategy created
14
- // without this flag can never be Email-suitable and would never reach the editor's list.
15
- RECOMMENDATION_STRATEGY_CREATE_PATH: "/discovery/recommendation-strategies/create?isEmail=true"
16
- }, d = (e) => {
17
- const { RECOMMENDATION_STRATEGIES_PANEL_PATH: n } = a;
18
- return `${n}/${e}/edit?isEmail=true`;
19
- }, m = {
20
- campaign: a.MIGRATE_STRATEGIES_PATH,
21
- template: a.TEMPLATE_MIGRATE_STRATEGIES_PATH
12
+ TEMPLATE_MIGRATE_STRATEGIES_PATH: "/newsletter/recommendations/template/migrate-strategies"
13
+ }, d = () => {
14
+ const { RECOMMENDATION_STRATEGIES_PANEL_PATH: e } = t;
15
+ return `${e}/create`;
16
+ }, m = (e) => {
17
+ const { RECOMMENDATION_STRATEGIES_PANEL_PATH: n } = t;
18
+ return `${n}/${e}/edit`;
22
19
  }, T = {
20
+ campaign: t.MIGRATE_STRATEGIES_PATH,
21
+ template: t.TEMPLATE_MIGRATE_STRATEGIES_PATH
22
+ }, p = {
23
23
  CLIENT_ID: "clientId"
24
24
  }, E = () => {
25
25
  const e = s();
@@ -85,21 +85,21 @@ const a = {
85
85
  path: "top-sellers"
86
86
  }
87
87
  ];
88
- }, p = ["discount", "omnibus_price", "omnibus_discount", "price", "original_price"], A = [
88
+ }, A = ["discount", "omnibus_price", "omnibus_discount", "price", "original_price"], v = [
89
89
  { text: "before the amount", value: "0" },
90
90
  { text: "after the amount", value: "1" }
91
- ], v = [
91
+ ], _ = [
92
92
  { text: "dot(.)", value: "." },
93
93
  { text: "comma(,)", value: "," },
94
94
  { text: "space( )", value: " " }
95
- ], _ = [
95
+ ], h = [
96
96
  { text: "0", value: "0" },
97
97
  { text: "1", value: "1" },
98
98
  { text: "2", value: "2" },
99
99
  { text: "3", value: "3" },
100
100
  { text: "4", value: "4" },
101
101
  { text: "5", value: "5" }
102
- ], r = "||", t = [
102
+ ], r = "||", a = [
103
103
  { text: "is exactly", value: "=" },
104
104
  { text: "contains", value: "~" },
105
105
  { text: "does not contain", value: "!~" },
@@ -121,9 +121,9 @@ const a = {
121
121
  ], c = [
122
122
  { text: "true", value: "==" },
123
123
  { text: "false", value: "!=" }
124
- ], h = (e) => {
124
+ ], x = (e) => {
125
125
  if (!e)
126
- return t;
126
+ return a;
127
127
  switch (e) {
128
128
  case "Boolean":
129
129
  return c;
@@ -132,28 +132,29 @@ const a = {
132
132
  case "Number":
133
133
  return i;
134
134
  case "String":
135
- return t;
135
+ return a;
136
136
  case "Strings":
137
137
  return o;
138
138
  default:
139
- return t;
139
+ return a;
140
140
  }
141
141
  };
142
142
  export {
143
- m as MIGRATION_PATHS,
143
+ T as MIGRATION_PATHS,
144
144
  r as OP_ANY_OF,
145
- p as PriceAttributes,
146
- T as QUERY_PARAMS,
147
- a as URLS,
148
- _ as currencyDecimalCounts,
149
- A as currencyLocationMaps,
150
- v as currencyOperators,
151
- h as getOperatorOptions,
145
+ A as PriceAttributes,
146
+ p as QUERY_PARAMS,
147
+ t as URLS,
148
+ h as currencyDecimalCounts,
149
+ v as currencyLocationMaps,
150
+ _ as currencyOperators,
151
+ x as getOperatorOptions,
152
152
  E as getRecommendationFeedSourceMaps,
153
153
  o as operatorOptionsForArrayOfStrings,
154
154
  c as operatorOptionsForBooleans,
155
155
  u as operatorOptionsForDates,
156
156
  i as operatorOptionsForNumbers,
157
- t as operatorOptionsForStrings,
158
- d as strategyEditPath
157
+ a as operatorOptionsForStrings,
158
+ d as strategyCreatePath,
159
+ m as strategyEditPath
159
160
  };
@@ -1,32 +1,33 @@
1
1
  var k = Object.defineProperty;
2
- var D = (l, a, t) => a in l ? k(l, a, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[a] = t;
3
- var y = (l, a, t) => D(l, typeof a != "symbol" ? a + "" : a, t);
4
- import { BlockId as N } from "../../../enums/block.js";
2
+ var S = (d, l, e) => l in d ? k(d, l, { enumerable: !0, configurable: !0, writable: !0, value: e }) : d[l] = e;
3
+ var g = (d, l, e) => S(d, typeof l != "symbol" ? l + "" : l, e);
4
+ import { BlockId as D } from "../../../enums/block.js";
5
5
  import { useOnboardingStore as T } from "../../../stores/onboarding.js";
6
- import { getMigrationBannerHtml as S } from "../../../utils/migrationBannerHtml.js";
7
- import { Block as A, BlockCompositionType as M, ModificationDescription as u } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
8
- import { currencyAttrTargets as H, ITEMS_CURRENCY_ATTR as m } from "./constants/currency.js";
9
- import { ItemsBlockId as R } from "./enums/controlEnums.js";
10
- import { SETTINGS_ENUMS as C, DefaultConfigValues as g } from "./enums/settingsEnums.js";
6
+ import { getMigrationBannerHtml as N } from "../../../utils/migrationBannerHtml.js";
7
+ import { Block as H, BlockCompositionType as R, ModificationDescription as u } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
8
+ import { PRODUCT_WRAPPER_SELECTOR as M, isZeroWidthValue as m } from "./constants/cardWidth.js";
9
+ import { currencyAttrTargets as w, ITEMS_CURRENCY_ATTR as y } from "./constants/currency.js";
10
+ import { ItemsBlockId as E } from "./enums/controlEnums.js";
11
+ import { SETTINGS_ENUMS as b, DefaultConfigValues as p } from "./enums/settingsEnums.js";
11
12
  import { getDefaultTemplate as O } from "./template.js";
12
- import { getItemsBlockContainer as b, getItemsBlockConfig as h, deriveItemNumber as B, generateBlockInstanceId as E, getDefaultItemsBlockConfig as w } from "./utils/nodeConfigUtils.js";
13
- const _ = N.Items, P = "Reconcile Items currency DOM attributes";
14
- class K extends A {
13
+ import { getItemsBlockContainer as _, getItemsBlockConfig as C, deriveItemNumber as B, generateBlockInstanceId as P, getDefaultItemsBlockConfig as v } from "./utils/nodeConfigUtils.js";
14
+ const A = D.Items, V = "Reconcile Items currency DOM attributes";
15
+ class $ extends H {
15
16
  constructor() {
16
17
  super(...arguments);
17
18
  /** Block instances whose currency attrs were already self-healed this session (SD-147588 — undo-safe). */
18
- y(this, "_currencyHealed", /* @__PURE__ */ new Set());
19
+ g(this, "_currencyHealed", /* @__PURE__ */ new Set());
19
20
  /** blockInstanceIds already claimed by a live block this session (SD-147588 collision detection). */
20
- y(this, "_seenInstanceIds", /* @__PURE__ */ new Set());
21
+ g(this, "_seenInstanceIds", /* @__PURE__ */ new Set());
21
22
  }
22
23
  getId() {
23
- return _;
24
+ return A;
24
25
  }
25
26
  getIcon() {
26
27
  return "items-icon";
27
28
  }
28
29
  getBlockCompositionType() {
29
- return M.CONTAINER;
30
+ return R.CONTAINER;
30
31
  }
31
32
  getName() {
32
33
  return this.api.translate("Items");
@@ -35,20 +36,20 @@ class K extends A {
35
36
  return this.api.translate("Items lets you display personalized products based on user behavior.");
36
37
  }
37
38
  getSettingsPanelTitleHtml() {
38
- return S(
39
- _,
39
+ return N(
40
+ A,
40
41
  this.api.translate("Items"),
41
42
  this.api.translate("This block is switched from the Old Version to the New Version. We recommend you check the Items block and test your message to ensure it works properly.")
42
43
  );
43
44
  }
44
45
  getTemplate() {
45
46
  return O({
46
- orientation: C.ORIENTATION.VERTICAL,
47
- itemsType: C.ITEMS_TYPE.CART_ITEMS,
47
+ orientation: b.ORIENTATION.VERTICAL,
48
+ itemsType: b.ITEMS_TYPE.CART_ITEMS,
48
49
  itemId: "{{Abandoned Cart Item (1) Url}}",
49
- currencySymbol: g.productPriceCurrencySymbolControlValue,
50
- currencyLocation: g.productPriceCurrencyLocationControlValue,
51
- formattedPrice: g.productPriceFormattedControlValue === "1"
50
+ currencySymbol: p.productPriceCurrencySymbolControlValue,
51
+ currencyLocation: p.productPriceCurrencyLocationControlValue,
52
+ formattedPrice: p.productPriceFormattedControlValue === "1"
52
53
  });
53
54
  }
54
55
  allowInnerBlocksDND() {
@@ -57,27 +58,27 @@ class K extends A {
57
58
  canBeSavedAsModule() {
58
59
  return !0;
59
60
  }
60
- onCreated(t) {
61
- const o = this.api.getDocumentModifier(), c = this.api.getDocumentRootCssNode();
62
- c.querySelector('[product-attr="imageSrc"] img') || o.modifyCss(c).appendRule('[product-attr="imageSrc"] img {object-fit: contain;}');
63
- const i = b(t);
64
- if (!i)
61
+ onCreated(e) {
62
+ const t = this.api.getDocumentModifier(), c = this.api.getDocumentRootCssNode();
63
+ c.querySelector('[product-attr="imageSrc"] img') || t.modifyCss(c).appendRule('[product-attr="imageSrc"] img {object-fit: contain;}');
64
+ const r = _(e);
65
+ if (!r)
65
66
  return;
66
- const r = i.getNodeConfig(), s = r && Object.keys(r).length > 0, e = h(t);
67
- if (e != null && e.initialized) {
67
+ const o = r.getNodeConfig(), s = o && Object.keys(o).length > 0, i = C(e);
68
+ if (i != null && i.initialized) {
68
69
  if (!s) {
69
- const d = this.api.getDocumentModifier();
70
- d.modifyHtml(i).setNodeConfig(e), this._stampProductTdDomAttributes(i, e, d), this._shouldReconcileCurrency(e) && this._reconcileCurrencyDomAttributes(i, e, d), d.apply(new u("Migrate legacy config to nodeConfig")), this._markCurrencyHealed(e.blockInstanceId);
70
+ const a = this.api.getDocumentModifier();
71
+ a.modifyHtml(r).setNodeConfig(i), this._stampProductTdDomAttributes(r, i, a), this._healCollapsedWidths(r, a), this._shouldReconcileCurrency(i) && this._reconcileCurrencyDomAttributes(r, i, a), a.apply(new u("Migrate legacy config to nodeConfig")), this._markCurrencyHealed(i.blockInstanceId);
71
72
  return;
72
73
  }
73
74
  } else {
74
- const d = w(), p = this.api.getDocumentModifier();
75
- p.modifyHtml(i).setNodeConfig(d), this._stampProductTdDomAttributes(i, d, p, !0), p.apply(new u("Initialize Items block with default configuration")), T().startOnboarding("itemsOnboarding");
75
+ const a = v(), I = this.api.getDocumentModifier();
76
+ I.modifyHtml(r).setNodeConfig(a), this._stampProductTdDomAttributes(r, a, I, !0), I.apply(new u("Initialize Items block with default configuration")), T().startOnboarding("itemsOnboarding");
76
77
  return;
77
78
  }
78
- const n = this._resolveInstanceId(e.blockInstanceId), f = this.api.getDocumentModifier();
79
- let I = !1;
80
- n !== e.blockInstanceId && (f.modifyHtml(i).setNodeConfig({ ...e, blockInstanceId: n }), I = !0), !this._currencyHealed.has(n) && this._reconcileCurrencyDomAttributes(i, e, f) && (I = !0), I && f.apply(new u("Assign Items block instance ID and reconcile currency")), this._markCurrencyHealed(n);
79
+ const n = this._resolveInstanceId(i.blockInstanceId), f = this.api.getDocumentModifier();
80
+ let h = !1;
81
+ n !== i.blockInstanceId && (f.modifyHtml(r).setNodeConfig({ ...i, blockInstanceId: n }), h = !0), !this._currencyHealed.has(n) && this._reconcileCurrencyDomAttributes(r, i, f) && (h = !0), this._healCollapsedWidths(r, f) && (h = !0), h && f.apply(new u("Assign Items block instance ID and reconcile currency")), this._markCurrencyHealed(n);
81
82
  }
82
83
  /**
83
84
  * Re-seeds nodeConfig from the persisted esd-ext-config when a saved module
@@ -85,24 +86,24 @@ class K extends A {
85
86
  * into nodeConfig, so without this a reused module would reset to defaults.
86
87
  * Guarded to the nodeConfig-empty case so it runs once and never loops.
87
88
  */
88
- onDocumentChanged(t) {
89
- const o = b(t);
90
- if (!o)
89
+ onDocumentChanged(e) {
90
+ const t = _(e);
91
+ if (!t)
91
92
  return;
92
- const c = o.getNodeConfig();
93
+ const c = t.getNodeConfig();
93
94
  if (c && Object.keys(c).length > 0) {
94
- const e = h(t);
95
- if (e != null && e.initialized && this._shouldReconcileCurrency(e)) {
95
+ const i = C(e);
96
+ if (i != null && i.initialized && this._shouldReconcileCurrency(i)) {
96
97
  const n = this.api.getDocumentModifier();
97
- this._reconcileCurrencyDomAttributes(o, e, n) && n.apply(new u(P)), this._markCurrencyHealed(e.blockInstanceId);
98
+ this._reconcileCurrencyDomAttributes(t, i, n) && n.apply(new u(V)), this._markCurrencyHealed(i.blockInstanceId);
98
99
  }
99
100
  return;
100
101
  }
101
- const r = h(t);
102
- if (!(r != null && r.initialized))
102
+ const o = C(e);
103
+ if (!(o != null && o.initialized))
103
104
  return;
104
105
  const s = this.api.getDocumentModifier();
105
- s.modifyHtml(o).setNodeConfig(r), this._stampProductTdDomAttributes(o, r, s), this._shouldReconcileCurrency(r) && this._reconcileCurrencyDomAttributes(o, r, s), s.apply(new u("Recover Items block config from saved module")), this._markCurrencyHealed(r.blockInstanceId);
106
+ s.modifyHtml(t).setNodeConfig(o), this._stampProductTdDomAttributes(t, o, s), this._healCollapsedWidths(t, s), this._shouldReconcileCurrency(o) && this._reconcileCurrencyDomAttributes(t, o, s), s.apply(new u("Recover Items block config from saved module")), this._markCurrencyHealed(o.blockInstanceId);
106
107
  }
107
108
  /**
108
109
  * Bakes the compiler-read DOM attributes (`data-type`, `data-number`, `data-nodup`) onto the
@@ -112,11 +113,21 @@ class K extends A {
112
113
  * restored before export. The name `<a>` carries no data-type/data-number of its own and
113
114
  * relies on this td-level fallback in pairProductVariables.
114
115
  */
115
- _stampProductTdDomAttributes(t, o, c, i = !1) {
116
- const r = B(o.itemsSelectValue, o.type), s = (e, n) => {
117
- i && t.getAttribute(e) || c.modifyHtml(t).setAttribute(e, n);
116
+ _stampProductTdDomAttributes(e, t, c, r = !1) {
117
+ const o = B(t.itemsSelectValue, t.type), s = (i, n) => {
118
+ r && e.getAttribute(i) || c.modifyHtml(e).setAttribute(i, n);
118
119
  };
119
- s("data-type", o.type), s("data-number", r), s("data-nodup", String(o.priceHideDiscount));
120
+ s("data-type", t.type), s("data-number", o), s("data-nodup", String(t.priceHideDiscount));
121
+ }
122
+ /**
123
+ * Repairs a saved module's collapsed card into the state the load migrator produces. Acts only
124
+ * on a zero width, so Stripo's non-zero drop-time width never triggers it and a healed block no-ops.
125
+ */
126
+ _healCollapsedWidths(e, t) {
127
+ const r = e.querySelectorAll(M).filter((o) => m(o.getAttribute("width")) || m(o.getStyle("width")));
128
+ return !m(e.getAttribute("width")) && !r.length ? !1 : (e.hasClass("esd-container-frame") && t.modifyHtml(e).removeClass("esd-container-frame"), e.getAttribute("width") !== null && t.modifyHtml(e).removeAttribute("width"), r.forEach((o) => {
129
+ m(o.getAttribute("width")) && t.modifyHtml(o).setAttribute("width", "100%"), m(o.getStyle("width")) && t.modifyHtml(o).setStyle("width", "100%");
130
+ }), !0);
120
131
  }
121
132
  /**
122
133
  * Whether a currency self-heal pass should run for this block (SD-147588). The only gate here is
@@ -126,12 +137,12 @@ class K extends A {
126
137
  * the symbol write alone is skipped for the 'USD' sentinel — so we must NOT gate the whole pass
127
138
  * on symbol customization here, or a default-symbol block with a toggled location never heals.
128
139
  */
129
- _shouldReconcileCurrency(t) {
130
- return !t.blockInstanceId || !this._currencyHealed.has(t.blockInstanceId);
140
+ _shouldReconcileCurrency(e) {
141
+ return !e.blockInstanceId || !this._currencyHealed.has(e.blockInstanceId);
131
142
  }
132
143
  /** Marks a block instance's currency as reconciled so it is not healed again (undo-safe). */
133
- _markCurrencyHealed(t) {
134
- t && this._currencyHealed.add(t);
144
+ _markCurrencyHealed(e) {
145
+ e && this._currencyHealed.add(e);
135
146
  }
136
147
  /**
137
148
  * Resolves the id for a just-created block to one that is unique per live instance.
@@ -140,13 +151,13 @@ class K extends A {
140
151
  * currency heal guard and settings-panel switch detection. Mint a fresh id on absence
141
152
  * or collision, otherwise keep the existing one. Registers the result as claimed.
142
153
  */
143
- _resolveInstanceId(t) {
144
- let o = t;
145
- if (!o || this._seenInstanceIds.has(o))
154
+ _resolveInstanceId(e) {
155
+ let t = e;
156
+ if (!t || this._seenInstanceIds.has(t))
146
157
  do
147
- o = E();
148
- while (this._seenInstanceIds.has(o));
149
- return this._seenInstanceIds.add(o), o;
158
+ t = P();
159
+ while (this._seenInstanceIds.has(t));
160
+ return this._seenInstanceIds.add(t), t;
150
161
  }
151
162
  /**
152
163
  * Stamps the export-read currency attrs onto every price `<p>` from config, so a template whose
@@ -159,15 +170,15 @@ class K extends A {
159
170
  * Returns true only when an attr actually changed, so the caller can skip an empty apply that
160
171
  * would otherwise re-trigger onDocumentChanged and loop.
161
172
  */
162
- _reconcileCurrencyDomAttributes(t, o, c) {
163
- const { position: i, symbol: r } = H(o), s = t.querySelectorAll(`.${R.PRICE} p`);
164
- let e = !1;
173
+ _reconcileCurrencyDomAttributes(e, t, c) {
174
+ const { position: r, symbol: o } = w(t), s = e.querySelectorAll(`.${E.PRICE} p`);
175
+ let i = !1;
165
176
  return s.forEach((n) => {
166
- i !== void 0 && n.getAttribute(m.POSITION) !== i && (c.modifyHtml(n).setAttribute(m.POSITION, i), e = !0), r !== void 0 && n.getAttribute(m.SYMBOL) !== r && (c.modifyHtml(n).setAttribute(m.SYMBOL, r), e = !0);
167
- }), e;
177
+ r !== void 0 && n.getAttribute(y.POSITION) !== r && (c.modifyHtml(n).setAttribute(y.POSITION, r), i = !0), o !== void 0 && n.getAttribute(y.SYMBOL) !== o && (c.modifyHtml(n).setAttribute(y.SYMBOL, o), i = !0);
178
+ }), i;
168
179
  }
169
180
  }
170
181
  export {
171
- _ as BLOCK_ID,
172
- K as ItemsBlock
182
+ A as BLOCK_ID,
183
+ $ as ItemsBlock
173
184
  };
@@ -0,0 +1,20 @@
1
+ import { SETTINGS_ENUMS as r } from "../enums/settingsEnums.js";
2
+ const I = "130px", L = "100%", R = (e) => e === r.ORIENTATION.HORIZONTAL ? I : L, n = {
3
+ VERTICAL: "es-p5b es-p5t",
4
+ HORIZONTAL: "es-p5l es-p5r"
5
+ }, o = "data-items-cell-pad", d = (e) => `${o}="${e ? "v" : "h"}"`, t = (e) => e ? ` ${n.VERTICAL}` : ` ${n.HORIZONTAL}`, E = (e, A) => {
6
+ if (!e.includes(o))
7
+ return e;
8
+ const T = A ? n.HORIZONTAL : n.VERTICAL, s = A ? n.VERTICAL : n.HORIZONTAL, c = A ? "v" : "h";
9
+ return e.includes(T) ? e.replace(T, s).replace(new RegExp(`${o}="[hv]"`), `${o}="${c}"`) : e;
10
+ };
11
+ export {
12
+ n as BLOCK_CELL_PADDING,
13
+ o as BLOCK_CELL_PAD_ATTR,
14
+ I as NAME_HORIZONTAL_MAX_WIDTH,
15
+ L as NAME_VERTICAL_MAX_WIDTH,
16
+ d as blockCellPadMarker,
17
+ t as blockCellPaddingFor,
18
+ R as nameMaxWidthFor,
19
+ E as reorientBlockCellPadding
20
+ };
@@ -0,0 +1,20 @@
1
+ const R = ".ins-product-td", T = ".ins-product-wrapper", s = "width: 100%", c = /(^|;)\s*width\s*:\s*0(?:px|%)?\s*(?:!important)?\s*(?=;|$)/i, n = new RegExp(c.source, "gi"), o = /(^|;)\s*width\s*:/i, _ = /^0(?:px|%)?$/i, a = (t) => _.test((t ?? "").trim()), E = (t) => c.test(t), h = (t) => {
2
+ if (E(t))
3
+ return t.replace(
4
+ n,
5
+ (i, e) => `${e}${e ? " " : ""}${s}`
6
+ );
7
+ if (o.test(t))
8
+ return t;
9
+ const r = t.trim();
10
+ return r ? r.endsWith(";") ? `${r} ${s};` : `${r}; ${s};` : `${s};`;
11
+ }, p = (t) => t.replace(n, (r, i) => i).replace(/;{2,}/g, ";").replace(/^\s*;\s*/, "").replace(/;\s*$/, "").trim();
12
+ export {
13
+ R as PRODUCT_TD_SELECTOR,
14
+ T as PRODUCT_WRAPPER_SELECTOR,
15
+ s as WIDTH_PIN_DECLARATION,
16
+ E as hasZeroWidthDeclaration,
17
+ a as isZeroWidthValue,
18
+ h as withWidthPin,
19
+ p as withoutZeroWidth
20
+ };
@@ -1,14 +1,15 @@
1
- import { ModificationDescription as l, UIElementType as s, UEAttr as d } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
- import { CommonControl as p } from "../../../common-control.js";
1
+ import { ModificationDescription as d, UIElementType as s, UEAttr as p } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
+ import { CommonControl as T } from "../../../common-control.js";
3
+ import { nameMaxWidthFor as h } from "../../constants/cardLayout.js";
3
4
  import { ItemsBlockControlId as a } from "../../enums/controlEnums.js";
4
- import { findNameTextNode as T } from "../../utils/nameNode.js";
5
- import { getItemsBlockConfig as r, setItemsBlockConfig as c } from "../../utils/nodeConfigUtils.js";
6
- const g = a.NAME_TRIMMING, i = {
5
+ import { findNameTextNode as c } from "../../utils/nameNode.js";
6
+ import { getItemsBlockConfig as r, setItemsBlockConfig as g } from "../../utils/nodeConfigUtils.js";
7
+ const I = a.NAME_TRIMMING, n = {
7
8
  TRIMMING: "trimming"
8
9
  };
9
- class y extends p {
10
+ class E extends T {
10
11
  getId() {
11
- return g;
12
+ return I;
12
13
  }
13
14
  getTemplate() {
14
15
  return `
@@ -19,39 +20,39 @@ class y extends p {
19
20
  }
20
21
  onRender() {
21
22
  const e = r(this.currentNode);
22
- this.api.updateValues({ [i.TRIMMING]: (e == null ? void 0 : e.nameTrimming) ?? !0 }), this.api.onValueChanged(i.TRIMMING, (t) => {
23
+ this.api.updateValues({ [n.TRIMMING]: (e == null ? void 0 : e.nameTrimming) ?? !0 }), this.api.onValueChanged(n.TRIMMING, (t) => {
23
24
  this._onTrimmingChange(t);
24
25
  });
25
26
  }
26
27
  onTemplateNodeUpdated(e) {
27
28
  super.onTemplateNodeUpdated(e), this.handleBlockInstanceChange(() => {
28
29
  const t = r(this.currentNode);
29
- this.api.updateValues({ [i.TRIMMING]: (t == null ? void 0 : t.nameTrimming) ?? !0 });
30
+ this.api.updateValues({ [n.TRIMMING]: (t == null ? void 0 : t.nameTrimming) ?? !0 });
30
31
  });
31
32
  }
32
33
  _onTrimmingChange(e) {
33
- c(this.currentNode, this.api, { nameTrimming: e }), this.api.updateValues({ [i.TRIMMING]: e }), this._applyTrimmingStyles(e);
34
+ g(this.currentNode, this.api, { nameTrimming: e }), this.api.updateValues({ [n.TRIMMING]: e }), this._applyTrimmingStyles(e);
34
35
  }
35
36
  _applyTrimmingStyles(e) {
36
- const t = T(this.currentNode);
37
+ const t = c(this.currentNode);
37
38
  if (!t)
38
39
  return;
39
- const n = r(this.currentNode), m = e !== void 0 ? e : (n == null ? void 0 : n.nameTrimming) ?? !0, o = this.api.getDocumentModifier().modifyHtml(t);
40
- m ? o.setStyle("white-space", "nowrap").setStyle("overflow", "hidden").setStyle("text-overflow", "ellipsis") : o.removeStyle("white-space").removeStyle("overflow").removeStyle("text-overflow"), o.setStyle("max-width", "100%").apply(new l(`Text Trimming ${m ? "Enabled" : "Disabled"}`));
40
+ const i = r(this.currentNode), m = e !== void 0 ? e : (i == null ? void 0 : i.nameTrimming) ?? !0, l = h(i == null ? void 0 : i.orientation), o = this.api.getDocumentModifier().modifyHtml(t);
41
+ m ? o.setStyle("white-space", "nowrap").setStyle("overflow", "hidden").setStyle("text-overflow", "ellipsis") : o.removeStyle("white-space").removeStyle("overflow").removeStyle("text-overflow"), o.setStyle("max-width", l).apply(new d(`Text Trimming ${m ? "Enabled" : "Disabled"}`));
41
42
  }
42
43
  _getTextTrimming() {
43
44
  return `
44
45
  <div class="display-flex align-items-center justify-content-between">
45
46
  <${s.LABEL}
46
- ${d.LABEL.text}="${this.api.translate("Text Trimming")}"
47
+ ${p.LABEL.text}="${this.api.translate("Text Trimming")}"
47
48
  >
48
49
  </${s.LABEL}>
49
- ${this._GuToggle(i.TRIMMING)}
50
+ ${this._GuToggle(n.TRIMMING)}
50
51
  </div>
51
52
  `;
52
53
  }
53
54
  }
54
55
  export {
55
- g as CONTROL_BLOCK_ID,
56
- y as NameTrimmingControl
56
+ I as CONTROL_BLOCK_ID,
57
+ E as NameTrimmingControl
57
58
  };