@useinsider/guido 3.2.0-beta.8e8f902 → 3.2.0-beta.8f147c3

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 (72) hide show
  1. package/README.md +1 -25
  2. package/dist/@types/config/schemas.js +163 -109
  3. package/dist/components/Guido.vue.js +4 -4
  4. package/dist/components/Guido.vue2.js +77 -77
  5. package/dist/components/organisms/header/RightSlot.vue.js +8 -8
  6. package/dist/components/organisms/header/RightSlot.vue2.js +8 -9
  7. package/dist/composables/useSave.js +15 -15
  8. package/dist/config/migrator/index.js +9 -9
  9. package/dist/config/migrator/recommendation/compositionMapper.js +98 -0
  10. package/dist/config/migrator/recommendation/extractors.js +27 -0
  11. package/dist/config/migrator/recommendation/htmlBuilder.js +486 -0
  12. package/dist/config/migrator/recommendation/parseLegacyConfig.js +33 -0
  13. package/dist/config/migrator/recommendation/settingsMapper.js +78 -0
  14. package/dist/config/migrator/recommendation/themeMapper.js +93 -0
  15. package/dist/config/migrator/recommendationMigrator.js +60 -290
  16. package/dist/enums/extensions/recommendationBlock.js +2 -1
  17. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +5 -5
  18. package/dist/extensions/Blocks/Recommendation/services/configService.js +65 -29
  19. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +8 -8
  20. package/dist/extensions/Blocks/Recommendation/templates/utils.js +1 -1
  21. package/dist/extensions/Blocks/Recommendation/utils/preserveTextStyles.js +13 -22
  22. package/dist/guido.css +1 -1
  23. package/dist/node_modules/valibot/dist/index.js +450 -235
  24. package/dist/services/templateLibraryApi.js +4 -5
  25. package/dist/src/@types/config/defaults.d.ts +5 -1
  26. package/dist/src/@types/config/index.d.ts +3 -3
  27. package/dist/src/@types/config/schemas.d.ts +213 -4
  28. package/dist/src/@types/config/types.d.ts +9 -1
  29. package/dist/src/components/Guido.vue.d.ts +1 -1
  30. package/dist/src/components/organisms/header/EditorActions.vue.d.ts +1 -1
  31. package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +1 -1
  32. package/dist/src/components/organisms/header/RightSlot.vue.d.ts +1 -1
  33. package/dist/src/components/wrappers/WpModal.vue.d.ts +1 -1
  34. package/dist/src/composables/useConfig.d.ts +56 -2
  35. package/dist/src/composables/useSave.d.ts +1 -1
  36. package/dist/src/config/migrator/index.d.ts +2 -1
  37. package/dist/src/config/migrator/recommendation/compositionMapper.d.ts +2 -0
  38. package/dist/src/config/migrator/recommendation/compositionMapper.test.d.ts +1 -0
  39. package/dist/src/config/migrator/recommendation/extractors.d.ts +7 -0
  40. package/dist/src/config/migrator/recommendation/htmlBuilder.d.ts +11 -0
  41. package/dist/src/config/migrator/recommendation/parseLegacyConfig.d.ts +15 -0
  42. package/dist/src/config/migrator/recommendation/parseLegacyConfig.test.d.ts +1 -0
  43. package/dist/src/config/migrator/recommendation/settingsMapper.d.ts +7 -0
  44. package/dist/src/config/migrator/recommendation/settingsMapper.test.d.ts +1 -0
  45. package/dist/src/config/migrator/recommendation/themeMapper.d.ts +5 -0
  46. package/dist/src/config/migrator/recommendation/themeMapper.test.d.ts +1 -0
  47. package/dist/src/config/migrator/recommendation/types.d.ts +205 -0
  48. package/dist/src/config/migrator/recommendationMigrator.d.ts +13 -1
  49. package/dist/src/config/migrator/recommendationMigrator.test.d.ts +1 -0
  50. package/dist/src/extensions/Blocks/Recommendation/services/configService.d.ts +10 -0
  51. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +1 -1
  52. package/dist/src/extensions/Blocks/Recommendation/utils/preserveTextStyles.d.ts +0 -3
  53. package/dist/src/stores/config.d.ts +504 -18
  54. package/dist/src/stores/editor.d.ts +0 -23
  55. package/dist/src/utils/htmlEscape.d.ts +5 -0
  56. package/dist/stores/editor.js +1 -3
  57. package/dist/utils/htmlEscape.js +13 -0
  58. package/dist/utils/pairProductVariables.js +88 -89
  59. package/package.json +5 -1
  60. package/dist/components/organisms/AutoSaveController.vue.js +0 -17
  61. package/dist/components/organisms/AutoSaveController.vue2.js +0 -13
  62. package/dist/components/organisms/header/AutoSaveToggle.vue.js +0 -22
  63. package/dist/components/organisms/header/AutoSaveToggle.vue2.js +0 -19
  64. package/dist/composables/useAutoSave.js +0 -71
  65. package/dist/extensions/Blocks/Recommendation/templates/grid/migration.js +0 -251
  66. package/dist/src/components/organisms/AutoSaveController.vue.d.ts +0 -2
  67. package/dist/src/components/organisms/header/AutoSaveToggle.vue.d.ts +0 -2
  68. package/dist/src/composables/useAutoSave.d.ts +0 -3
  69. package/dist/src/stores/autosave.d.ts +0 -12
  70. package/dist/src/utils/timeUtil.d.ts +0 -8
  71. package/dist/stores/autosave.js +0 -17
  72. package/dist/utils/timeUtil.js +0 -19
