@useinsider/guido 3.22.0-beta.9277778 → 3.22.0-beta.cca3c2e

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +35 -13
  2. package/dist/@types/config/schemas.js +33 -35
  3. package/dist/components/Guido.vue.js +5 -5
  4. package/dist/components/Guido.vue2.js +121 -115
  5. package/dist/composables/useEditorOpenMetrics.js +167 -0
  6. package/dist/composables/useModuleRepair.js +23 -32
  7. package/dist/composables/useStripo.js +93 -82
  8. package/dist/config/compiler/utils/recommendationCompilerUtils.js +22 -22
  9. package/dist/config/migrator/index.js +9 -10
  10. package/dist/config/migrator/recommendation/compositionMapper.js +56 -49
  11. package/dist/config/migrator/recommendation/extractors.js +100 -40
  12. package/dist/config/migrator/recommendation/htmlBuilder.js +285 -207
  13. package/dist/config/migrator/recommendation/settingsMapper.js +37 -36
  14. package/dist/config/migrator/recommendation/themeMapper.js +53 -41
  15. package/dist/config/migrator/recommendationMigrator.js +68 -61
  16. package/dist/enums/academy.js +1 -2
  17. package/dist/extensions/Blocks/Recommendation/block.js +33 -24
  18. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +20 -19
  19. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +148 -163
  20. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +23 -22
  21. package/dist/extensions/Blocks/Recommendation/templates/list/template.js +19 -18
  22. package/dist/extensions/Blocks/Recommendation/templates/utils.js +82 -91
  23. package/dist/extensions/Blocks/Recommendation/utils/inlinePriceOrder.js +12 -0
  24. package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMap.js +3 -2
  25. package/dist/guido.css +1 -1
  26. package/dist/library.js +12 -10
  27. package/dist/package.json.js +6 -4
  28. package/dist/public/prefetchRuntime.js +4 -0
  29. package/dist/src/@types/config/schemas.d.ts +0 -4
  30. package/dist/src/composables/useConfig.d.ts +0 -2
  31. package/dist/src/composables/useEditorOpenMetrics.d.ts +27 -0
  32. package/dist/src/composables/useModuleRepair.d.ts +11 -2
  33. package/dist/src/composables/useStripo.d.ts +2 -1
  34. package/dist/src/config/migrator/recommendation/compositionMapper.d.ts +3 -1
  35. package/dist/src/config/migrator/recommendation/extractors.d.ts +35 -6
  36. package/dist/src/config/migrator/recommendation/htmlBuilder.d.ts +3 -1
  37. package/dist/src/config/migrator/recommendation/themeMapper.d.ts +3 -1
  38. package/dist/src/config/migrator/recommendation/types.d.ts +11 -1
  39. package/dist/src/enums/academy.d.ts +0 -1
  40. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +1 -0
  41. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +2 -8
  42. package/dist/src/extensions/Blocks/Recommendation/templates/utils.d.ts +1 -13
  43. package/dist/src/extensions/Blocks/Recommendation/utils/inlinePriceOrder.d.ts +9 -0
  44. package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMap.d.ts +2 -19
  45. package/dist/src/library.d.ts +1 -0
  46. package/dist/src/public/prefetchRuntime.d.ts +1 -0
  47. package/dist/src/stores/config.d.ts +0 -20
  48. package/dist/src/stores/editor.d.ts +0 -25
  49. package/dist/src/utils/runtimePrefetch.d.ts +4 -0
  50. package/dist/src/utils/stripoRuntime.d.ts +3 -0
  51. package/dist/static/stripo-runtime-manifest.json.js +9 -0
  52. package/dist/stores/editor.js +14 -15
  53. package/dist/utils/runtimePrefetch.js +26 -0
  54. package/dist/utils/stripoRuntime.js +13 -0
  55. package/package.json +6 -1
  56. package/dist/components/organisms/unsubscribe/LegacyUnsubscribeConvertedModal.vue.js +0 -17
  57. package/dist/components/organisms/unsubscribe/LegacyUnsubscribeConvertedModal.vue2.js +0 -30
  58. package/dist/config/migrator/legacyUnsubscribeTextMigrator.js +0 -16
  59. package/dist/src/components/organisms/unsubscribe/LegacyUnsubscribeConvertedModal.vue.d.ts +0 -2
  60. package/dist/src/config/migrator/legacyUnsubscribeTextMigrator.d.ts +0 -1
  61. package/dist/src/utils/legacyUnsubscribeConversion.d.ts +0 -10
  62. package/dist/utils/legacyUnsubscribeConversion.js +0 -49
package/README.md CHANGED
@@ -166,7 +166,6 @@ const config: GuidoConfigInput = {
166
166
  allowlistEnabled?: boolean, // Default: false - Pre-save domain-allowlist check (opt-in). Guido self-serves the block toaster (role lookup, deep-link, copy from window.trans).
167
167
  allowSaveWithErrors?: boolean, // Default: true - Allow the validation drawer's "Save and Continue" soft-save. Set false to hard-block invalid saves (transactional + unsubscribe pages).
168
168
  reusableRecommendationStrategy?: boolean, // Default: false - Assign an RRS strategy to recommendation blocks instead of per-block algorithm/filters/shuffle/product-count settings.
169
- legacyUnsubscribeConversion?: boolean, // Default: false - Convert legacy unsubscribe blocks that have no unsubscribe link into text blocks (on load and on module drop/copy) and show a warning modal.
170
169
  },
171
170
 
172
171
  // Optional: Callbacks
@@ -583,9 +582,9 @@ import '@useinsider/guido/style';
583
582
 
584
583
  ### Subpath entries
