@useinsider/guido 3.21.0 → 3.21.1-beta.18ab939

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 (33) hide show
  1. package/README.md +34 -4
  2. package/dist/components/Guido.vue.js +3 -3
  3. package/dist/components/Guido.vue2.js +118 -108
  4. package/dist/composables/useEditorOpenMetrics.js +164 -0
  5. package/dist/composables/useStripo.js +94 -82
  6. package/dist/config/compiler/htmlCompilerRules.js +1 -1
  7. package/dist/extensions/Blocks/Recommendation/block.js +209 -139
  8. package/dist/extensions/Blocks/Recommendation/controls/main/algorithm.js +18 -23
  9. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +171 -141
  10. package/dist/extensions/Blocks/Recommendation/controls/main/productLayout.js +68 -59
  11. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +249 -248
  12. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +62 -45
  13. package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +52 -31
  14. package/dist/guido.css +1 -1
  15. package/dist/library.js +12 -10
  16. package/dist/package.json.js +6 -4
  17. package/dist/public/prefetchRuntime.js +4 -0
  18. package/dist/src/composables/useEditorOpenMetrics.d.ts +27 -0
  19. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +23 -7
  20. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +6 -0
  21. package/dist/src/extensions/Blocks/Recommendation/controls/main/productLayout.d.ts +5 -2
  22. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +6 -0
  23. package/dist/src/extensions/Blocks/Recommendation/utils/nodeConfigWriter.d.ts +4 -0
  24. package/dist/src/extensions/Blocks/Recommendation/utils/strategyCommit.d.ts +11 -0
  25. package/dist/src/library.d.ts +1 -0
  26. package/dist/src/public/prefetchRuntime.d.ts +1 -0
  27. package/dist/src/utils/runtimePrefetch.d.ts +4 -0
  28. package/dist/src/utils/stripoRuntime.d.ts +2 -0
  29. package/dist/static/stripo-runtime-manifest.json.js +9 -0
  30. package/dist/static/styles/components/tabs.css.js +5 -0
  31. package/dist/utils/runtimePrefetch.js +26 -0
  32. package/dist/utils/stripoRuntime.js +9 -0
  33. package/package.json +7 -2
@@ -1,68 +1,85 @@
1
- import { ModificationDescription as g } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
- import { RECOMMENDATION_ID_ATTR as l } from "../constants/selectors.js";
3
- import { isPartnerManagedBlock as m, updateProductContentInPlace as d, regenerateProductRowsWithStyles as C } from "../controls/main/utils.js";
1
+ import { ModificationDescription as a } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
+ import { RECOMMENDATION_ID_ATTR as m } from "../constants/selectors.js";
3
+ import { isPartnerManagedBlock as y, updateProductContentInPlace as I, regenerateProductRowsWithStyles as N } from "../controls/main/utils.js";
4
4
  import { RecommendationConfigService as c } from "../services/configService.js";
5
- import { useRecommendationExtensionStore as y } from "../store/recommendation.js";
5
+ import { useRecommendationExtensionStore as O } from "../store/recommendation.js";
6
6
  let r = null;