@@ -263,27 +263,4 @@ export declare const useEditorStore: import("pinia").StoreDefinition<"guidoEdito
263
263
  templateId: string;
264
264
  syncModulesEnabled: boolean;
265
265
  }>) => boolean;
266
- isInSaveableState: (state: {
267
- loadingStatus: boolean;
268
- isCodeEditorOpen: boolean;
269
- isSaveAsTemplateDrawerOpen: boolean;
270
- isVersionHistoryOpen: boolean;
271
- isPreviewModeOpen: boolean;
272
- editorVisualMode: string;
273
- hasChanges: boolean;
274
- isStripoInitialized: boolean;
275
- templateId: string;
276
- syncModulesEnabled: boolean;
277
- } & import("pinia").PiniaCustomStateProperties<{
278
- loadingStatus: boolean;
279
- isCodeEditorOpen: boolean;
280
- isSaveAsTemplateDrawerOpen: boolean;
281
- isVersionHistoryOpen: boolean;
282
- isPreviewModeOpen: boolean;
283
- editorVisualMode: string;
284
- hasChanges: boolean;
285
- isStripoInitialized: boolean;
286
- templateId: string;
287
- syncModulesEnabled: boolean;
288
- }>) => boolean;
289
266
  }, {}>;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Escape HTML special characters for safe inclusion in attribute values
3
+ * or text content. Use for any string that may contain untrusted input.
4
+ */
5
+ export declare function escapeHtml(text: string): string;
@@ -25,9 +25,7 @@ const o = e("guidoEditor", {
25
25
  isExportButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen,
26
26
  isSaveAsButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen,
27
27
  isTestButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen,
28
- isSaveButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen || i.isPreviewModeOpen,
29
- // Autosave
30
- isInSaveableState: (i) => !i.loadingStatus && !i.isVersionHistoryOpen && !i.isPreviewModeOpen && !i.isCodeEditorOpen
28
+ isSaveButtonDisabled: (i) => i.loadingStatus || i.isVersionHistoryOpen || i.isPreviewModeOpen
31
29
  }
32
30
  });