585
584
 
586
- Two surfaces also ship as their own entry points. Importing one pulls in only its
587
- own dependencies, so a consumer that needs the store or the tracking-id helpers
588
- never loads the editor:
585
+ Three surfaces also ship as their own entry points. Importing one pulls in only its
586
+ own dependencies, so a consumer that needs the store, the tracking-id helpers or the
587
+ runtime prefetch never loads the editor:
589
588
 
590
589
  ```typescript
591
590
  // Live editor state, published by the editor into the host's shared Pinia instance.
@@ -596,11 +595,42 @@ import type { GuidoEmailEditorState } from '@useinsider/guido/editor-state';
596
595
  // Persistent link ids for the click heatmap.
597
596
  import { assignTrackingIds, TRACK_ID_ATTRIBUTE } from '@useinsider/guido/tracking-ids';
598
597
  import type { TrackingIdResult } from '@useinsider/guido/tracking-ids';
598
+
599
+ // Start downloading the Stripo editor runtime before the editor opens.
600
+ import { prefetchGuidoRuntime } from '@useinsider/guido/prefetch';
599
601
  ```
600
602
 
601
- Both are re-exported from the root barrel as well; the subpath is what keeps the
603
+ All three are re-exported from the root barrel as well; the subpath is what keeps the
602
604
  editor out of the consumer's module graph.
603
605
 
606
+ ### Runtime prefetch
607
+
608
+ ```typescript
609
+ import { prefetchGuidoRuntime } from '@useinsider/guido/prefetch';
610
+
611
+ prefetchGuidoRuntime(); // e.g. when the user lands on the page that opens the editor
612
+ ```
613
+
614
+ Call it as early as the host knows an editor is likely to open. It appends one
615
+ `<link rel="prefetch" data-guido-prefetch>` per file of the pinned Stripo runtime
616
+ (`src/static/stripo-runtime-manifest.json`) from
617
+ `https://email-static.useinsider.com/guido/<stripo version>/`, so the files are in the
618
+ HTTP cache when `<Guido>` mounts. It only downloads: no Stripo code runs and the
619
+ editor's startup order does not change.
620
+
621
+ - Returns `void` and never throws.
622
+ - Idempotent: later calls add nothing.
623
+ - Adds nothing when the runtime is already loading or loaded (`#UiEditorScript` exists
624
+ or `window.UIEditor` is defined), when the browser does not support `rel="prefetch"`
625
+ (Safari by default), when `navigator.connection.saveData` is on, or when
626
+ `navigator.connection.effectiveType` is `slow-2g` or `2g`.
627
+ - The `guido_editor_open` metric reports it as `runtime_prefetch`: `none` (not called
628
+ before Guido's setup), `pending` (some files still downloading) or `done`.
629
+
630
+ After bumping `guido.stripo.version`, regenerate the file list with
631
+ `npm run stripo:manifest`; a unit test fails while the manifest's version differs from
632
+ the pinned one.
633
+
604
634
  ---
605
635
 
606
636
  ## Constants
@@ -668,14 +698,6 @@ multiple partners (e.g. architect) should key by partner and place the active pa
668
698
  first. Omit the prop and the repair is a safe no-op — nothing is rewritten and no
669
699
  toaster fires (useful before the host has wired the catalog).
670
700
 
671
- With `features.legacyUnsubscribeConversion: true`, a dropped or copied module's legacy
672
- unsubscribe block that has no unsubscribe link (the old editor reused it as plain text,
673
- e.g. a company address) becomes a plain text block that keeps its content, and a warning
674
- modal explains it. The same conversion runs when a template is opened. Register these
675
- keys host-side: `email-editor.legacy-unsubscribe-converted-modal-title`,
676
- `email-editor.legacy-unsubscribe-converted-modal-message` and
677
- `email-editor.legacy-unsubscribe-converted-modal-visit-academy` (OK reuses `action-builder.ok`).
678
-
679
701
  ---
680
702
 
681
703
  ## Development
@@ -1,5 +1,5 @@
1
- import { ModuleFolderDefaults as S } from "../../enums/defaults.js";
2
- import { object as a, number as s, optional as e, string as t, picklist as m, pipe as i, minLength as b, custom as k, boolean as o, array as n, transform as y, unknown as r, record as g, fallback as R, literal as u, looseObject as C, variant as I, union as h, lazy as T } from "../../node_modules/valibot/dist/index.js";
1
+ import { ModuleFolderDefaults as f } from "../../enums/defaults.js";
2
+ import { object as a, number as s, optional as e, string as t, picklist as m, pipe as i, minLength as b, custom as k, boolean as o, array as c, transform as y, unknown as r, record as g, fallback as R, literal as u, looseObject as C, variant as I, union as h, lazy as T } from "../../node_modules/valibot/dist/index.js";
3
3
  const p = {
4
4
  /** Promotional/marketing emails */
5
5
  PROMOTIONAL: 1,
@@ -76,30 +76,30 @@ const p = {
76
76
  value: t()
77
77
  })
78
78
  )
