@useinsider/guido 3.9.0-beta.ec06cf4 → 3.9.0-beta.f844081

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,17 +1,24 @@
1
1
  import { ModificationDescription as b } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
2
- import { DefaultConfigValues as i, SETTINGS_ENUMS as n, ItemInCartOptions as g } from "../enums/settingsEnums.js";
2
+ import { ItemInCartOptions as p, DefaultConfigValues as i, SETTINGS_ENUMS as c } from "../enums/settingsEnums.js";
3
3
  function _() {
4
4
  return String(Date.now() + Math.floor(Math.random() * 1e3));
5
5
  }
6
- const E = (r) => r.replace(/\$/g, "$$$$");
7
- function y() {
6
+ const S = (r) => r.replace(/\$/g, "$$$$");
7
+ function y(r, t) {
8
+ const e = p[t], n = e ? e.findIndex((u) => u.value === r) : -1;
9
+ if (n >= 0)
10
+ return String(n + 1);
11
+ const o = typeof r == "string" ? r.match(/\((\d+)\)/) : null;
12
+ return (o == null ? void 0 : o[1]) ?? "1";
13
+ }
14
+ function A() {
8
15
  return {
9
16
  initialized: !0,
10
17
  blockInstanceId: _(),
11
- source: n.ITEMS_TYPE.CART_ITEMS,
12
- type: n.ITEMS_TYPE.CART_ITEMS,
18
+ source: c.ITEMS_TYPE.CART_ITEMS,
19
+ type: c.ITEMS_TYPE.CART_ITEMS,
13
20
  itemsSelectValue: i.cartItemsSelectControlValue,
14
- orientation: n.ORIENTATION.VERTICAL,
21
+ orientation: c.ORIENTATION.VERTICAL,
15
22
  nameTrimming: i.productNameTrimmingControlValue === "1",
16
23
  priceHideDiscount: i.productPriceHideDiscountControlValue === "1",
17
24
  priceFormatted: i.productPriceFormattedControlValue === "1",
@@ -33,7 +40,7 @@ function y() {
33
40
  buttonVisible: i.productButtonVisible === "1"
34
41
  };
35
42
  }
36
- function p(r) {
43
+ function g(r) {
37
44
  if (!r)
38
45
  return null;
39
46
  const t = r.closest(".items-block-v2");
@@ -41,14 +48,14 @@ function p(r) {
41
48
  }
42
49
  function m(r) {
43
50
  return r ? {
44
- CartItems: n.ITEMS_TYPE.CART_ITEMS,
45
- BrowsedItems: n.ITEMS_TYPE.BROWSED_ITEMS,
46
- PurchasedItems: n.ITEMS_TYPE.PURCHASED_ITEMS,
51
+ CartItems: c.ITEMS_TYPE.CART_ITEMS,
52
+ BrowsedItems: c.ITEMS_TYPE.BROWSED_ITEMS,
53
+ PurchasedItems: c.ITEMS_TYPE.PURCHASED_ITEMS,
47
54
  // Also handle already correct formats
48
- CART_ITEMS: n.ITEMS_TYPE.CART_ITEMS,
49
- BROWSED_ITEMS: n.ITEMS_TYPE.BROWSED_ITEMS,
50
- PURCHASED_ITEMS: n.ITEMS_TYPE.PURCHASED_ITEMS
51
- }[r] || n.ITEMS_TYPE.CART_ITEMS : n.ITEMS_TYPE.CART_ITEMS;
55
+ CART_ITEMS: c.ITEMS_TYPE.CART_ITEMS,
56
+ BROWSED_ITEMS: c.ITEMS_TYPE.BROWSED_ITEMS,
57
+ PURCHASED_ITEMS: c.ITEMS_TYPE.PURCHASED_ITEMS
58
+ }[r] || c.ITEMS_TYPE.CART_ITEMS : c.ITEMS_TYPE.CART_ITEMS;
52
59
  }
53
60
  function f(r, t) {
54
61
  if (!r)
@@ -56,27 +63,27 @@ function f(r, t) {
56
63
  if (r.includes("{{"))
57
64
  return r;
58
65
  if (/^\d+$/.test(r)) {
59
- const e = parseInt(r) - 1, o = g[t];
60
- if (o && o[e])
61
- return o[e].value;
66
+ const e = parseInt(r) - 1, n = p[t];
67
+ if (n && n[e])
68
+ return n[e].value;
62
69
  }
63
70
  return i.cartItemsSelectControlValue;
64
71
  }
65
- function C(r) {
72
+ function I(r) {
66
73
  const t = r.querySelector("esd-config-block");
67
74
  if (!t)
68
75
  return null;
69
- const e = (u, s) => u == null ? s : u === "1" || u === "true", o = (u, s) => u || s, c = t.getAttribute("data-type"), a = m(c), d = t.getAttribute("data-cart_items_select_control_value"), l = f(d, a);
76
+ const e = (a, s) => a == null ? s : a === "1" || a === "true", n = (a, s) => a || s, o = t.getAttribute("data-type"), u = m(o), d = t.getAttribute("data-cart_items_select_control_value"), l = f(d, u);
70
77
  return {
71
78
  initialized: e(t.getAttribute("data-initialized"), !1),
72
- blockInstanceId: o(
79
+ blockInstanceId: n(
73
80
  t.getAttribute("data-block-instance-id"),
74
81
  _()
75
82
  ),
76
- source: a,
77
- type: a,
83
+ source: u,
84
+ type: u,
78
85
  itemsSelectValue: l,
79
- orientation: t.getAttribute("data-card_orientation_control_value") || n.ORIENTATION.VERTICAL,
86
+ orientation: t.getAttribute("data-card_orientation_control_value") || c.ORIENTATION.VERTICAL,
80
87
  nameTrimming: e(
81
88
  t.getAttribute("data-product_name_control_trim"),
82
89
  !0
@@ -93,11 +100,11 @@ function C(r) {
93
100
  t.getAttribute("data-product_price_control_single_price"),
94
101
  !1
95
102
  ),
96
- priceCurrencySymbol: o(
103
+ priceCurrencySymbol: n(
97
104
  t.getAttribute("data-product_price_control_currency_symbol"),
98
105
  i.productPriceCurrencySymbolControlValue
99
106
  ),
100
- priceCurrencyLocation: o(
107
+ priceCurrencyLocation: n(
101
108
  t.getAttribute("data-product_price_currency_location"),
102
109
  i.productPriceCurrencyLocationControlValue
103
110
  ),
@@ -106,15 +113,15 @@ function C(r) {
106
113
  t.getAttribute("data-product_quantity_control_enabled"),
107
114
  !0
108
115
  ),
109
- buttonLink: o(
116
+ buttonLink: n(
110
117
  t.getAttribute("data-product_button_link"),
111
118
  i.productButtonLinkControlValue
112
119
  ),
113
- imageLink: o(
120
+ imageLink: n(
114
121
  t.getAttribute("data-product_image_link"),
115
122
  i.productImageLinkControlValue
116
123
  ),
117
- buttonLabel: o(
124
+ buttonLabel: n(
118
125
  t.getAttribute("data-product_button_control_label"),
119
126
  "Buy"
120
127
  ),
@@ -149,7 +156,7 @@ function C(r) {
149
156
  )
150
157
  };
151
158
  }
152
- function I(r) {
159
+ function C(r) {
153
160
  if (typeof r.getAttribute != "function")
154
161
  return null;
155
162
  const t = r.getAttribute("esd-ext-config");
@@ -163,31 +170,32 @@ function I(r) {
163
170
  }
164
171
  return null;
165
172
  }
166
- function A(r) {
167
- const t = p(r);
173
+ function V(r) {
174
+ const t = g(r);
168
175
  if (!t)
169
176
  return null;
170
177
  const e = t.getNodeConfig();
171
178
  if (e && e.initialized)
172
179
  return e;
180
+ const n = C(t);
181
+ if (n)
182
+ return n;
173
183
  const o = I(t);
174
- if (o)
175
- return o;
176
- const c = C(t);
177
- return c || null;
184
+ return o || null;
178
185
  }
179
- function V(r, t, e, o) {
180
- const c = p(r);
181
- if (!c)
186
+ function M(r, t, e, n) {
187
+ const o = g(r);
188
+ if (!o)
182
189
  return;
183
- const d = { ...c.getNodeConfig() || {}, ...e }, l = o ?? t.getDocumentModifier();
184
- l.modifyHtml(c).setNodeConfig(d), o || l.apply(new b("Update Items block configuration"));
190
+ const d = { ...o.getNodeConfig() || {}, ...e }, l = n ?? t.getDocumentModifier();
191
+ l.modifyHtml(o).setNodeConfig(d), n || l.apply(new b("Update Items block configuration"));
185
192
  }
186
193
  export {
187
- E as escapeReplacement,
194
+ y as deriveItemNumber,
195
+ S as escapeReplacement,
188
196
  _ as generateBlockInstanceId,
189
- y as getDefaultItemsBlockConfig,
190
- A as getItemsBlockConfig,
191
- p as getItemsBlockContainer,
192
- V as setItemsBlockConfig
197
+ A as getDefaultItemsBlockConfig,
198
+ V as getItemsBlockConfig,
199
+ g as getItemsBlockContainer,
200
+ M as setItemsBlockConfig
193
201
  };
@@ -0,0 +1,34 @@
1
+ import { useToaster as m } from "../composables/useToaster.js";
2
+ import { useTranslations as c } from "../composables/useTranslations.js";
3
+ import { BLANK_TEMPLATE_HTML_URL as T, BLANK_TEMPLATE_CSS_URL as i } from "../enums/defaults.js";
4
+ import { ToasterTypeOptions as p } from "../enums/toaster.js";
5
+ const a = 3, f = 1e3;
6
+ let s = null;
7
+ const u = (e) => new Promise((t) => {
8
+ setTimeout(t, e);
9
+ }), n = async (e) => {
10
+ const t = await fetch(e);
11
+ if (!t.ok)
12
+ throw new Error(`Blank template request failed: ${t.status}`);
13
+ return t.text();
14
+ }, k = () => {
15
+ const { showToaster: e } = m(), t = c();
16
+ return { getBlankTemplate: async () => {
17
+ if (s)
18
+ return s;
19
+ for (let r = 1; r <= a; r++)
20
+ try {
21
+ const [o, l] = await Promise.all([
22
+ n(T),
23
+ n(i)
24
+ ]);
25
+ return s = { html: o, css: l }, s;
26
+ } catch (o) {
27
+ console.error(`Failed to fetch blank template (attempt ${r}/${a}):`, o), r < a && await u(r * f);
28
+ }
29
+ return e({ type: p.Alert, message: t("errors-pages.undefined-response") }), { html: "", css: "" };
30
+ } };
31
+ };
32
+ export {
33
+ k as useBlankTemplate
34
+ };
@@ -1,10 +1,9 @@
1
1
  import { useHttp as d } from "../composables/useHttp.js";
2
2
  import { useToaster as m } from "../composables/useToaster.js";
3
3
  import { MAX_DEFAULT_TEMPLATE_ID as y } from "../enums/defaults.js";
4
- import f from "../static/templates/empty/index.html.js";
5
- import g from "../static/templates/empty/style.css.js";
6
- const E = () => {
7
- const { get: s, post: c } = d(), { handleError: r } = m();
4
+ import { useBlankTemplate as f } from "./blankTemplate.js";
5
+ const D = () => {
6
+ const { get: s, post: u } = d(), { handleError: r } = m(), { getBlankTemplate: o } = f();
8
7
  return {
9
8
  getToken: async () => {
10
9
  try {
@@ -26,18 +25,14 @@ const E = () => {
26
25
  }
27
26
  },
28
27
  getDefaultTemplate: async () => {
29
- const t = {
30
- html: f,
31
- css: g
32
- };
33
28
  try {
34
- const e = new URLSearchParams(window.location.search), u = e.get("default-template"), p = e.get("master"), a = u ? parseInt(u) : 0, i = a >= 1 && a <= y ? a : 0;
35
- if (!i && !p)
36
- return t;
37
- const l = `/stripo/default-template/${i}`, { data: n } = await s(l), o = typeof n == "string" ? JSON.parse(n) : n;
38
- return !o || typeof o != "object" || !("html" in o) || !("css" in o) ? t : o;
39
- } catch (e) {
40
- return r(e, "Failed to fetch default template"), t;
29
+ const t = new URLSearchParams(window.location.search), e = t.get("default-template"), l = t.get("master"), n = e ? parseInt(e) : 0, i = n >= 1 && n <= y ? n : 0;
30
+ if (!i && !l)
31
+ return await o();
32
+ const p = `/stripo/default-template/${i}`, { data: c } = await s(p), a = typeof c == "string" ? JSON.parse(c) : c;
33
+ return !a || typeof a != "object" || !("html" in a) || !("css" in a) ? await o() : a;
34
+ } catch (t) {
35
+ return r(t, "Failed to fetch default template"), o();
41
36
  }
42
37
  },
43
38
  getSyncModulesStatus: async () => {
@@ -50,7 +45,7 @@ const E = () => {
50
45
  },
51
46
  updateSyncModule: async (t) => {
52
47
  try {
53
- return await c(`/stripo/stripo-modules/${t.moduleId}/update`), !0;
48
+ return await u(`/stripo/stripo-modules/${t.moduleId}/update`), !0;
54
49
  } catch (e) {
55
50
  return r(e, "Failed to update sync module"), !1;
56
51
  }
@@ -71,7 +66,7 @@ const E = () => {
71
66
  if (t.length === 0)
72
67
  return !0;
73
68
  try {
74
- return await c("/stripo/stripo-modules/set-unsubscription-preference-pages", t), !0;
69
+ return await u("/stripo/stripo-modules/set-unsubscription-preference-pages", t), !0;
75
70
  } catch (e) {
76
71
  return r(e, "Failed to set unsubscription preference pages"), !1;
77
72
  }
@@ -79,5 +74,5 @@ const E = () => {
79
74
  };
80
75
  };
81
76
  export {
82
- E as useStripoApi
77
+ D as useStripoApi
83
78
  };
@@ -8,6 +8,9 @@ export declare const TemplateTypes: {
8
8
  };
9
9
  export declare const EditorType: number;
10
10
  export declare const MAX_DEFAULT_TEMPLATE_ID = 13;
11
+ export declare const EMAIL_STATIC_BASE_URL = "https://email-static.useinsider.com";
12
+ export declare const BLANK_TEMPLATE_HTML_URL = "https://email-static.useinsider.com/templates/campaign/default.html";
13
+ export declare const BLANK_TEMPLATE_CSS_URL = "https://email-static.useinsider.com/templates/campaign/default.css";
11
14
  export declare const ProductIds: Record<string, number>;
12
15
  export declare const ModuleFolderDefaults: {
13
16
  readonly SAVED_MODULES: "savedModules";
@@ -33,4 +33,13 @@ export declare class ItemsBlock extends Block {
33
33
  * Guarded to the nodeConfig-empty case so it runs once and never loops.
34
34
  */
35
35
  onDocumentChanged(node: ImmutableHtmlNode): void;
36
+ /**
37
+ * Bakes the compiler-read DOM attributes (`data-type`, `data-number`) onto the
38
+ * `.ins-product-td` container from the recovered config. Required for saved modules:
39
+ * `migrate()` (which backfills these) only runs at template load — never when a module
40
+ * is dropped into a live editor — so this is the one place the namespace + index get
41
+ * restored before export. The name `<a>` carries no data-type/data-number of its own and
42
+ * relies on this td-level fallback in pairProductVariables.
43
+ */
44
+ private _stampProductTdDomAttributes;
36
45
  }
@@ -3,6 +3,13 @@ declare const migrationTemplate = "ADD YOUR MIGRATION HERE";
3
3
  type ProductType = 'CART_ITEMS' | 'BROWSED_ITEMS' | 'PURCHASED_ITEMS';
4
4
  type OrientationType = 'vertical' | 'horizontal';
5
5
  type PriceOrientationType = 'vertical' | 'horizontal';
6
+ /**
7
+ * Wraps a bare migrate-block `<td>` in a `<tr>` so it forms a valid table row.
8
+ * Stripo renders its `BlockType.*` tags as full rows, so both the migrate template
9
+ * (here) and the orientation-change rebuild (settingsControl._reOrderTemplate) must
10
+ * emit `<tr><td>` — otherwise the code editor flags the bare cell as invalid.
11
+ */
12
+ export declare const wrapInTableRow: (html: string) => string;
6
13
  type TemplateParameters = {
7
14
  orientation: OrientationType;
8
15
  itemsType: ProductType;
@@ -40,6 +40,18 @@ export declare function generateBlockInstanceId(): string;
40
40
  * Prevents currency symbols like "$", "R$", "HK$" from being interpreted as special replacement patterns.
41
41
  */
42
42
  export declare const escapeReplacement: (str: string) => string;
43
+ /**
44
+ * Derives a card's 1-based product index from its `itemsSelectValue`.
45
+ * Prefers the position within ItemInCartOptions for the type; falls back to the
46
+ * `(N)` token in the value (e.g. "{{Browsed Item (3) Url}}" -> "3"); defaults to "1".
47
+ *
48
+ * Single source of truth so block.ts, settingsControl and template.ts stay in sync —
49
+ * the number feeds `data-number`, which pairProductVariables reads to index merge tags.
50
+ *
51
+ * `itemsSelectValue` is typed loosely because callers pass it straight from parsed
52
+ * configs where the field can be absent — the runtime guard below is load-bearing.
53
+ */
54
+ export declare function deriveItemNumber(itemsSelectValue: string | undefined, itemsType: ProductType): string;
43
55
  /**
44
56
  * Returns default ItemsBlockConfig values.
45
57
  * These are used when initializing a new block or when migrating from legacy format.
@@ -0,0 +1,11 @@
1
+ import type { Template } from '@@/Types/stripo';
2
+ /**
3
+ * Fetches the blank starter template (html + css) from the email CDN — the single
4
+ * source of truth shared with email-fe. Retries a few times, caches the result for
5
+ * the session, and on persistent failure returns an empty template (the editor still
6
+ * opens) plus a toaster. Kept separate from stripoApi: this is a CDN asset fetch, not
7
+ * a Stripo backend call.
8
+ */
9
+ export declare const useBlankTemplate: () => {
10
+ getBlankTemplate: () => Promise<Template>;
11
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "3.9.0-beta.ec06cf4",
3
+ "version": "3.9.0-beta.f844081",
4
4
  "description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
5
5
  "main": "./dist/guido.umd.cjs",
6
6
  "module": "./dist/library.js",
@@ -1,74 +0,0 @@
1
- const t = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
- <html>
3
-
4
- <head>
5
- <meta charset="UTF-8">
6
- <meta content="width=device-width, initial-scale=1" name="viewport">
7
- <meta name="x-apple-disable-message-reformatting">
8
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
9
- <meta content="telephone=no" name="format-detection">
10
- <title></title>
11
- <!--[if (mso 16)]><style type="text/css">a{text-decoration:none}</style><![endif]-->
12
- <!--[if gte mso 9]><style>sup{font-size:100% !important}</style><![endif]-->
13
- <!--[if gte mso 9]><style>sup{font-size:100% !important}</style><![endif]-->
14
- <!--[if gte mso 9]><style>sup{font-size:100% !important}</style><![endif]-->
15
- <!--[if gte mso 9]><style>sup{font-size:100% !important}</style><![endif]-->
16
- <!--[if gte mso 9]><style>sup { font-size: 100% !important; }</style><![endif]-->
17
- </head>
18
-
19
- <body>
20
- <div class="es-wrapper-color">
21
- <!--[if gte mso 9]>
22
- <v:background xmlns:v="urn:schemas-microsoft-com:vml" fill="t">
23
- <v:fill type="tile" color="#f6f6f6"></v:fill>
24
- </v:background>
25
- <![endif]-->
26
- <table class="es-wrapper" width="100%" cellspacing="0" cellpadding="0">
27
- <tbody>
28
- <tr>
29
- <td class="esd-email-paddings" valign="top">
30
- <table class="es-content esd-footer-popover" cellspacing="0" cellpadding="0" align="center">
31
- <tbody>
32
- <tr>
33
- <td class="esd-stripe" align="center">
34
- <table class="es-content-body" width="600" cellspacing="0" cellpadding="0" bgcolor="#ffffff" align="center">
35
- <tbody>
36
- <tr>
37
- <td class="esd-structure es-p20" align="left">
38
- <table cellpadding="0" cellspacing="0" width="100%">
39
- <tbody>
40
- <tr>
41
- <td width="560" class="esd-container-frame" align="center" valign="top">
42
- <table cellpadding="0" cellspacing="0" width="100%">
43
- <tbody>
44
- <tr>
45
- <td align="center" class="esd-empty-container" style="display: none;"></td>
46
- </tr>
47
- </tbody>
48
- </table>
49
- </td>
50
- </tr>
51
- </tbody>
52
- </table>
53
- </td>
54
- </tr>
55
- </tbody>
56
- </table>
57
- </td>
58
- </tr>
59
- </tbody>
60
- </table>
61
- </td>
62
- </tr>
63
- </tbody>
64
- </table>
65
- </div>
66
- <div style="position: absolute; left: -9999px; top: -9999px; margin: 0px;"></div>
67
- <div style="position: absolute; left: -9999px; top: -9999px; margin: 0px; padding: 0px; border: 0px none; width: 1px;"></div>
68
- </body>
69
-
70
- </html>
71
- `;
72
- export {
73
- t as default
74
- };