33
31
  export {
@@ -0,0 +1,13 @@
1
+ const c = {
2
+ "&": "&amp;",
3
+ "<": "&lt;",
4
+ ">": "&gt;",
5
+ '"': "&quot;",
6
+ "'": "&#x27;"
7
+ };
8
+ function n(t) {
9
+ return t.replace(/[&<>"']/g, (e) => c[e]);
10
+ }
11
+ export {
12
+ n as escapeHtml
13
+ };
@@ -1,85 +1,84 @@
1
- import { productPairs as L } from "../extensions/Blocks/Items/enums/productEnums.js";
2
- function q(w) {
3
- const y = w.replaceAll("{%", "<!--{%").replaceAll("%}", "%}-->"), T = new DOMParser().parseFromString(y, "text/html"), C = L.PAIRS_FOR_EXTENSION;
4
- Object.entries(C).forEach(([r, f]) => {
5
- T.querySelectorAll(".ins-product-td").forEach((o) => {
6
- const A = o.getAttribute("data-number") || "1", b = o.getAttribute("data-type") || "CART_ITEMS";
7
- o.querySelectorAll(`[product-attr="${r}"]`).forEach((e) => {
8
- var k, F, I;
9
- const $ = e.getAttribute("data-type") || b, d = e.getAttribute("data-number") || A, u = f[$];
10
- if (u)
11
- switch (r) {
1
+ import { productPairs as P } from "../extensions/Blocks/Items/enums/productEnums.js";
2
+ function L(F) {
3
+ const R = F.replaceAll("{%", "<!--{%").replaceAll("%}", "%}-->"), $ = new DOMParser().parseFromString(R, "text/html"), y = P.PAIRS_FOR_EXTENSION;
4
+ Object.entries(y).forEach(([n, l]) => {
5
+ $.querySelectorAll(".ins-product-td").forEach((c) => {
6
+ const E = c.getAttribute("data-number") || "1", T = c.getAttribute("data-type") || "CART_ITEMS";
7
+ c.querySelectorAll(`[product-attr="${n}"]`).forEach((e) => {
8
+ var H;
9
+ const b = e.getAttribute("data-type") || T, u = e.getAttribute("data-number") || E, p = l[b];
10
+ if (p)
11
+ switch (n) {
12
12
  case "imageSrc": {
13
- let t = null, i = null;
14
- if (e.tagName === "IMG" ? (t = e, i = t.closest("a")) : (t = e.querySelector("img"), i = e.querySelector("a") || e.closest("a")), !t)
13
+ let t = null, o = null;
14
+ if (e.tagName === "IMG" ? (t = e, o = t.closest("a")) : (t = e.querySelector("img"), o = e.querySelector("a") || e.closest("a")), !t)
15
15
  break;
16
- const a = u.DEFAULT, s = u.ATTR;
17
- if (a && t.src) {
18
- const c = t.src;
19
- a.some((h) => {
20
- const l = h.split("/").pop() || "", g = c.split("/").pop() || "";
21
- return c.includes(h) || c.includes(l) || g === l;
22
- }) && (t.src = `{{${s}_${d}}}`);
16
+ const i = p.DEFAULT, a = p.ATTR;
17
+ if (i && t.src) {
18
+ const r = t.src;
19
+ i.some((f) => {
20
+ const s = f.split("/").pop() || "", _ = r.split("/").pop() || "";
21
+ return r.includes(f) || r.includes(s) || _ === s;
22
+ }) && (t.src = `{{${a}_${u}}}`);
23
23
  }
24
- const n = (F = (k = C.name) == null ? void 0 : k[$]) == null ? void 0 : F.ATTR;
25
- if (n && t.setAttribute("alt", `{{${n}_${d}}}`), i) {
26
- const c = (I = C.itemLink) == null ? void 0 : I[$];
27
- if (c) {
28
- const E = c.HREF, h = c.DEFAULT_HREF || "#!", l = i.href;
29
- (l === "#" || l === "" || l.endsWith("#!") || l.endsWith(h) || l === `${window.location.href}${h}` || !l || l === window.location.href) && (i.href = `{{${E}_${d}}}`);
24
+ if (o) {
25
+ const r = (H = y.itemLink) == null ? void 0 : H[b];
26
+ if (r) {
27
+ const d = r.HREF, f = r.DEFAULT_HREF || "#!", s = o.href;
28
+ (s === "#" || s === "" || s.endsWith("#!") || s.endsWith(f) || s === `${window.location.href}${f}` || !s || s === window.location.href) && (o.href = `{{${d}_${u}}}`);
30
29
  }
31
30
  }
32
31
  break;
33
32
  }
34
33
  case "name": {
35
- const t = u, i = t.ATTR, a = t.DEFAULT_HREF || "#!", s = t.HREF;
36
- e.textContent && (e.textContent = `{{${i}_${d}}}`);
37
- const n = e.closest("a") || (e.tagName === "A" ? e : null);
38
- if (n && s) {
39
- const c = n.href, E = `${window.location.href}${a}`;
40
- (c === E || c.endsWith(a)) && (n.href = `{{${s}_${d}}}`);
34
+ const t = p, o = t.ATTR, i = t.DEFAULT_HREF || "#!", a = t.HREF;
35
+ e.textContent && (e.textContent = `{{${o}_${u}}}`);
36
+ const r = e.closest("a") || (e.tagName === "A" ? e : null);
37
+ if (r && a) {
38
+ const d = r.href, f = `${window.location.href}${i}`;
39
+ (d === f || d.endsWith(i)) && (r.href = `{{${a}_${u}}}`);
41
40
  }
42
41
  break;
43
42
  }
44
43
  case "price":
45
44
  case "originalPrice": {
46
- const t = u, i = e.getAttribute("data-formated"), a = e.getAttribute("data-single_price"), s = i === "true", n = a === "true", c = e.getAttribute("data-curency") || "before";
47
- let E;
48
- n ? E = s ? t.SINGLE_PRICE_FORMATTED : t.SINGLE_PRICE : E = s ? t.PRICE_FORMATTED : t.PRICE;
49
- const h = t.CURRENCY;
50
- let l = `{{${E}_${d}}}`;
51
- if (h) {
52
- const g = `{{${h}_${d}}}`;
53
- l = c === "after" ? `${l} ${g}` : `${g} ${l}`;
45
+ const t = p, o = e.getAttribute("data-formated"), i = e.getAttribute("data-single_price"), a = o === "true", r = i === "true", d = e.getAttribute("data-curency") || "before";
46
+ let f;
47
+ r ? f = a ? t.SINGLE_PRICE_FORMATTED : t.SINGLE_PRICE : f = a ? t.PRICE_FORMATTED : t.PRICE;
48
+ const s = t.CURRENCY;
49
+ let _ = `{{${f}_${u}}}`;
50
+ if (s) {
51
+ const k = `{{${s}_${u}}}`;
52
+ _ = d === "after" ? `${_} ${k}` : `${k} ${_}`;
54
53
  }
55
- e.textContent = l;
54
+ e.textContent = _;
56
55
  break;
57
56
  }
58
57
  case "quantity": {
59
- const t = u, i = t.ATTR, a = t.DEFAULT;
60
- e.textContent && e.textContent.trim() === a && (e.textContent = `{{${i}_${d}}}`);
58
+ const t = p, o = t.ATTR, i = t.DEFAULT;
59
+ e.textContent && e.textContent.trim() === i && (e.textContent = `{{${o}_${u}}}`);
61
60
  break;
62
61
  }
63
62
  case "button": {
64
- const t = u, i = t.HREF, a = t.DEFAULT_HREF || "#!", s = e.tagName === "A" ? e : e.querySelector("a");
65
- if (s) {
66
- const n = s.href || "", c = `${window.location.href}${a}`;
67
- (n === "" || n === "#" || n === c || n.endsWith(a) || n.endsWith("#!") || n === window.location.href) && (s.href = `{{${i}_${d}}}`);
63
+ const t = p, o = t.HREF, i = t.DEFAULT_HREF || "#!", a = e.tagName === "A" ? e : e.querySelector("a");
64
+ if (a) {
65
+ const r = a.href || "", d = `${window.location.href}${i}`;
66
+ (r === "" || r === "#" || r === d || r.endsWith(i) || r.endsWith("#!") || r === window.location.href) && (a.href = `{{${o}_${u}}}`);
68
67
  }
69
68
  break;
70
69
  }
71
70
  case "itemLink": {
72
- const t = u, i = t.HREF, a = t.DEFAULT_HREF || "#!", s = e;
73
- if (s.href) {
74
- const n = s.href, c = `${window.location.href}${a}`;
75
- (n === c || n.endsWith(a)) && (s.href = `{{${i}_${d}}}`);
71
+ const t = p, o = t.HREF, i = t.DEFAULT_HREF || "#!", a = e;
72
+ if (a.href) {
73
+ const r = a.href, d = `${window.location.href}${i}`;
74
+ (r === d || r.endsWith(i)) && (a.href = `{{${o}_${u}}}`);
76
75
  }
77
76
  break;
78
77
  }
79
78
  default: {
80
- if ("ATTR" in u) {
81
- const t = u.ATTR;
82
- e.textContent && (e.textContent = `{{${t}_${d}}}`);
79
+ if ("ATTR" in p) {
80
+ const t = p.ATTR;
81
+ e.textContent && (e.textContent = `{{${t}_${u}}}`);
83
82
  }
84
83
  break;
85
84
  }
@@ -87,55 +86,55 @@ function q(w) {
87
86
  });
88
87
  });
89
88
  });
90
- const S = y.match(/<!DOCTYPE[^>]*>/i), M = S ? `${S[0]}
91
- ` : "", P = T.querySelectorAll(".ins-product-td"), H = [];
92
- P.forEach((r) => {
93
- const f = r.getAttribute("data-type") || "CART_ITEMS", p = r.getAttribute("data-number") || "1", o = r.getAttribute("data-nodup"), A = r.outerHTML;
94
- H.push({
95
- element: r,
96
- outerHtml: A,
97
- type: f,
98
- number: p,
99
- nodup: o || void 0
89
+ const S = R.match(/<!DOCTYPE[^>]*>/i), I = S ? `${S[0]}
90
+ ` : "", w = $.querySelectorAll(".ins-product-td"), m = [];
91
+ w.forEach((n) => {
92
+ const l = n.getAttribute("data-type") || "CART_ITEMS", A = n.getAttribute("data-number") || "1", c = n.getAttribute("data-nodup"), E = n.outerHTML;
93
+ m.push({
94
+ element: n,
95
+ outerHtml: E,
96
+ type: l,
97
+ number: A,
98
+ nodup: c || void 0
100
99
  });
101
100
  });
102
- let _ = M + T.documentElement.outerHTML;
103
- H.reverse().forEach(({ outerHtml: r, type: f, number: p }) => {
104
- let o = "";
105
- switch (f) {
101
+ let h = I + $.documentElement.outerHTML;
102
+ m.reverse().forEach(({ outerHtml: n, type: l, number: A }) => {
103
+ let c = "";
104
+ switch (l) {
106
105
  case "CART_ITEMS":
107
- o = "ins_apr_total_product_kind";
106
+ c = "ins_apr_total_product_kind";
108
107
  break;
109
108
  case "BROWSED_ITEMS":
110
- o = "browsed_item_total_product_kind";
109
+ c = "browsed_item_total_product_kind";
111
110
  break;
112
111
  case "PURCHASED_ITEMS":
113
- o = "purchased_item_total_product_kind";
112
+ c = "purchased_item_total_product_kind";
114
113
  break;
115
114
  }
116
- if (o) {
117
- const b = parseInt(p) - 1, $ = `${`{% if ${o} > ${b} %}`}${r}{% endif %}`;
118
- _ = _.replace(r, $);
115
+ if (c) {
116
+ const T = parseInt(A) - 1, b = `${`{% if ${c} > ${T} %}`}${n}{% endif %}`;
117
+ h = h.replace(n, b);
119
118
  }
120
119
  });
121
- const D = T.querySelectorAll('[product-attr="originalPrice"][data-type="CART_ITEMS"]'), R = [];
122
- return D.forEach((r) => {
123
- const f = r.getAttribute("data-number"), p = r.getAttribute("data-type");
124
- if (!f || p !== "CART_ITEMS")
120
+ const M = $.querySelectorAll('[product-attr="originalPrice"][data-type="CART_ITEMS"]'), g = [];
121
+ return M.forEach((n) => {
122
+ const l = n.getAttribute("data-number"), A = n.getAttribute("data-type");
123
+ if (!l || A !== "CART_ITEMS")
125
124
  return;
126
- const o = r.closest(".product-original-price-class");
127
- if (o) {
128
- const A = o.outerHTML;
129
- R.some((m) => m.tdOuterHtml === A) || R.push({ tdOuterHtml: A, number: f });
125
+ const c = n.closest(".product-original-price-class");
126
+ if (c) {
127
+ const E = c.outerHTML;
128
+ g.some((C) => C.tdOuterHtml === E) || g.push({ tdOuterHtml: E, number: l });
130
129
  }
131
- }), R.reverse().forEach(({ tdOuterHtml: r, number: f }) => {
132
- const p = `{% if ins_apr_price_${f} != ins_apr_originalprice_${f} %}`;
133
- if (!_.includes(p) && !r.includes("{% if")) {
134
- const A = `${p}${r}{% endif %}`;
135
- _ = _.replace(r, A);
130
+ }), g.reverse().forEach(({ tdOuterHtml: n, number: l }) => {
131
+ const A = `{% if ins_apr_price_${l} != ins_apr_originalprice_${l} %}`;
132
+ if (!h.includes(A) && !n.includes("{% if")) {
133
+ const E = `${A}${n}{% endif %}`;
134
+ h = h.replace(n, E);
136
135
  }
137
- }), _.replaceAll("<!--{%", "{%").replaceAll("%}-->", "%}").replaceAll("&lt;!--{%", "{%").replaceAll("%}--&gt;", "%}");
136
+ }), h.replaceAll("<!--{%", "{%").replaceAll("%}-->", "%}").replaceAll("&lt;!--{%", "{%").replaceAll("%}--&gt;", "%}");
138
137
  }
139
138
  export {
140
- q as pairProductVariables
139
+ L as pairProductVariables
141
140
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "3.2.0-beta.8e8f902",
3
+ "version": "3.2.0-beta.8f147c3",
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",
@@ -24,6 +24,8 @@
24
24
  "lint": "NODE_OPTIONS=--max-old-space-size=2048 eslint ./ && bun run type-check",
25
25
  "lint:fix": "NODE_OPTIONS=--max-old-space-size=2048 eslint --fix ./",
26
26
  "type-check": "vue-tsc --noEmit --project tsconfig.config.json && vue-tsc --noEmit --project tsconfig.app.json",
27
+ "test": "vitest run",
28
+ "test:watch": "vitest",
27
29
  "test:visual-update": "npx playwright test --update-snapshots --reporter html",
28
30
  "prepare": "husky",
29
31
  "preinstall": "rm -rf ./node_modules/.vite"
@@ -69,12 +71,14 @@
69
71
  "eslint-plugin-vue": "10.1.0",
70
72
  "eslint-plugin-vue-scoped-css": "2.6.1",
71
73
  "globals": "16.0.0",
74
+ "happy-dom": "^15",
72
75
  "husky": "9.1.7",
73
76
  "msw": "2.10.3",
74
77
  "sass": "1.69.7",
75
78
  "typescript": "5.5.4",
76
79
  "typescript-eslint": "8.26.0",
77
80
  "vite-plugin-dts": "4.5.4",
81
+ "vitest": "^2",
78
82
  "vue-tsc": "2.2.10"
79
83
  },
80
84
  "overrides": {
@@ -1,17 +0,0 @@
1
- import n from "./AutoSaveController.vue2.js";
2
- import t from "../../_virtual/_plugin-vue2_normalizer.js";
3
- var o = function() {
4
- var r = this, e = r._self._c;
5
- return r._self._setupProxy, e("div", { staticClass: "d-n" });
6
- }, s = [], _ = /* @__PURE__ */ t(
7
- n,
8
- o,
9
- s,
10
- !1,
11
- null,
12
- null
13
- );
14
- const f = _.exports;
15
- export {
16
- f as default
17
- };
@@ -1,13 +0,0 @@
1
- import { defineComponent as t } from "vue";
2
- import { useAutoSave as r } from "../../composables/useAutoSave.js";
3
- import { useSave as s } from "../../composables/useSave.js";
4
- const f = /* @__PURE__ */ t({
5
- __name: "AutoSaveController",
6
- setup(a) {
7
- const { save: e } = s(), o = () => e(!1, !0);
8
- return r(o), { __sfc: !0, save: e, backgroundSave: o };
9
- }
10
- });
11
- export {
12
- f as default
13
- };
@@ -1,22 +0,0 @@
1
- import o from "./AutoSaveToggle.vue2.js";
2
- /* empty css */
3
- import i from "../../../_virtual/_plugin-vue2_normalizer.js";
4
- var n = function() {
5
- var e = this, a = e._self._c, t = e._self._setupProxy;
6
- return t.isFeatureEnabled("autosave") ? a("div", { staticClass: "d-f a-i-c mr-3 auto-save-toggle", on: { mouseenter: function(s) {
7
- t.isHovered = !0;
8
- }, mouseleave: function(s) {
9
- t.isHovered = !1;
10
- } } }, [a(t.InToggle, { attrs: { id: "guido__autosave-toggle", name: "guido-autosave-toggle", checked: t.autosaveStore.isOn, disable: t.editorStore.loadingStatus }, on: { click: t.toggle } }), a("span", { staticClass: "ml-2 auto-save-toggle__label t-c-55" }, [e._v(" " + e._s(t.trans("email-editor.auto-save")) + " ")]), t.autosaveStore.status === t.AUTOSAVE_STATUS.SAVING ? a("span", { staticClass: "ml-2 d-f a-i-c f-s-1" }, [a(t.InLoading, { attrs: { "color-class": "i-c-53", size: "16" } }), a("span", { staticClass: "ml-1 t-c-53" }, [e._v(" " + e._s(t.trans("newsletter.saving")) + " ")])], 1) : t.lastSavedLabel ? a("span", { staticClass: "ml-2 f-s-1 t-c-53" }, [e._v(" " + e._s(t.lastSavedLabel) + " ")]) : e._e(), t.isHovered ? a(t.InInfoBox, { staticClass: "auto-save-toggle__info-box", attrs: { id: "guido__autosave-info-box", size: "small", variant: "information", "description-text": t.trans("email-editor.auto-save-description"), "title-text": t.trans("email-editor.auto-save-title") } }) : e._e()], 1) : e._e();
11
- }, l = [], r = /* @__PURE__ */ i(
12
- o,
13
- n,
14
- l,
15
- !1,
16
- null,
17
- "2c964af4"
18
- );
19
- const d = r.exports;
20
- export {
21
- d as default
22
- };
@@ -1,19 +0,0 @@
1
- import { defineComponent as i, ref as f, computed as u } from "vue";
2
- import { useConfig as l } from "../../../composables/useConfig.js";
3
- import { useTranslations as p } from "../../../composables/useTranslations.js";
4
- import { useAutosaveStore as c, AUTOSAVE_STATUS as t } from "../../../stores/autosave.js";
5
- import { useEditorStore as S } from "../../../stores/editor.js";
6
- import { formatLocalTime as d } from "../../../utils/timeUtil.js";
7
- import { InToggle as g, InLoading as _, InInfoBox as A } from "@useinsider/design-system-vue";
8
- const U = /* @__PURE__ */ i({
9
- __name: "AutoSaveToggle",
10
- setup(v) {
11
- const { isFeatureEnabled: e } = l(), r = S(), o = c(), s = p(), n = f(!1), a = u(() => o.status !== t.SAVED || !o.lastSavedAt ? "" : d(o.lastSavedAt));
12
- return { __sfc: !0, isFeatureEnabled: e, editorStore: r, autosaveStore: o, trans: s, isHovered: n, lastSavedLabel: a, toggle: (m) => {
13
- o.isOn = m;
14
- }, AUTOSAVE_STATUS: t, InInfoBox: A, InLoading: _, InToggle: g };
15
- }
16
- });
17
- export {
18
- U as default
19
- };
@@ -1,71 +0,0 @@
1
- import { useConfig as m } from "./useConfig.js";
2
- import { useAutosaveStore as A, AUTOSAVE_STATUS as s } from "../stores/autosave.js";
3
- import { useEditorStore as E } from "../stores/editor.js";
4
- import { computed as f, watch as p, onUnmounted as y } from "vue";
5
- const I = 18e4, r = 6e4, T = (b) => {
6
- const { isFeatureEnabled: S } = m(), a = E(), t = A();
7
- let i = null, c = 0;
8
- const u = f(
9
- () => S("autosave") && t.isOn
10
- ), g = () => a.hasChanges && a.isInSaveableState, h = () => ({
11
- hasChanges: a.hasChanges,
12
- isInSaveableState: a.isInSaveableState
13
- }), l = async (e) => {
14
- if (!u.value) {
15
- console.debug("guido:autosave:skipped", { trigger: e, reason: "not-active" });
16
- return;
17
- }
18
- if (!g()) {
19
- console.debug("guido:autosave:skipped", { trigger: e, reason: "gates-blocked", gates: h() });
20
- return;
21
- }
22
- if (t.status === s.SAVING) {
23
- console.debug("guido:autosave:skipped", { trigger: e, reason: "already-saving" });
24
- return;
25
- }
26
- console.debug("guido:autosave:save-start", { trigger: e }), t.status = s.SAVING;
27
- try {
28
- if (await b() === void 0) {
29
- console.debug("guido:autosave:blocked", { trigger: e, reason: "save-returned-undefined" }), t.status = s.ERROR;
30
- return;
31
- }
32
- a.hasChanges = !1, t.status = s.SAVED, t.lastSavedAt = /* @__PURE__ */ new Date(), console.debug("guido:autosave:save-complete", { trigger: e, at: t.lastSavedAt });
33
- } catch (o) {
34
- console.debug("guido:autosave:error", { trigger: e, error: o }), t.status = s.ERROR;
35
- }
36
- }, n = () => {
37
- const { visibilityState: e } = document;
38
- if (console.debug("guido:autosave:visibility-change", {
39
- visibilityState: e,
40
- isActive: u.value
41
- }), e !== "hidden")
42
- return;
43
- const o = Date.now() - c;
44
- if (o < r) {
45
- console.debug("guido:autosave:visibility-debounced", {
46
- sinceLastMs: o,
47
- debounceMs: r
48
- });
49
- return;
50
- }
51
- c = Date.now(), l("visibility");
52
- }, d = () => {
53
- i && (clearInterval(i), i = null);
54
- }, v = () => {
55
- document.removeEventListener("visibilitychange", n), window.removeEventListener("pagehide", n);
56
- };
57
- p(
58
- u,
59
- (e) => {
60
- console.debug("guido:autosave:active-changed", { active: e }), e ? (d(), i = setInterval(() => {
61
- console.debug("guido:autosave:interval-tick"), l("interval");
62
- }, I), document.addEventListener("visibilitychange", n), window.addEventListener("pagehide", n)) : (d(), v(), t.status = s.IDLE);
63
- },
64
- { immediate: !0 }
65
- ), y(() => {
66
- d(), v(), t.status = s.IDLE, t.lastSavedAt = null;
67
- });
68
- };
69
- export {
70
- T as useAutoSave
71
- };