79
- }), f = T(() => C({
79
+ }), S = T(() => C({
80
80
  text: e(t()),
81
81
  // eslint-disable-next-line camelcase -- backend field name
82
82
  tag_text: e(t()),
83
83
  value: e(t()),
84
- children: e(n(f)),
84
+ children: e(c(S)),
85
85
  // eslint-disable-next-line camelcase -- backend field name
86
- select_items: e(n(f))
87
- })), v = g(
86
+ select_items: e(c(S))
87
+ })), N = g(
88
88
  t(),
89
- R(n(f), [])
90
- ), N = C({
89
+ R(c(S), [])
90
+ ), P = C({
91
91
  /** Block ID (matches the dictionary key and the legacy HTML element id) */
92
92
  id: e(s()),
93
93
  /** Decimal places for price display (legacy data may use string or number) */
94
94
  decimalCount: e(h([t(), s()])),
95
95
  /** Pinned product IDs (empty array when filter-driven) */
96
- productIds: e(n(r())),
96
+ productIds: e(c(r())),
97
97
  /** Whether the block requested live products at send time */
98
98
  sendProductRequestFlag: e(o()),
99
99
  /** Whether to randomize product order */
100
100
  shuffleProducts: e(o()),
101
101
  /** Filter rules driving product selection */
102
- filters: e(n(r())),
102
+ filters: e(c(r())),
103
103
  /** Currency code (e.g. 'EUR') — sometimes absent in legacy data */
104
104
  currency: e(t()),
105
105
  /** Currency display settings (separators, alignment, decimals) */
@@ -109,7 +109,7 @@ const p = {
109
109
  /** Recommendation strategy key (e.g. 'newArrivals') */
110
110
  strategy: e(t()),
111
111
  /** Snapshot of products as rendered by the legacy block */
112
- recommendedProducts: e(n(r())),
112
+ recommendedProducts: e(c(r())),
113
113
  /** Number of product cards per row */
114
114
  cardsInRow: e(s()),
115
115
  /** Mobile-only padding (right) */
@@ -132,7 +132,7 @@ const p = {
132
132
  isPriceMovedToNextLine: e(o()),
133
133
  /** Legacy "Hide if same as discounted" / delete-price-for-zero-sale toggle */
134
134
  isPriceDeletedForZeroSale: e(o())
135
- }), P = a({
135
+ }), v = a({
136
136
  /**
137
137
  * Legacy recommendation block configs keyed by block ID.
138
138
  * Pass this when loading a template authored with the v1
@@ -140,7 +140,7 @@ const p = {
140
140
  * strategy, currency, locale, and layout data.
141
141
  */
142
142
  recommendationConfigs: e(
143
- g(t(), N),
143
+ g(t(), P),
144
144
  {}
145
145
  )
146
146
  }), x = a({
@@ -150,7 +150,7 @@ const p = {
150
150
  css: e(t(), ""),
151
151
  /** Preselected dynamic content items */
152
152
  preselectedDynamicContent: e(
153
- n(M),
153
+ c(M),
154
154
  []
155
155
  ),
156
156
  /**
@@ -159,11 +159,11 @@ const p = {
159
159
  * (first) partner's leaf attributes into the label→token map that repairs
160
160
  * label-form placeholders (`{{ Phone Number }}`) in dropped saved modules.
161
161
  */
162
- dynamicContentList: e(v, {}),
162
+ dynamicContentList: e(N, {}),
163
163
  /** Valid custom field attribute names from the partner's categorized fields */
164
- customFieldAttributes: e(n(t()), []),
164
+ customFieldAttributes: e(c(t()), []),
165
165
  /** Selected unsubscribe page IDs */
166
- selectedUnsubscribePages: e(n(s()), []),
166
+ selectedUnsubscribePages: e(c(s()), []),
167
167
  /** Force recreate template in Stripo storage (use true when updating externally modified templates) */
168
168
  forceRecreate: e(o(), !1),
169
169
  /**
@@ -176,7 +176,7 @@ const p = {
176
176
  trackIdCounter: e(
177
177
  i(
178
178
  s(),
179
- y((c) => Number.isFinite(c) ? Math.max(0, Math.floor(c)) : 0)
179
+ y((n) => Number.isFinite(n) ? Math.max(0, Math.floor(n)) : 0)
180
180
  ),
181
181
  0
182
182
  ),
@@ -190,11 +190,11 @@ const p = {
190
190
  recommendationCampaignUrls: e(
191
191
  i(
192
192
  r(),
193
- y((c) => c && typeof c == "object" ? { ...c } : void 0)
193
+ y((n) => n && typeof n == "object" ? { ...n } : void 0)
194
194
  )
195
195
  ),
196
196
  /** Migration-only inputs (legacy block configs) */
197
- migration: e(P, {})
197
+ migration: e(v, {})
198
198
  }), D = a({
199
199
  /** Sender display name */
200
200
  senderName: e(t(), ""),
@@ -210,9 +210,9 @@ const p = {
210
210
  /** Email header settings */
211
211
  emailHeader: e(D, { senderName: "", subject: "" }),
212
212
  /** Folder name for user-saved modules (used by Stripo plugin panel for path construction) */
213
- savedModulesFolderName: e(t(), S.SAVED_MODULES),
213
+ savedModulesFolderName: e(t(), f.SAVED_MODULES),
214
214
  /** Folder name for default/prebuilt modules (used by Stripo plugin panel for path construction) */
215
- defaultModulesFolderName: e(t(), S.DEFAULT_MODULES)
215
+ defaultModulesFolderName: e(t(), f.DEFAULT_MODULES)
216
216
  }), F = a({
217
217
  /** Whether to show the header bar */
218
218
  showHeader: e(o(), !0),
@@ -243,9 +243,7 @@ const p = {
243
243
  linkTrackingIds: e(o(), !1),
244
244
  /** Allow persisting a template that still has validation errors (drawer "Save and Continue" soft-save). Host sets false for transactional + unsubscribe. */
245
245
  allowSaveWithErrors: e(o(), !0),
246
- reusableRecommendationStrategy: e(o(), !1),
247
- /** Convert linkless legacy unsubscribe blocks into text blocks and warn with a modal (opt-in) */
248
- legacyUnsubscribeConversion: e(o(), !1)
246
+ reusableRecommendationStrategy: e(o(), !1)
249
247
  }), w = m([
250
248
  "amp-accordion",
251
249
  "amp-carousel",
@@ -271,12 +269,12 @@ const p = {
271
269
  ]), j = a({
272
270
  /** Default blocks to exclude from the editor */
273
271
  excludeDefaults: e(
274
- n(w),
272
+ c(w),
275
273
  []
276
274
  ),
277
275
  /** Custom blocks to include in the editor */
278
276
  includeCustoms: e(
279
- n(B),
277
+ c(B),
280
278
  []
281
279
  )
282
280
  }), d = a({
@@ -308,13 +306,13 @@ const p = {
308
306
  ...d.entries,
309
307
  type: u("remove"),
310
308
  /** Strings or patterns to remove */
311
- targets: n(t())
309
+ targets: c(t())
312
310
  }), G = a({
313
311
  ...d.entries,
314
312
  type: u("custom"),
315
313
  /** Custom processor function */
316
314
  processor: k(
317
- (c) => typeof c == "function",
315
+ (n) => typeof n == "function",
318
316
  "processor must be a function"
319
317
  )
320
318
  }), V = I("type", [
@@ -324,7 +322,7 @@ const p = {
324
322
  G
325
323
  ]), z = a({
326
324
  /** Custom compiler rules to apply */
327
- customRules: e(n(V), []),
325
+ customRules: e(c(V), []),
328
326
  /** Skip default compiler rules */
329
327
  ignoreDefaultRules: e(o(), !1)
330
328
  }), W = a({
@@ -334,7 +332,7 @@ const p = {
334
332
  */
335
333
  externalValidation: e(
336
334
  k(
337
- (c) => typeof c == "function",
335
+ (n) => typeof n == "function",
338
336
  "externalValidation must be a function"
339
337
  )
340
338
  )
@@ -368,8 +366,8 @@ export {
368
366
  B as CustomBlockTypeSchema,
369
367
  G as CustomRuleSchema,
370
368
  w as DefaultBlockTypeSchema,
371
- v as DynamicContentListSchema,
372
- f as DynamicContentNodeSchema,
369
+ N as DynamicContentListSchema,
370
+ S as DynamicContentNodeSchema,
373
371
  M as DynamicContentSchema,
374
372
  O as EditorSchema,
375
373
  D as EmailHeaderSchema,
@@ -377,14 +375,14 @@ export {
377
375
  U as FeaturesSchema,
378
376
  K as GuidoConfigSchema,
379
377
  A as IdentitySchema,
380
- N as LegacyRecommendationConfigSchema,
378
+ P as LegacyRecommendationConfigSchema,
381
379
  p as MessageType,
382
380
  E as PartnerSchema,
383
381
  l as ProductType,
384
382
  _ as RegexRuleSchema,
385
383
  q as RemoveRuleSchema,
386
384
  H as ReplaceRuleSchema,
387
- P as TemplateMigrationSchema,
385
+ v as TemplateMigrationSchema,
388
386
  x as TemplateSchema,
389
387
  F as UISchema
390
388
  };
@@ -1,18 +1,18 @@
1
1
  import o from "./Guido.vue2.js";
2
2
  /* empty css */
3
3
  import i from "../_virtual/_plugin-vue2_normalizer.js";
4
- var s = function() {
4
+ var t = function() {
5
5
  var a = this, r = a._self._c, e = a._self._setupProxy;
6
- return r("div", { ref: "wrapperRef", staticClass: "guido-editor__wrapper", class: { "guido-editor__no-header": e.noHeader } }, [r(e.HeaderWrapper, { ref: "headerWrapperRef" }), r(e.AutoSaveController), e.editorStore.isPreviewModeOpen ? r(e.PreviewContainer) : a._e(), r("div", { directives: [{ name: "show", rawName: "v-show", value: !e.previewStore.isLoaded, expression: "!previewStore.isLoaded" }], staticClass: "guido-editor__container", class: { "guido-editor__no-header": e.noHeader }, attrs: { id: "guido-editor" } }), r(e.Toaster), r(e.AuthErrorModal), r(e.FilterSelectionDrawer), e.isRrsEnabled || e.hasAssignedStrategy ? r(e.AssignStrategyDrawer) : a._e(), e.isRrsEnabled || e.hasAssignedStrategy ? r(e.RemoveStrategyModal) : a._e(), e.isRrsEnabled ? r(e.LegacyStrategyUpdatedModal) : a._e(), e.isLegacyUnsubscribeConversionEnabled ? r(e.LegacyUnsubscribeConvertedModal) : a._e(), r(e.SaveAsTemplateDrawer), e.isSaveValidationEnabled ? r(e.ValidationErrorDrawer) : a._e(), e.isTestPartner() ? a._e() : r(e.OnboardingWrapper, { on: { "onboarding-finished": function(_) {
6
+ return r("div", { ref: "wrapperRef", staticClass: "guido-editor__wrapper", class: { "guido-editor__no-header": e.noHeader } }, [r(e.HeaderWrapper, { ref: "headerWrapperRef" }), r(e.AutoSaveController), e.editorStore.isPreviewModeOpen ? r(e.PreviewContainer) : a._e(), r("div", { directives: [{ name: "show", rawName: "v-show", value: !e.previewStore.isLoaded, expression: "!previewStore.isLoaded" }], staticClass: "guido-editor__container", class: { "guido-editor__no-header": e.noHeader }, attrs: { id: "guido-editor" } }), r(e.Toaster), r(e.AuthErrorModal), r(e.FilterSelectionDrawer), e.isRrsEnabled || e.hasAssignedStrategy ? r(e.AssignStrategyDrawer) : a._e(), e.isRrsEnabled || e.hasAssignedStrategy ? r(e.RemoveStrategyModal) : a._e(), e.isRrsEnabled ? r(e.LegacyStrategyUpdatedModal) : a._e(), r(e.SaveAsTemplateDrawer), e.isSaveValidationEnabled ? r(e.ValidationErrorDrawer) : a._e(), e.isTestPartner() ? a._e() : r(e.OnboardingWrapper, { on: { "onboarding-finished": function(_) {
7
7
  return e.emit("onboarding:finished");
8
8
  } } }), r(e.UnsubscribeWrapper), r(e.LoadingWrapper)], 1);
9
- }, t = [], n = /* @__PURE__ */ i(
9
+ }, s = [], n = /* @__PURE__ */ i(
10
10
  o,
11
- s,
12
11
  t,
12
+ s,
13
13
  !1,
14
14
  null,
15
- "6cdd5182"
15
+ "f2154cb6"
16
16
  );
17
17
  const v = n.exports;
18
18
  export {
@@ -1,183 +1,189 @@
1
- import { defineComponent as de, defineAsyncComponent as c, ref as W, computed as l, watch as G, onMounted as me, onUnmounted as le } from "vue";
1
+ import { defineComponent as de, defineAsyncComponent as l, ref as W, computed as f, watch as G, onMounted as me, onUnmounted as le } from "vue";
2
2
  import { useCortexBlueprintBridge as ue } from "../composables/useCortexBlueprintBridge.js";
3
3
  import { useEditorLock as pe } from "../composables/useEditorLock.js";
4
- import { provideGuidoActions as fe } from "../composables/useGuidoActions.js";
5
- import { useGuidoStateBridge as ye } from "../composables/useGuidoStateBridge.js";
6
- import { usePartner as ge } from "../composables/usePartner.js";
7
- import { useSaveValidationRollout as be } from "../composables/useSaveValidationRollout.js";
8
- import { useStripo as ve } from "../composables/useStripo.js";
9
- import { useTimerClone as Se } from "../composables/useTimerClone.js";
10
- import { migrate as V } from "../config/migrator/index.js";
11
- import { ModuleFolderDefaults as $ } from "../enums/defaults.js";
12
- import { RIBBON_SELECTOR as he } from "../enums/onboarding.js";
13
- import { useRecommendationExtensionStore as z, disposeStrategyPageReturnListeners as Ee } from "../extensions/Blocks/Recommendation/store/recommendation.js";
14
- import { disposeUnsubscribeListeners as we } from "../extensions/Blocks/Unsubscribe/block.js";
15
- import Ce from "./organisms/AutoSaveController.vue.js";
16
- import De from "./organisms/base/AuthErrorModal.vue.js";
17
- import ke from "./organisms/base/Toaster.vue.js";
18
- import Fe from "./organisms/extensions/recommendation/FilterSelectionDrawer.vue.js";
19
- import Le from "./organisms/header/HeaderWrapper.vue.js";
20
- import Re from "./organisms/LoadingWrapper.vue.js";
21
- import Me from "./organisms/save-as-template/SaveAsTemplateDrawer.vue.js";
4
+ import { startEditorOpenMetrics as fe } from "../composables/useEditorOpenMetrics.js";
5
+ import { provideGuidoActions as ye } from "../composables/useGuidoActions.js";
6
+ import { useGuidoStateBridge as ge } from "../composables/useGuidoStateBridge.js";
7
+ import { usePartner as ve } from "../composables/usePartner.js";
8
+ import { useSaveValidationRollout as Se } from "../composables/useSaveValidationRollout.js";
9
+ import { useStripo as be } from "../composables/useStripo.js";
10
+ import { useTimerClone as he } from "../composables/useTimerClone.js";
11
+ import { migrate as Ee } from "../config/migrator/index.js";
12
+ import { ModuleFolderDefaults as H } from "../enums/defaults.js";
13
+ import { RIBBON_SELECTOR as we } from "../enums/onboarding.js";
14
+ import { useRecommendationExtensionStore as V, disposeStrategyPageReturnListeners as ke } from "../extensions/Blocks/Recommendation/store/recommendation.js";
15
+ import { disposeUnsubscribeListeners as Ce } from "../extensions/Blocks/Unsubscribe/block.js";
16
+ import De from "./organisms/AutoSaveController.vue.js";
17
+ import Ie from "./organisms/base/AuthErrorModal.vue.js";
18
+ import Fe from "./organisms/base/Toaster.vue.js";
19
+ import Me from "./organisms/extensions/recommendation/FilterSelectionDrawer.vue.js";
20
+ import Re from "./organisms/header/HeaderWrapper.vue.js";
21
+ import Te from "./organisms/LoadingWrapper.vue.js";
22
+ import Le from "./organisms/save-as-template/SaveAsTemplateDrawer.vue.js";
22
23
  import Ue from "./organisms/unsubscribe/UnsubscribeWrapper.vue.js";
23
- import Te from "./organisms/validation/ValidationErrorDrawer.vue.js";
24
- import { useStripoApi as Ie } from "../services/stripoApi.js";
24
+ import Ne from "./organisms/validation/ValidationErrorDrawer.vue.js";
25
+ import { useStripoApi as _e } from "../services/stripoApi.js";
25
26
  import { useConfigStore as Ae } from "../stores/config.js";
26
27
  import { useDynamicContentStore as Be } from "../stores/dynamic-content.js";
27
- import { useEditorStore as E } from "../stores/editor.js";
28
- import { usePreviewStore as Ne } from "../stores/preview.js";
28
+ import { useEditorStore as w } from "../stores/editor.js";
29
+ import { usePreviewStore as Oe } from "../stores/preview.js";
29
30
  import { useSaveValidationStore as Pe } from "../stores/save-validation.js";
30
- import { useTemplateStore as _e } from "../stores/template.js";
31
- import { useUnsubscribeStore as Oe } from "../stores/unsubscribe.js";
32
- import { readTrackFloor as H } from "../utils/linkTrackingIds.js";
33
- const vo = /* @__PURE__ */ de({
31
+ import { useTemplateStore as xe } from "../stores/template.js";
32
+ import { useUnsubscribeStore as We } from "../stores/unsubscribe.js";
33
+ import { readTrackFloor as $ } from "../utils/linkTrackingIds.js";
34
+ const ht = /* @__PURE__ */ de({
34
35
  __name: "Guido",
35
36
  props: {
36
37
  config: null,
37
38
  ready: { type: Boolean, default: !0 }
38
39
  },
39
40
  emits: ["dynamic-content:open", "back", "save:start", "save:complete", "on-change", "ready", "onboarding:finished", "test-email:click"],
40
- setup(q, { expose: K, emit: r }) {
41
- const a = q, j = c(
41
+ setup(z, { expose: q, emit: a }) {
42
+ const s = z, n = fe(), K = l(
42
43
  () => import("./organisms/email-preview/PreviewContainer.vue.js")
43
- ), J = c(
44
+ ), j = l(
44
45
  () => import("./organisms/onboarding/OnboardingWrapper.vue.js")
45
- ), Q = c(
46
+ ), J = l(
46
47
  () => import("./organisms/extensions/recommendation/AssignStrategyDrawer.vue.js")
47
- ), X = c(
48
+ ), Q = l(
48
49
  () => import("./organisms/extensions/recommendation/RemoveStrategyModal.vue.js")
49
- ), Y = c(
50
+ ), X = l(
50
51
  () => import("./organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.js")
51
- ), Z = c(
52
- () => import("./organisms/unsubscribe/LegacyUnsubscribeConvertedModal.vue.js")
53
- ), w = W(), f = W(), y = Be(), C = Oe(), t = Ae();
54
- a.ready && t.init(a.config);
55
- const d = E(), ee = Ne(), u = l(() => d.hasChanges), { isTestPartner: oe } = ge(), { isEnabled: te, loadRollout: D } = be(), k = () => {
56
- var o;
57
- return (o = w.value) == null ? void 0 : o.handleSave(!0);
58
- }, F = (o) => {
59
- d.loadingStatus = o;
52
+ ), k = W(), y = W(), g = Be(), C = We(), o = Ae();
53
+ s.ready && o.init(s.config);
54
+ const d = w(), Y = Oe(), u = f(() => d.hasChanges), { isTestPartner: Z } = ve(), { isEnabled: ee, loadRollout: D } = Se(), I = () => {
55
+ var t;
56
+ return (t = k.value) == null ? void 0 : t.handleSave(!0);
57
+ }, F = (t) => {
58
+ d.loadingStatus = t;
60
59
  };
61
- ue(), ye();
62
- const g = () => {
63
- var o, e;
60
+ ue(), ge();
61
+ const v = () => {
62
+ var t, e;
64
63
  return {
65
- emailId: t.templateId,
66
- userId: t.userId,
67
- username: t.username,
68
- partnerName: t.partnerName,
69
- savedModulesFolderName: ((o = t.editor) == null ? void 0 : o.savedModulesFolderName) || $.SAVED_MODULES,
70
- defaultModulesFolderName: ((e = t.editor) == null ? void 0 : e.defaultModulesFolderName) || $.DEFAULT_MODULES
64
+ emailId: o.templateId,
65
+ userId: o.userId,
66
+ username: o.username,
67
+ partnerName: o.partnerName,
68
+ savedModulesFolderName: ((t = o.editor) == null ? void 0 : t.savedModulesFolderName) || H.SAVED_MODULES,
69
+ defaultModulesFolderName: ((e = o.editor) == null ? void 0 : e.defaultModulesFolderName) || H.DEFAULT_MODULES
71
70
  };
72
- }, { initPlugin: L, preloadRuntime: R } = ve(), { runExclusive: M, beginMount: U, isCurrentMount: b } = pe();
71
+ }, { initPlugin: M, preloadRuntime: R } = be(n), { runExclusive: T, beginMount: L, isCurrentMount: S } = pe();
73
72
  let p = 0;
74
- const { getDefaultTemplate: T } = Ie(), { cloneTimersOnSave: I, hasTimerBlocks: A } = Se(), ne = l(() => {
75
- var o;
76
- return !((o = t.ui) != null && o.showHeader);
77
- }), re = l(() => t.isFeatureEnabled("reusableRecommendationStrategy")), se = l(
78
- () => t.isFeatureEnabled("legacyUnsubscribeConversion")
79
- ), ae = l(
80
- () => !!z().recommendationConfigs.strategyId
73
+ const { getDefaultTemplate: U } = _e(), { cloneTimersOnSave: N, hasTimerBlocks: _ } = he(), te = f(() => {
74
+ var t;
75
+ return !((t = o.ui) != null && t.showHeader);
76
+ }), oe = f(() => o.isFeatureEnabled("reusableRecommendationStrategy")), re = f(
77
+ () => !!V().recommendationConfigs.strategyId
81
78
  );
82
- fe({
79
+ ye({
83
80
  onBack: () => {
84
- console.debug("guido:back"), r("back");
81
+ console.debug("guido:back"), a("back");
85
82
  },
86
83
  onSaveStart: () => {
87
- console.debug("guido:save:start"), r("save:start");
84
+ console.debug("guido:save:start"), a("save:start");
88
85
  },
89
- onSaveComplete: (o) => {
90
- const e = { ...o, metadata: g() };
91
- console.debug("guido:save:complete", e), r("save:complete", e);
86
+ onSaveComplete: (t) => {
87
+ const e = { ...t, metadata: v() };
88
+ console.debug("guido:save:complete", e), a("save:complete", e);
92
89
  },
93
90
  onTestEmailClick: () => {
94
- console.debug("guido:test-email:click"), r("test-email:click");
91
+ console.debug("guido:test-email:click"), a("test-email:click");
95
92
  }
96
93
  });
97
- const B = (o) => {
98
- console.debug("dynamic-content:close", o), y.setSelectedDynamicContent(o), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: o }));
99
- }, N = () => {
94
+ const A = (t) => {
95
+ console.debug("dynamic-content:close", t), g.setSelectedDynamicContent(t), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: t }));
96
+ }, B = () => {
100
97
  console.debug("dynamic-content:close", "Without Data"), document.dispatchEvent(new CustomEvent("dynamic-content:close", { detail: { text: "", value: "" } }));
101
98
  };
102
99
  G(() => u.value, () => {
103
- r("on-change", u.value);
100
+ a("on-change", u.value);
104
101
  });
105
- const v = (o) => {
106
- const e = o, { attribute: s, position: m } = e.detail;
107
- console.debug("dynamic-content:open", e.detail), r("dynamic-content:open", s, m);
102
+ const b = (t) => {
103
+ const e = t, { attribute: i, position: m } = e.detail;
104
+ console.debug("dynamic-content:open", e.detail), a("dynamic-content:open", i, m);
108
105
  };
109
- let i = null;
110
- const S = () => {
106
+ let c = null;
107
+ const h = () => {
111
108
  var e;
112
- const o = document.querySelector(he);
113
- (e = f.value) == null || e.style.setProperty("--ribbon-offset", `${(o == null ? void 0 : o.offsetHeight) ?? 0}px`);
114
- }, h = async () => {
115
- var o;
109
+ const t = document.querySelector(we);
110
+ (e = y.value) == null || e.style.setProperty("--ribbon-offset", `${(t == null ? void 0 : t.offsetHeight) ?? 0}px`);
111
+ }, E = async () => {
112
+ var t;
113
+ n.mark("host_ready");
116
114
  try {
117
- t.initialized || t.init(a.config), d.templateId = t.templateId;
118
- const e = t.template, s = (e == null ? void 0 : e.html) || "", m = (e == null ? void 0 : e.css) || "", P = (e == null ? void 0 : e.preselectedDynamicContent) || [];
115
+ o.initialized || o.init(s.config), d.templateId = o.templateId, n.setContext({
116
+ partnerName: o.partnerName,
117
+ productType: o.productType,
118
+ templateId: o.templateId,
119
+ variationId: o.variationId
120
+ });
121
+ const e = o.template, i = (e == null ? void 0 : e.html) || "", m = (e == null ? void 0 : e.css) || "", O = (e == null ? void 0 : e.preselectedDynamicContent) || [];
119
122
  C.selectedUnsubscribePages = (e == null ? void 0 : e.selectedUnsubscribePages) || [];
120
- const _ = ((o = e == null ? void 0 : e.migration) == null ? void 0 : o.recommendationConfigs) ?? {}, O = t.isFeatureEnabled("linkTrackingIds"), x = {
121
- partnerName: t.partnerName,
123
+ const ne = ((t = e == null ? void 0 : e.migration) == null ? void 0 : t.recommendationConfigs) ?? {}, P = o.isFeatureEnabled("linkTrackingIds"), ae = {
124
+ partnerName: o.partnerName,
122
125
  campaignUrls: e == null ? void 0 : e.recommendationCampaignUrls,
123
- rrsEnabled: t.isFeatureEnabled("reusableRecommendationStrategy")
124
- };
125
- let n = {
126
- html: s && await V(s, _, x),
126
+ rrsEnabled: o.isFeatureEnabled("reusableRecommendationStrategy")
127
+ }, x = (ce) => n.timed(
128
+ "migration",
129
+ () => Ee(ce, ne, ae)
130
+ );
131
+ let r = {
132
+ html: i && await x(i),
127
133
  css: m
128
134
  };
129
- n.html || (n = await T(), n.html = await V(n.html, _, x));
130
- const ie = O ? H(n.html, (e == null ? void 0 : e.trackIdCounter) || 0) : 0;
131
- A(n.html) && (n.html = await I(n.html)), O && (d.trackIdSessionFloor = Math.max(ie, H(n.html)));
132
- const ce = {
133
- preselectedDynamicContentList: P,
135
+ r.html || (r = await n.timed("default_template", () => U()), r.html = await x(r.html));
136
+ const ie = P ? $(r.html, (e == null ? void 0 : e.trackIdCounter) || 0) : 0;
137
+ _(r.html) && (r.html = await n.timed("timer_clone", () => N(r.html))), P && (d.trackIdSessionFloor = Math.max(ie, $(r.html)));
138
+ const se = {
139
+ preselectedDynamicContentList: O,
134
140
  onReady: () => {
135
- console.debug("guido:ready"), r("ready");
141
+ console.debug("guido:ready"), a("ready");
136
142
  }
137
143
  };
138
- p = U(), await L(n, g(), ce), y.selectedDynamicContentList = P;
144
+ p = L(), await M(r, v(), se), g.selectedDynamicContentList = O;
139
145
  } catch (e) {
140
- console.error("Failed to initialize Stripo editor:", e);
146
+ console.error("Failed to initialize Stripo editor:", e), n.markFailed();
141
147
  }
142
148
  };
143
149
  return me(async () => {
144
150
  var e;
145
- console.debug("Guido says happy coding 🎉"), console.debug("🚗 Ka-Chow"), z().$reset(), E().$reset(), _e().$reset(), Pe().$reset(), D(), S();
146
- const o = (e = f.value) == null ? void 0 : e.parentElement;
147
- if (o && (i = new ResizeObserver(S), i.observe(o)), R(), a.ready)
148
- await h();
151
+ console.debug("Guido says happy coding 🎉"), console.debug("🚗 Ka-Chow"), V().$reset(), w().$reset(), xe().$reset(), Pe().$reset(), D(), h();
152
+ const t = (e = y.value) == null ? void 0 : e.parentElement;
153
+ if (t && (c = new ResizeObserver(h), c.observe(t)), R(), s.ready)
154
+ await E();
149
155
  else {
150
- const s = G(() => a.ready, (m) => {
151
- m && (s(), h());
156
+ const i = G(() => s.ready, (m) => {
157
+ m && (i(), E());
152
158
  });
153
159
  }
154
- document.addEventListener("dynamic-content:open", v);
160
+ document.addEventListener("dynamic-content:open", b);
155
161
  }), le(() => {
156
- if (we(), Ee(), i == null || i.disconnect(), document.removeEventListener("dynamic-content:open", v), b(p))
162
+ if (Ce(), ke(), n.dispose(), c == null || c.disconnect(), document.removeEventListener("dynamic-content:open", b), S(p))
157
163
  try {
158
- E().isStripoInitialized = !1;
159
- } catch (o) {
160
- console.debug("Failed to close the editor readiness gate on unmount", o);
164
+ w().isStripoInitialized = !1;
165
+ } catch (t) {
166
+ console.debug("Failed to close the editor readiness gate on unmount", t);
161
167
  }
162
- M(async () => {
163
- if (b(p))
168
+ T(async () => {
169
+ if (S(p))
164
170
  try {
165
171
  window.UIEditor.removeEditor();
166
172
  } catch {
167
173
  console.debug("Failed to remove Stripo editor: No editor found");
168
174
  }
169
- }), t.reset();
170
- }), K({
175
+ }), o.reset();
176
+ }), q({
171
177
  dynamicContent: {
172
- insert: B,
173
- close: N
178
+ insert: A,
179
+ close: B
174
180
  },
175
181
  hasChanges: u,
176
- saveSilent: k,
182
+ saveSilent: I,
177
183
  setLoading: F
178
- }), { __sfc: !0, PreviewContainer: j, OnboardingWrapper: J, AssignStrategyDrawer: Q, RemoveStrategyModal: X, LegacyStrategyUpdatedModal: Y, LegacyUnsubscribeConvertedModal: Z, headerWrapperRef: w, wrapperRef: f, dynamicContentStore: y, unsubscribeStore: C, props: a, configStore: t, editorStore: d, previewStore: ee, hasChanges: u, isTestPartner: oe, isSaveValidationEnabled: te, loadRollout: D, saveSilent: k, setLoading: F, emit: r, buildMetadata: g, initPlugin: L, preloadRuntime: R, runExclusive: M, beginMount: U, isCurrentMount: b, mountGeneration: p, getDefaultTemplate: T, cloneTimersOnSave: I, hasTimerBlocks: A, noHeader: ne, isRrsEnabled: re, isLegacyUnsubscribeConversionEnabled: se, hasAssignedStrategy: ae, insertDynamicContent: B, closeDynamicContent: N, handleDynamicContentOpen: v, ribbonObserver: i, updateRibbonOffset: S, startEditor: h, AutoSaveController: Ce, AuthErrorModal: De, Toaster: ke, FilterSelectionDrawer: Fe, HeaderWrapper: Le, LoadingWrapper: Re, SaveAsTemplateDrawer: Me, UnsubscribeWrapper: Ue, ValidationErrorDrawer: Te };
184
+ }), { __sfc: !0, openMetrics: n, PreviewContainer: K, OnboardingWrapper: j, AssignStrategyDrawer: J, RemoveStrategyModal: Q, LegacyStrategyUpdatedModal: X, headerWrapperRef: k, wrapperRef: y, dynamicContentStore: g, unsubscribeStore: C, props: s, configStore: o, editorStore: d, previewStore: Y, hasChanges: u, isTestPartner: Z, isSaveValidationEnabled: ee, loadRollout: D, saveSilent: I, setLoading: F, emit: a, buildMetadata: v, initPlugin: M, preloadRuntime: R, runExclusive: T, beginMount: L, isCurrentMount: S, mountGeneration: p, getDefaultTemplate: U, cloneTimersOnSave: N, hasTimerBlocks: _, noHeader: te, isRrsEnabled: oe, hasAssignedStrategy: re, insertDynamicContent: A, closeDynamicContent: B, handleDynamicContentOpen: b, ribbonObserver: c, updateRibbonOffset: h, startEditor: E, AutoSaveController: De, AuthErrorModal: Ie, Toaster: Fe, FilterSelectionDrawer: Me, HeaderWrapper: Re, LoadingWrapper: Te, SaveAsTemplateDrawer: Le, UnsubscribeWrapper: Ue, ValidationErrorDrawer: Ne };
179
185
  }
180
186
  });
181
187
  export {
182
- vo as default
188
+ ht as default
183
189
  };