7
- function M(n) {
8
- r = n;
7
+ function $(t) {
8
+ r = t;
9
9
  }
10
- function a(n) {
11
- const e = r == null ? void 0 : r.getDocumentRootHtmlNode();
12
- return !e || !("querySelector" in e) ? null : e.querySelector(`[${l}="${n}"]`) ?? null;
10
+ function C(t) {
11
+ const n = r == null ? void 0 : r.getDocumentRootHtmlNode();
12
+ return !n || !("querySelector" in n) ? null : n.querySelector(`[${m}="${t}"]`) ?? null;
13
13
  }
14
- function N(n, e) {
15
- const o = c.getConfig(n);
16
- return Object.keys(e).some((t) => JSON.stringify(o[t]) !== JSON.stringify(e[t]));
14
+ function D(t, n) {
15
+ const o = c.getConfig(t);
16
+ return Object.keys(n).some((e) => JSON.stringify(o[e]) !== JSON.stringify(n[e]));
17
17
  }
18
- function S(n, e) {
19
- const o = c.getConfig(n);
20
- return ["filters", "strategy", "strategyId", "size"].some((t) => t in e && JSON.stringify(o[t]) !== JSON.stringify(e[t]));
18
+ function R(t, n) {
19
+ const o = c.getConfig(t);
20
+ return ["filters", "strategy", "strategyId", "size", "productIds"].some((e) => e in n && JSON.stringify(o[e]) !== JSON.stringify(n[e]));
21
21
  }
22
- function P(n, e, o) {
23
- const t = a(n);
24
- return !r || !t ? !1 : (S(t, e) && c.updateConfig(r, t, e, o), !0);
22
+ const p = "Updated product IDs";
23
+ function S(t, n) {
24
+ if (!("productIds" in n))
25
+ return !1;
26
+ const o = c.getConfig(t);
27
+ return JSON.stringify(o.productIds) !== JSON.stringify(n.productIds);
28
+ }
29
+ function h(t, n, o) {
30
+ return S(t, n) ? p : o;
31
+ }
32
+ function k(t, n, o) {
33
+ const e = C(t);
34
+ if (!r || !e)
35
+ return !1;
36
+ if (R(e, n)) {
37
+ const i = h(e, n, o);
38
+ c.updateConfig(r, e, n, i);
39
+ }
40
+ return !0;
25
41
  }
26
- function p(n, e) {
27
- const o = y(), t = o.currentRecommendationId;
28
- if (t === n || !o.blockStates[n]) {
29
- e();
42
+ function P(t, n) {
43
+ const o = O(), e = o.currentRecommendationId;
44
+ if (e === t || !o.blockStates[t]) {
45
+ n();
30
46
  return;
31
47
  }
32
- o.setCurrentBlock(n);
48
+ o.setCurrentBlock(t);
33
49
  try {
34
- e();
50
+ n();
35
51
  } finally {
36
- o.$patch({ currentRecommendationId: t });
52
+ o.$patch({ currentRecommendationId: e });
37
53
  }
38
54
  }
39
- function I(n) {
40
- const e = r == null ? void 0 : r.getDocumentRootHtmlNode();
41
- return !e || !("querySelectorAll" in e) ? [] : e.querySelectorAll(`[${l}="${n}"]`).map((o) => c.getConfig(o));
55
+ function q(t) {
56
+ const n = r == null ? void 0 : r.getDocumentRootHtmlNode();
57
+ return !n || !("querySelectorAll" in n) ? [] : n.querySelectorAll(`[${m}="${t}"]`).map((o) => c.getConfig(o));
42
58
  }
43
- function $(n, e, o, t) {
44
- const i = a(n);
59
+ function w(t, n, o, e) {
60
+ const i = C(t);
45
61
  if (!r || !i)
46
62
  return !1;
47
- const f = r.getDocumentModifier(), s = N(i, e);
48
- if (c.stageConfig(f, i, e), m(i))
49
- return s && f.apply(new g(t)), !0;
63
+ const f = r.getDocumentModifier(), d = D(i, n), g = S(i, n), s = g ? p : e, l = { currentNode: i, documentModifier: f, products: o, ...g ? { description: s } : {} };
64
+ if (c.stageConfig(f, i, n), y(i))
65
+ return d && f.apply(new a(s)), !0;
50
66
  let u = !1;
51
- return p(n, () => {
52
- d({
53
- currentNode: i,
54
- documentModifier: f,
55
- products: o,
67
+ return P(t, () => {
68
+ I({
69
+ ...l,
56
70
  onApplied: () => {
57
71
  u = !0;
58
72
  }
59
- }) || (u = C({ currentNode: i, documentModifier: f, products: o }));
60
- }), !u && s && f.apply(new g(t)), !0;
73
+ }) || (u = N(l));
74
+ }), !u && d && f.apply(new a(s)), !0;
61
75
  }
62
76
  export {
63
- $ as commitBlockChangeOutsidePanel,
64
- S as hasEditedConfigChange,
65
- I as readBlockNodeConfigs,
66
- M as registerNodeConfigWriter,
67
- P as writeBlockConfigOutsidePanel
77
+ p as PRODUCT_IDS_DESCRIPTION,
78
+ w as commitBlockChangeOutsidePanel,
79
+ R as hasEditedConfigChange,
80
+ S as isProductIdsChange,
81
+ h as pickConfigDescription,
82
+ q as readBlockNodeConfigs,
83
+ $ as registerNodeConfigWriter,
84
+ k as writeBlockConfigOutsidePanel
68
85
  };
@@ -1,43 +1,64 @@
1
- import { useRecommendationExtensionStore as g } from "../store/recommendation.js";
2
- import { refreshBlockOutsidePanel as y } from "./blockRefresh.js";
3
- import { toBlockUrlConfig as a } from "./blockUrlConfig.js";
4
- import { commitBlockChangeOutsidePanel as l, readBlockNodeConfigs as S } from "./nodeConfigWriter.js";
5
- function d(e, t) {
6
- const r = JSON.stringify(a(t));
7
- return S(e).find((o) => JSON.stringify(a(o)) !== r) ?? t;
1
+ import { useRecommendationExtensionStore as f } from "../store/recommendation.js";
2
+ import { refreshBlockOutsidePanel as l } from "./blockRefresh.js";
3
+ import { toBlockUrlConfig as c } from "./blockUrlConfig.js";
4
+ import { readBlockNodeConfigs as m, commitBlockChangeOutsidePanel as d } from "./nodeConfigWriter.js";
5
+ function u(n, t) {
6
+ const r = JSON.stringify(c(t));
7
+ return m(n).find((s) => JSON.stringify(c(s)) !== r) ?? t;
8
8
  }
9
- async function p(e, t, r) {
10
- const o = g(), s = [e, t];
11
- (/* @__PURE__ */ new Map([[e, d(e, r)], [t, r]])).forEach((n, i) => {
12
- var m;
13
- (!!n.strategyId || i === t) && ((m = o.blockStates[i]) == null ? void 0 : m.recommendationConfigs.strategyId) !== n.strategyId && o.seedBlockUrlConfig(i, a(n));
14
- }), o.resetArrivedBlock(t), await Promise.all(s.map(async (n) => {
15
- if (!await o.refreshStrategyBlock(n))
9
+ async function y(n, t, r = () => !0) {
10
+ const s = f();
11
+ await Promise.all(n.map(async (e) => {
12
+ if (!await s.refreshStrategyBlock(e))
16
13
  return;
17
- const { recommendationConfigs: i, recommendationProducts: f } = o.blockStates[n];
18
- l(
19
- n,
20
- { size: i.size },
21
- f,
22
- "Refresh duplicated recommendation strategy"
14
+ const { recommendationConfigs: a, recommendationProducts: o } = s.blockStates[e];
15
+ r(e, a.size) && d(
16
+ e,
17
+ { size: a.size },
18
+ o,
19
+ t
23
20
  );
24
21
  }));
25
22
  }
26
- async function k(e, t) {
27
- if (!g().blockStates[e])
23
+ async function w(n, t, r) {
24
+ const s = f(), e = [n, t];
25
+ (/* @__PURE__ */ new Map([[n, u(n, r)], [t, r]])).forEach((o, i) => {
26
+ var g;
27
+ (!!o.strategyId || i === t) && ((g = s.blockStates[i]) == null ? void 0 : g.recommendationConfigs.strategyId) !== o.strategyId && s.seedBlockUrlConfig(i, c(o));
28
+ }), s.resetArrivedBlock(t), await y(e, "Refresh duplicated recommendation strategy");
29
+ }
30
+ async function k(n) {
31
+ const t = f(), r = n.filter(({ config: e }) => !!e.strategyId);
32
+ if (!r.length)
33
+ return;
34
+ r.forEach(({ id: e, config: a }) => t.seedBlockUrlConfig(e, c(a))), t.invalidateStrategies();
35
+ const s = new Map(r.map(({ id: e, config: a }) => [e, a]));
36
+ await y(
37
+ r.map(({ id: e }) => e),
38
+ "Refresh recommendation strategy",
39
+ (e, a) => {
40
+ const o = s.get(e);
41
+ return a !== (o == null ? void 0 : o.size) && m(e).some((i) => i.strategyId === (o == null ? void 0 : o.strategyId));
42
+ }
43
+ );
44
+ }
45
+ async function O(n, t) {
46
+ if (!f().blockStates[n])
28
47
  return !1;
29
- const r = await y(e, {
30
- pickUpdates: ({ strategyId: o, strategy: s, size: c, nodeConfigVersion: n }) => ({
31
- strategyId: o,
32
- strategy: s,
33
- size: c,
34
- configVersion: n
48
+ const r = await l(n, {
49
+ pickUpdates: ({ strategyId: s, strategy: e, size: a, nodeConfigVersion: o }) => ({
50
+ strategyId: s,
51
+ strategy: e,
52
+ size: a,
53
+ configVersion: o
35
54
  }),
36
55
  description: t
37
56
  });
38
- return r || console.error("[recommendation] strategy change did not reach a node", { blockId: e }), r;
57
+ return r || console.error("[recommendation] strategy change did not reach a node", { blockId: n }), r;
39
58
  }
40
59
  export {
41
- k as commitStrategyChange,
42
- p as refreshDuplicatedStrategyBlocks
60
+ O as commitStrategyChange,
61
+ k as refreshArrivedStrategyBlocks,
62
+ w as refreshDuplicatedStrategyBlocks,
63
+ u as resolveSourceConfig
43
64
  };
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- @charset "UTF-8";.auth-error-modal[data-v-b4d7ae51]{position:relative;z-index:145}.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-b8f24f34] .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-baf7a5dd]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.validation-error-list[data-v-e48cebe9]{gap:16px}.validation-error-row[data-v-e48cebe9]{gap:8px;padding:24px;border:1px solid #E1E1E1;border-radius:8px}.validation-error-row__icon[data-v-e48cebe9]{flex-shrink:0;font-size:24px;line-height:0}.validation-error-row__text[data-v-e48cebe9]{font-size:13px;line-height:16px;color:#292929;word-break:break-word}.guido-editor__wrapper[data-v-c5146fc5]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-c5146fc5]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-c5146fc5]{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-19d8cb42] .vueperslides__bullets,[data-v-ec2027ff] .vueperslides__bullets,[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}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-skeleton{width:100%!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}.legacy-strategy-updated-modal[data-v-da2225a1]{position:relative;z-index:145}
1
+ @charset "UTF-8";.auth-error-modal[data-v-b4d7ae51]{position:relative;z-index:145}.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-b8f24f34] .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-baf7a5dd]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.validation-error-list[data-v-e48cebe9]{gap:16px}.validation-error-row[data-v-e48cebe9]{gap:8px;padding:24px;border:1px solid #E1E1E1;border-radius:8px}.validation-error-row__icon[data-v-e48cebe9]{flex-shrink:0;font-size:24px;line-height:0}.validation-error-row__text[data-v-e48cebe9]{font-size:13px;line-height:16px;color:#292929;word-break:break-word}.guido-editor__wrapper[data-v-1a3ddd48]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-1a3ddd48]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-1a3ddd48]{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-19d8cb42] .vueperslides__bullets,[data-v-ec2027ff] .vueperslides__bullets,[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}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-skeleton{width:100%!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}.legacy-strategy-updated-modal[data-v-da2225a1]{position:relative;z-index:145}
package/dist/library.js CHANGED
@@ -1,20 +1,22 @@
1
1
  import { default as a } from "./components/Guido.vue.js";
2
- import { MessageType as t, ProductType as d } from "./@types/config/schemas.js";
2
+ import { MessageType as t, ProductType as f } from "./@types/config/schemas.js";
3
3
  import "./@types/config/defaults.js";
4
- import { getValidationErrors as s, isValidConfig as p, parseConfig as g, parseConfigSafe as m, validateConfig as n } from "./@types/config/validator.js";
5
- import { assignTrackingIds as u, readTrackFloor as x, readTrackSeq as T } from "./utils/linkTrackingIds.js";
4
+ import { getValidationErrors as p, isValidConfig as s, parseConfig as m, parseConfigSafe as g, validateConfig as n } from "./@types/config/validator.js";
5
+ import { assignTrackingIds as l, readTrackFloor as x, readTrackSeq as c } from "./utils/linkTrackingIds.js";
6
6
  import { useGuidoEmailEditorStore as C } from "./stores/guido-email-editor.js";
7
+ import { prefetchGuidoRuntime as E } from "./utils/runtimePrefetch.js";
7
8
  export {
8
9
  a as Guido,
9
10
  t as MessageType,
10
- d as ProductType,
11
- u as assignTrackingIds,
12
- s as getValidationErrors,
13
- p as isValidConfig,
14
- g as parseConfig,
15
- m as parseConfigSafe,
11
+ f as ProductType,
12
+ l as assignTrackingIds,
13
+ p as getValidationErrors,
14
+ s as isValidConfig,
15
+ m as parseConfig,
16
+ g as parseConfigSafe,
17
+ E as prefetchGuidoRuntime,
16
18
  x as readTrackFloor,
17
- T as readTrackSeq,
19
+ c as readTrackSeq,
18
20
  C as useGuidoEmailEditorStore,
19
21
  n as validateConfig
20
22
  };
@@ -1,7 +1,9 @@
1
- const o = { stripo: { version: "2.79.0" } }, s = {
2
- guido: o
1
+ const o = "3.21.1-beta.18ab939", s = { stripo: { version: "2.81.1" } }, t = {
2
+ version: o,
3
+ guido: s
3
4
  };
4
5
  export {
5
- s as default,
6
- o as guido
6
+ t as default,
7
+ s as guido,
8
+ o as version
7
9
  };
@@ -0,0 +1,4 @@
1
+ import { prefetchGuidoRuntime as r } from "../utils/runtimePrefetch.js";
2
+ export {
3
+ r as prefetchGuidoRuntime
4
+ };
@@ -0,0 +1,27 @@
1
+ export type TimedOpenPhase = 'migration' | 'default_template' | 'timer_clone';
2
+ export type OpenPhase = 'setup' | 'host_ready' | `${TimedOpenPhase}_start` | `${TimedOpenPhase}_end` | 'plugin_start' | 'script_ready' | 'fonts_sync_ready' | 'blocks_config_ready' | 'init_editor' | 'token_start' | 'token_end' | 'ready';
3
+ export type OpenOutcome = 'ready' | 'error' | 'abandoned';
4
+ export interface OpenContext {
5
+ partnerName: string;
6
+ productType: number;
7
+ templateId: string;
8
+ variationId: string;
9
+ }
10
+ export interface OpenTemplate {
11
+ html: string;
12
+ css: string;
13
+ forceRecreate: boolean;
14
+ }
15
+ export interface EditorOpenMetrics {
16
+ mark: (phase: OpenPhase) => void;
17
+ timed: <T>(phase: TimedOpenPhase, task: () => Promise<T>) => Promise<T>;
18
+ setContext: (context: OpenContext) => void;
19
+ setTemplate: (template: OpenTemplate) => void;
20
+ setScriptPreloaded: (preloaded: boolean) => void;
21
+ markReady: () => void;
22
+ markFailed: () => void;
23
+ dispose: () => void;
24
+ }
25
+ export declare const startEditorOpenMetrics: () => EditorOpenMetrics;
26
+ /** Binds to the session open at call time, so a remounted editor never writes into its replacement's session. */
27
+ export declare const useEditorOpenMetrics: () => EditorOpenMetrics;
@@ -19,6 +19,9 @@ export declare class RecommendationBlock extends Block {
19
19
  private _resetSourceIds;
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
+ private _arrivedBlocks;
23
+ /** Strategy each in-flight arrival or duplicate refresh is fetching, by block id, so a second one does not race it. */
24
+ private _refreshClaims;
22
25
  constructor();
23
26
  getId(): string;
24
27
  getIcon(): string;
@@ -44,6 +47,8 @@ export declare class RecommendationBlock extends Block {
44
47
  * @param node - The newly created block node
45
48
  */
46
49
  onCreated(node: ImmutableHtmlNode): void;
50
+ /** Refreshes every block of an opened template: Stripo restores a stored document without `onCreated`. */
51
+ onDocumentInit(): void;
47
52
  /**
48
53
  * Called when the document changes or template is loaded
49
54
  *
@@ -85,15 +90,26 @@ export declare class RecommendationBlock extends Block {
85
90
  * the renamed one depending on where the module was dropped (SD-149916).
86
91
  */
87
92
  private _scheduleArrivalReset;
93
+ /**
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.
96
+ */
97
+ private _queueArrivalRefresh;
98
+ private _refreshArrivedBlocks;
99
+ /**
100
+ * A new document reports each block to onCreated and onDocumentInit, not always in one batch, so a
101
+ * claimed block refreshes again only once the document shows it under another strategy (a restored version).
102
+ */
103
+ private _canClaimRefresh;
104
+ private _releaseRefreshClaim;
88
105
  /**
89
106
  * Heals a duplicate that slipped past the create-time `_detectDuplicate`
90
107
  * scan (or that was persisted by an older template before SD-142352).
91
108
  * When two blocks share a `recommendation-id`, the first occurrence in DOM
92
109
  * order is treated as the source and any later sibling is reassigned a
93
- * fresh id. The store entry and active-block focus are intentionally not
94
- * touched here: each block's persisted `esd-ext-config` carries its own
95
- * truth and the regular save-time hydration (`hydrateRecommendationStore`)
96
- * will seed the new id from that. Skipping `setCurrentBlock` avoids
110
+ * fresh id and queued for the arrival refresh, which seeds the new id's
111
+ * store entry from its persisted `esd-ext-config`. The source's store
112
+ * entry is not cloned and focus is not moved. Skipping `setCurrentBlock` avoids
97
113
  * yanking the user's current selection mid-edit when the heal fires from
98
114
  * `onDocumentChanged`.
99
115
  */
@@ -109,9 +125,9 @@ export declare class RecommendationBlock extends Block {
109
125
  *
110
126
  * Used by `_handleDuplicate` at create-time (which additionally clones the
111
127
  * store entry and focuses the new block) and by `_healLingeringDuplicate`
112
- * at document-change time (which intentionally skips store/focus side
113
- * effects so older bug-affected templates can self-repair without
114
- * disturbing the user's current selection).
128
+ * at document-change time (which skips the clone and focus change so older
129
+ * bug-affected templates can self-repair without disturbing the user's
130
+ * current selection, and queues the arrival refresh for the new id).
115
131
  */
116
132
  private _reassignDuplicateId;
117
133
  /**
@@ -78,6 +78,8 @@ export declare class RecommendationBlockControl extends CommonControl {
78
78
  /** Whether the deferred write would move the node's strategyId — see the caller (SD-149916). */
79
79
  private _isPendingStrategyIdChange;
80
80
  private _capturePendingNodeConfigWrite;
81
+ /** The pending write only when it belongs to the node this panel draws: a duplicate focuses the copy. */
82
+ private _pendingWriteForNode;
81
83
  private _getNodeConfigUpdates;
82
84
  /**
83
85
  * Accumulates the pending write into `documentModifier` without applying, so the
@@ -103,6 +105,9 @@ export declare class RecommendationBlockControl extends CommonControl {
103
105
  * the intervening re-render staled, and saveConfig swallows that failure.
104
106
  */
105
107
  private _flushPendingNodeConfig;
108
+ private _cardsPredatePendingWrite;
109
+ /** The Product Ids label when the pending write moves the node's ids; the caller's default otherwise. */
110
+ private _pendingDescription;
106
111
  private _syncNodeConfigToStore;
107
112
  /**
108
113
  * Fetches initial data for a block in three phases:
@@ -156,6 +161,7 @@ export declare class RecommendationBlockControl extends CommonControl {
156
161
  private _debouncedRegenerateWithProducts;
157
162
  /** Draws the current block's products into this panel's node. */
158
163
  private _regenerateWithProducts;
164
+ private _consumePendingNodeConfig;
159
165
  /**
160
166
  * Listen to store changes that require product refresh or regeneration.
161
167
  *
@@ -26,6 +26,8 @@ export declare const PRODUCT_LAYOUT_CONTROL_ID = "recommendation-product-layout-
26
26
  export declare class ProductLayoutControl extends CommonControl {
27
27
  private store;
28
28
  private storeUnsubscription;
29
+ private pendingMobileLayoutEnabled;
30
+ private pendingMobileLayoutBlockId;
29
31
  getId(): string;
30
32
  getTemplate(): string;
31
33
  onRender(): void;
@@ -37,7 +39,8 @@ export declare class ProductLayoutControl extends CommonControl {
37
39
  */
38
40
  _syncDisabledState(): void;
39
41
  onDestroy(): void;
40
- _setFormValues(): void;
42
+ _getBlockId(node: ImmutableHtmlNode | null | undefined): string | null;
43
+ _setFormValues(config?: import("../../types").RecommendationNodeConfig): void;
41
44
  /**
42
45
  * Returns true when the editor preview is in mobile mode.
43
46
  */
@@ -53,7 +56,7 @@ export declare class ProductLayoutControl extends CommonControl {
53
56
  * Only one row is visible at a time. This avoids setUIEAttribute on hidden
54
57
  * elements, which Stripo does not apply reliably.
55
58
  */
56
- _updateProductsInRowVisibility(): void;
59
+ _updateProductsInRowVisibility(config?: import("../../types").RecommendationNodeConfig): void;
57
60
  /**
58
61
  * Initializes the mobile layout toggle using the same pattern as shuffle.ts.
59
62
  * Sets the initial UI attribute value from the node config.
@@ -69,6 +69,8 @@ export interface RegenerateProductRowsOptions {
69
69
  layout?: Orientation;
70
70
  /** Optional: pass composition directly to avoid stale DOM reads after setAttribute */
71
71
  composition?: string[];
72
+ /** Optional: pass mobileLayoutEnabled directly to avoid stale node config reads after apply */
73
+ mobileLayoutEnabled?: boolean;
72
74
  }
73
75
  export declare function getMainContainerTbody(currentNode: ImmutableHtmlNode): ImmutableHtmlNode | null;
74
76
  /**
@@ -88,6 +90,8 @@ export interface RegenerateWithStylesOptions extends Omit<RegenerateProductRowsO
88
90
  products?: RecommendationProduct[];
89
91
  /** Optional: pass layout directly to avoid stale DOM reads after setAttribute */
90
92
  layout?: Orientation;
93
+ /** Undo label for the apply; the caller sets it when a config change rides in the same batch */
94
+ description?: string;
91
95
  }
92
96
  /**
93
97
  * Regenerates product rows while preserving user-applied styles, in a SINGLE commit.
@@ -156,6 +160,8 @@ export interface UpdateProductContentInPlaceOptions {
156
160
  * leaves anything a caller staged into the same batch unwritten unless it applies itself.
157
161
  */
158
162
  onApplied?: () => void;
163
+ /** Undo label for the apply; the caller sets it when a config change rides in the same batch */
164
+ description?: string;
159
165
  }
160
166
  /**
161
167
  * Updates product content in-place without regenerating HTML structure.
@@ -14,6 +14,10 @@ interface ConfigWriterApi {
14
14
  */
15
15
  export declare function registerNodeConfigWriter(api: ConfigWriterApi): void;
16
16
  export declare function hasEditedConfigChange(node: ImmutableHtmlNode, updates: PartialNodeConfig): boolean;
17
+ export declare const PRODUCT_IDS_DESCRIPTION = "Updated product IDs";
18
+ /** A deferred Product Ids edit keeps its own undo label wherever the write finally lands. */
19
+ export declare function isProductIdsChange(node: ImmutableHtmlNode, updates: PartialNodeConfig): boolean;
20
+ export declare function pickConfigDescription(node: ImmutableHtmlNode, updates: PartialNodeConfig, fallback: string): string;
17
21
  /**
18
22
  * Writes a config change to the block's node on its own, found by id — never through a
19
23
  * panel-held node, which may already belong to the block the user switched to.
@@ -1,10 +1,21 @@
1
1
  import type { RecommendationNodeConfig } from '../types/nodeConfig';
2
+ /** A saved module keeps the id it was saved with, so it can arrive sharing the id of an unrelated block. */
3
+ export declare function resolveSourceConfig(sourceId: number, arrived: RecommendationNodeConfig): RecommendationNodeConfig;
2
4
  /**
3
5
  * Re-reads the strategy of a duplicated block and its source and redraws both: the clone copies the
4
6
  * cards the source last drew, so a strategy edited since then only reached a block once selected (SD-153266).
5
7
  * @param config - the arriving block's persisted config; seeds either block its store entry does not match
6
8
  */
7
9
  export declare function refreshDuplicatedStrategyBlocks(sourceId: number, duplicateId: number, config: RecommendationNodeConfig): Promise<void>;
10
+ /**
11
+ * Re-reads the strategy of blocks that arrived from a saved template or module, so the panel and
12
+ * preview show a strategy edited since the design was saved without selecting the block.
13
+ * @param blocks - each block's id with its persisted config, the truth its store entry is seeded from
14
+ */
15
+ export declare function refreshArrivedStrategyBlocks(blocks: {
16
+ id: number;
17
+ config: RecommendationNodeConfig;
18
+ }[]): Promise<void>;
8
19
  /**
9
20
  * Writes a strategy change and its products straight to the document, without the settings panel.
10
21
  *
@@ -4,5 +4,6 @@ export { validateConfig, parseConfig, parseConfigSafe, isValidConfig, getValidat
4
4
  export { assignTrackingIds, readTrackFloor, readTrackSeq } from './public/trackingIds';
5
5
  export { useGuidoEmailEditorStore } from './public/editorState';
6
6
  export type { GuidoEmailEditorState } from './public/editorState';
7
+ export { prefetchGuidoRuntime } from './public/prefetchRuntime';
7
8
  export type { StripoEventType } from './@types/events';
8
9
  export type { PositionData, DynamicContentEvent, MergeTagClickEvent, MergeTag, BaseDynamicContent, DynamicContentNode, DynamicContentList, TooltipOptions, TextValueObject, L10n, } from './@types/generic';
@@ -0,0 +1 @@
1
+ export { prefetchGuidoRuntime } from '../utils/runtimePrefetch';
@@ -0,0 +1,4 @@
1
+ export type RuntimePrefetchState = 'none' | 'pending' | 'done';
2
+ export declare const RUNTIME_PREFETCH_ATTRIBUTE = "data-guido-prefetch";
3
+ export declare const prefetchGuidoRuntime: () => void;
4
+ export declare const readRuntimePrefetchState: () => RuntimePrefetchState;
@@ -0,0 +1,2 @@
1
+ /** Null when package.json does not pin `guido.stripo.version`. */
2
+ export declare const getStripoRuntimeBaseUrl: () => string | null;
@@ -0,0 +1,9 @@
1
+ const s = "2.79.0", n = ["UIEditor.js", "zone.js", "styles-BWH3PMR4.css", "polyfills-FF3RLU5F.js", "main-MFU2R4FE.js", "chunk-2PIEA5YN.js", "chunk-5FVAINMG.js", "chunk-67OKDPNA.js", "chunk-BEE4NTMB.js", "chunk-FXMA33WF.js", "chunk-HEM7M3GC.js", "chunk-IP346EOD.js", "chunk-J3Q2HMUE.js", "chunk-JER72PP5.js", "chunk-LXRTAID3.js", "chunk-MV5VZJ34.js", "chunk-RTXKBDZV.js", "chunk-UQMM7Q74.js", "chunk-WCDYHSTN.js", "assets/css/uiEditor.css", "assets/i18n/en.json", "assets/icons/ui-editor-icons.sprite.svg", "assets/icons/ui-editor-icons.map.json", "assets/imageeditor/scripts.min.js", "assets/imageeditor/assets/icons/merged.svg"], c = {
2
+ version: s,
3
+ files: n
4
+ };
5
+ export {
6
+ c as default,
7
+ n as files,
8
+ s as version
9
+ };
@@ -10,6 +10,11 @@ ue-tabs-header .tabs-header {
10
10
  margin: 16px 16px 0;
11
11
  }
12
12
 
13
+ /* Stripo 2.81.0 sets margin: 15px 20px here; keep the 16px panel inset and its gap above the new divider. */
14
+ ue-control-panel .control-panel-card .control-panel-tabs .tabs-header {
15
+ margin: 16px 16px 15px;
16
+ }
17
+
13
18
  ue-tabs-header .tabs-header button {
14
19
  background-color: var(--guido-color-gray-0);
15
20
  outline: none;
@@ -0,0 +1,26 @@
1
+ import s from "../static/stripo-runtime-manifest.json.js";
2
+ import { getStripoRuntimeBaseUrl as c } from "./stripoRuntime.js";
3
+ const r = "data-guido-prefetch", d = "pending", o = "settled", i = `link[${r}]`, u = ["slow-2g", "2g"], l = /\.(?:js|json)$/, a = () => document.getElementById("UiEditorScript") !== null || window.UIEditor !== void 0, E = () => {
4
+ const { connection: e } = navigator;
5
+ return (e == null ? void 0 : e.saveData) === !0 || u.includes((e == null ? void 0 : e.effectiveType) ?? "");
6
+ }, m = (e) => {
7
+ const t = document.createElement("link"), n = () => t.setAttribute(r, o);
8
+ t.rel = "prefetch", t.href = e, l.test(e) && t.setAttribute("crossorigin", "anonymous"), t.setAttribute(r, d), t.addEventListener("load", n, { once: !0 }), t.addEventListener("error", n, { once: !0 }), document.head.appendChild(t);
9
+ }, T = () => {
10
+ try {
11
+ const e = c(), t = document.querySelector(i) !== null;
12
+ if (!e || t || a() || E())
13
+ return;
14
+ s.files.forEach((n) => m(`${e}${n}`));
15
+ } catch (e) {
16
+ console.debug("guido: runtime prefetch skipped", e);
17
+ }
18
+ }, g = () => {
19
+ const e = Array.from(document.querySelectorAll(i));
20
+ return e.length ? e.every((t) => t.getAttribute(r) === o) ? "done" : "pending" : "none";
21
+ };
22
+ export {
23
+ r as RUNTIME_PREFETCH_ATTRIBUTE,
24
+ T as prefetchGuidoRuntime,
25
+ g as readRuntimePrefetchState
26
+ };
@@ -0,0 +1,9 @@
1
+ import r from "../package.json.js";
2
+ const e = "https://email-static.useinsider.com/guido/", n = () => {
3
+ var s;
4
+ const t = r.guido, o = (s = t == null ? void 0 : t.stripo) == null ? void 0 : s.version;
5
+ return o ? `${e}${o}/` : null;
6
+ };
7
+ export {
8
+ n as getStripoRuntimeBaseUrl
9
+ };