@useinsider/guido 3.19.0 → 3.20.0-beta.0849ec7

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 (148) hide show
  1. package/README.md +22 -3
  2. package/dist/@types/config/schemas.js +76 -53
  3. package/dist/components/Guido.vue.js +4 -4
  4. package/dist/components/Guido.vue2.js +102 -86
  5. package/dist/components/organisms/AutoSaveController.vue2.js +9 -8
  6. package/dist/components/organisms/base/AuthErrorModal.vue.js +18 -0
  7. package/dist/components/organisms/base/AuthErrorModal.vue2.js +42 -0
  8. package/dist/components/organisms/base/Toaster.vue2.js +13 -12
  9. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +13 -11
  10. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +78 -57
  11. package/dist/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.js +18 -0
  12. package/dist/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue2.js +25 -0
  13. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +28 -42
  14. package/dist/components/organisms/header/EditorActions.vue.js +5 -5
  15. package/dist/components/organisms/header/EditorActions.vue2.js +90 -57
  16. package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
  17. package/dist/components/organisms/header/LeftSlot.vue2.js +16 -12
  18. package/dist/components/organisms/onboarding/OnboardingWrapper.vue2.js +28 -24
  19. package/dist/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue.js +21 -0
  20. package/dist/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue2.js +46 -0
  21. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.js +21 -0
  22. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue2.js +47 -0
  23. package/dist/components/organisms/validation/ValidationErrorDrawer.vue.js +20 -0
  24. package/dist/components/organisms/validation/ValidationErrorDrawer.vue2.js +49 -0
  25. package/dist/components/wrappers/WpDrawer.vue.js +9 -7
  26. package/dist/components/wrappers/WpDrawer.vue2.js +1 -1
  27. package/dist/components/wrappers/WpModal.vue.js +1 -1
  28. package/dist/components/wrappers/WpModal.vue2.js +4 -3
  29. package/dist/composables/useActionsApi.js +52 -47
  30. package/dist/composables/useAuthError.js +52 -0
  31. package/dist/composables/useAutoSave.js +11 -11
  32. package/dist/composables/useCodeEditorApi.js +23 -9
  33. package/dist/composables/useCortexBlueprintBridge.js +122 -54
  34. package/dist/composables/useCustomInterfaceAppearance.js +65 -51
  35. package/dist/composables/useEmailTemplateApplier.js +111 -50
  36. package/dist/composables/useHtmlCompiler.js +37 -26
  37. package/dist/composables/useHtmlValidator.js +89 -82
  38. package/dist/composables/useHttp.js +64 -54
  39. package/dist/composables/useLegacyStrategyConversion.js +65 -0
  40. package/dist/composables/useRecommendation.js +40 -35
  41. package/dist/composables/useSave.js +90 -45
  42. package/dist/composables/useSaveValidation.js +282 -0
  43. package/dist/composables/useSaveValidationRollout.js +9 -0
  44. package/dist/composables/useStripo.js +43 -39
  45. package/dist/composables/useToaster.js +18 -22
  46. package/dist/composables/useTranslations.js +3 -2
  47. package/dist/composables/useVersionHistoryApi.js +33 -24
  48. package/dist/composables/validators/useCouponBlockValidator.js +24 -21
  49. package/dist/composables/validators/useLiquidValidator.js +15 -15
  50. package/dist/composables/validators/useUnsubscribeBlockValidator.js +34 -27
  51. package/dist/config/migrator/index.js +14 -13
  52. package/dist/config/migrator/itemsBlockMigrator.js +236 -248
  53. package/dist/config/migrator/recommendationMigrator.js +28 -21
  54. package/dist/config/migrator/recommendationPartnerMigrator.js +56 -0
  55. package/dist/enums/extensions/recommendationBlock.js +51 -34
  56. package/dist/enums/save-validation.js +4 -0
  57. package/dist/extensions/Blocks/Items/constants/cardLayout.js +20 -0
  58. package/dist/extensions/Blocks/Items/controls/name/trimming.js +18 -17
  59. package/dist/extensions/Blocks/Items/controls/settingsControl.js +114 -105
  60. package/dist/extensions/Blocks/Items/enums/productEnums.js +14 -9
  61. package/dist/extensions/Blocks/Items/layouts/horizontal.html.js +11 -9
  62. package/dist/extensions/Blocks/Items/template.js +219 -204
  63. package/dist/extensions/Blocks/Recommendation/block.js +65 -45
  64. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +21 -20
  65. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +103 -90
  66. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +150 -52
  67. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +74 -74
  68. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +274 -92
  69. package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.js +42 -0
  70. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +26 -16
  71. package/dist/extensions/Blocks/Recommendation/utils/partnerCustomizations.js +3 -1
  72. package/dist/extensions/Blocks/Recommendation/utils/partnerScope.js +25 -0
  73. package/dist/extensions/Blocks/Recommendation/utils/productIds.js +5 -3
  74. package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +24 -0
  75. package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +21 -12
  76. package/dist/guido.css +1 -1
  77. package/dist/services/recommendationApi.js +46 -37
  78. package/dist/src/@types/config/schemas.d.ts +36 -0
  79. package/dist/src/@types/save-validation.d.ts +19 -0
  80. package/dist/src/components/Guido.vue.d.ts +17 -1
  81. package/dist/src/components/organisms/base/AuthErrorModal.vue.d.ts +2 -0
  82. package/dist/src/components/organisms/extensions/recommendation/LegacyStrategyUpdatedModal.vue.d.ts +2 -0
  83. package/dist/src/components/organisms/header/EditorActions.vue.d.ts +17 -1
  84. package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +17 -1
  85. package/dist/src/components/organisms/header/RightSlot.vue.d.ts +17 -1
  86. package/dist/src/components/organisms/onboarding/RecommendationLegacyStrategyOnboarding.vue.d.ts +2 -0
  87. package/dist/src/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.d.ts +2 -0
  88. package/dist/src/components/organisms/validation/ValidationErrorDrawer.vue.d.ts +2 -0
  89. package/dist/src/components/wrappers/WpDrawer.vue.d.ts +4 -3
  90. package/dist/src/components/wrappers/WpModal.vue.d.ts +5 -1
  91. package/dist/src/composables/useAuthError.d.ts +12 -0
  92. package/dist/src/composables/useConfig.d.ts +8 -0
  93. package/dist/src/composables/useCortexBlueprintBridge.d.ts +2 -3
  94. package/dist/src/composables/useEmailTemplateApplier.d.ts +18 -5
  95. package/dist/src/composables/useGuidoActions.d.ts +2 -0
  96. package/dist/src/composables/useHtmlValidator.d.ts +21 -0
  97. package/dist/src/composables/useHttp.d.ts +2 -0
  98. package/dist/src/composables/useLegacyStrategyConversion.d.ts +3 -0
  99. package/dist/src/composables/useSave.d.ts +6 -1
  100. package/dist/src/composables/useSaveValidation.d.ts +6 -0
  101. package/dist/src/composables/useSaveValidationRollout.d.ts +3 -0
  102. package/dist/src/composables/validators/useCouponBlockValidator.d.ts +3 -0
  103. package/dist/src/composables/validators/useUnsubscribeBlockValidator.d.ts +10 -0
  104. package/dist/src/config/migrator/index.d.ts +2 -1
  105. package/dist/src/config/migrator/recommendationPartnerMigrator.d.ts +19 -0
  106. package/dist/src/enums/extensions/recommendationBlock.d.ts +7 -1
  107. package/dist/src/enums/save-validation.d.ts +27 -0
  108. package/dist/src/extensions/Blocks/Items/constants/cardLayout.d.ts +44 -0
  109. package/dist/src/extensions/Blocks/Items/enums/productEnums.d.ts +3 -0
  110. package/dist/src/extensions/Blocks/Items/template.d.ts +19 -0
  111. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +10 -0
  112. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +1 -0
  113. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  114. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +2 -0
  115. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +10 -0
  116. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +7 -2
  117. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +162 -1
  118. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +6 -0
  119. package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.d.ts +32 -0
  120. package/dist/src/extensions/Blocks/Recommendation/utils/partnerScope.d.ts +33 -0
  121. package/dist/src/extensions/Blocks/Recommendation/utils/productIds.d.ts +2 -0
  122. package/dist/src/extensions/Blocks/Recommendation/utils/strategyCommit.d.ts +14 -0
  123. package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +4 -0
  124. package/dist/src/mock/cortexChatStore.d.ts +12 -0
  125. package/dist/src/services/recommendationApi.d.ts +2 -1
  126. package/dist/src/stores/config.d.ts +374 -0
  127. package/dist/src/stores/guido-email-editor.d.ts +20 -10
  128. package/dist/src/stores/onboarding.d.ts +812 -10
  129. package/dist/src/stores/recommendation.d.ts +5 -0
  130. package/dist/src/stores/save-validation.d.ts +22 -0
  131. package/dist/src/utils/dateUtil.d.ts +10 -0
  132. package/dist/src/utils/genericUtil.d.ts +3 -0
  133. package/dist/src/utils/stripoEditorApi.d.ts +4 -0
  134. package/dist/src/utils/templatePreparation.d.ts +30 -0
  135. package/dist/static/assets/icons/filled-arrow-rising.svg.js +5 -0
  136. package/dist/static/assets/icons/line-info.svg.js +5 -0
  137. package/dist/static/styles/components/recommendation-strategy.css.js +113 -9
  138. package/dist/static/styles/components/skeleton.css.js +23 -0
  139. package/dist/static/styles/components/version-history.css.js +2 -6
  140. package/dist/stores/config.js +55 -24
  141. package/dist/stores/guido-email-editor.js +3 -1
  142. package/dist/stores/onboarding.js +50 -36
  143. package/dist/stores/save-validation.js +30 -0
  144. package/dist/stores/unsubscribe.js +3 -3
  145. package/dist/utils/pairProductVariables.js +71 -71
  146. package/dist/utils/stripoEditorApi.js +11 -0
  147. package/dist/utils/templatePreparation.js +54 -51
  148. package/package.json +2 -1
@@ -6,5 +6,10 @@ type RecommendationConfig = {
6
6
  interface StoreState {
7
7
  recommendationConfigs: RecommendationConfig[];
8
8
  }
9
+ /**
10
+ * @deprecated recommendationConfigs has no writer in src/, so the store is
11
+ * permanently empty and its only readers (useHtmlValidator.ts:496-497) are a
12
+ * no-op. Slated for deletion, see the SD-667788 dead-code ledger.
13
+ */
9
14
  export declare const useRecommendationStore: import("pinia").StoreDefinition<"guidoRecommendation", StoreState, {}, {}>;
10
15
  export {};
@@ -0,0 +1,22 @@
1
+ import type { SaveValidationError, SaveValidationIntent } from '@@/Types/save-validation';
2
+ interface SaveValidationState {
3
+ errors: SaveValidationError[];
4
+ isDrawerOpen: boolean;
5
+ intent: SaveValidationIntent | null;
6
+ }
7
+ export declare const useSaveValidationStore: import("pinia").StoreDefinition<"guidoSaveValidation", SaveValidationState, {
8
+ errorCount: (state: {
9
+ errors: {
10
+ rule: import("../enums/save-validation").SaveValidationRule;
11
+ message: string;
12
+ detail?: string | undefined;
13
+ type: import("../enums/toaster").ToasterTypeOptions;
14
+ }[];
15
+ isDrawerOpen: boolean;
16
+ intent: SaveValidationIntent | null;
17
+ } & import("pinia").PiniaCustomStateProperties<SaveValidationState>) => number;
18
+ }, {
19
+ open(errors: SaveValidationError[], intent: SaveValidationIntent): void;
20
+ close(): void;
21
+ }>;
22
+ export {};
@@ -3,12 +3,22 @@
3
3
  * en-US -> MM/DD/YYYY
4
4
  * en-GB -> DD/MM/YYYY
5
5
  * tr-TR -> DD.MM.YYYY
6
+ *
7
+ * The non-string branches below are unreachable: the only caller chain is
8
+ * formatShortDate -> AssignStrategyDrawer.vue:74, which passes a non-empty string.
9
+ * The function itself is live — do not delete it with them.
6
10
  */
7
11
  export declare const convertToDateObject: (date: string | number | Date | null | undefined) => Date;
8
12
  export declare const locale: () => string;
9
13
  export declare const localTz: string;
10
14
  export declare const timezone: () => string;
15
+ /**
16
+ * @deprecated No caller in src/ and not exported from library.ts. Slated for deletion, see the SD-667788 dead-code ledger.
17
+ */
11
18
  export declare const hour12: () => boolean;
19
+ /**
20
+ * @deprecated No caller in src/ and not exported from library.ts. Slated for deletion, see the SD-667788 dead-code ledger.
21
+ */
12
22
  export declare const dateFormat: () => string;
13
23
  /**
14
24
  * @example 04/22/2024
@@ -24,6 +24,9 @@ export declare const getCsrfToken: () => string;
24
24
  */
25
25
  export declare const getUrlParams: () => URLSearchParams;
26
26
  export declare const getUrlParam: (paramName: string, defaultValue?: string) => string;
27
+ /**
28
+ * @deprecated No caller in src/. Slated for deletion, see the SD-667788 dead-code ledger.
29
+ */
27
30
  export declare const replaceString: (string?: string, values?: Record<string, string | number>, isRemoveEmptyValues?: boolean) => string;
28
31
  /**
29
32
  * Narrows an unknown API value to a printable string; anything that is neither
@@ -0,0 +1,4 @@
1
+ import type { StripoEditorApi } from '@@/Types/stripo';
2
+ export declare const EDITOR_NOT_READY_MESSAGE = "The editor is not ready yet. Please wait for it to load and try again.";
3
+ export declare const findEditorApi: () => StripoEditorApi | undefined;
4
+ export declare const getEditorApi: () => StripoEditorApi;
@@ -15,6 +15,36 @@ import type { SavedTemplateDetails } from '@@/Types/stripo';
15
15
  * same source), so it is reliably present regardless of how the block was added.
16
16
  */
17
17
  export declare function getHtmlReferencedUnsubscribePages(html: string): number[];
18
+ /**
19
+ * Hydrates the recommendation extension store from the persisted `esd-ext-config`
20
+ * JSON blob on each `.recommendation-block-v2` element in the raw editor HTML.
21
+ *
22
+ * Why this runs before `compileHtml`:
23
+ * The HTML compiler's `prepareRecommendationBlocks` rule asks
24
+ * `useRecommendation.buildCampaignUrl(id)` to assemble each block's API URL
25
+ * from `blockStates[id].recommendationConfigs`. That Pinia entry is normally
26
+ * populated by `RecommendationBlockControl._syncNodeConfigToStore`, which
27
+ * only fires when the user *selects* the block. Saving without ever
28
+ * selecting a migrated block would otherwise build the URL from empty/
29
+ * default state and the campaign URL would not be saved.
30
+ *
31
+ * Why we read raw HTML, not compiled HTML:
32
+ * Stripo's `compileEmail()` strips editor-only attributes (`esd-*`) from the
33
+ * compiled output, so `esd-ext-config` is gone by the time the compiler
34
+ * pipeline sees the HTML. The raw HTML from `getTemplateData()` preserves
35
+ * the attribute as the migrator wrote it.
36
+ *
37
+ * Reference data pre-load:
38
+ * When the template has recommendation blocks, this also pre-loads the
39
+ * shared reference data (languages / currency list) so the save-time
40
+ * required-fields validator can check each block's locale and currency
41
+ * against the partner's real options. Best-effort — on a fetch failure the
42
+ * validator degrades to its empty-list guard (`requiredFields.ts`) instead
43
+ * of blocking the save or stranding the Save button.
44
+ */
45
+ declare function hydrateRecommendationStoreFromRawHtml(rawHtml: string): Promise<void>;
18
46
  export declare const useTemplatePreparation: () => {
19
47
  prepareTemplateDetails: () => Promise<Omit<SavedTemplateDetails, "metadata">>;
48
+ hydrateRecommendationStore: typeof hydrateRecommendationStoreFromRawHtml;
20
49
  };
50
+ export {};
@@ -0,0 +1,5 @@
1
+ const C = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12.9403 5.51003L17.6328 11.0273C17.8845 11.3769 18.0068 11.8382 17.9997 12.2963L18 12.3333C18 13.2538 17.4627 14 16.8 14H15V15C15 15.5523 14.5523 16 14 16H10C9.44772 16 9 15.5523 9 15V14H7.2C6.53726 14 6 13.2538 6 12.3333L6.00029 12.2963C5.9932 11.8382 6.11551 11.3769 6.36722 11.0273L11.0597 5.51003C11.3182 5.15101 11.6615 4.98153 12 5.00159C12.3386 4.98153 12.6818 5.15101 12.9403 5.51003Z"/><path d="M10 18C9.44772 18 9 18.4477 9 19C9 19.5523 9.44772 20 10 20H14C14.5523 20 15 19.5523 15 19C15 18.4477 14.5523 18 14 18H10Z"/></svg>
2
+ `;
3
+ export {
4
+ C as default
5
+ };
@@ -0,0 +1,5 @@
1
+ const C = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 4C14.1217 4 16.1566 4.84285 17.6569 6.34315C19.1571 7.84344 20 9.87827 20 12C20 14.1217 19.1571 16.1566 17.6569 17.6569C16.1566 19.1571 14.1217 20 12 20C9.87827 20 7.84344 19.1571 6.34315 17.6569C4.84285 16.1566 4 14.1217 4 12C4 9.87827 4.84285 7.84344 6.34315 6.34315C7.84344 4.84285 9.87827 4 12 4ZM12 5.6C10.3026 5.6 8.67475 6.27428 7.47452 7.47452C6.27428 8.67475 5.6 10.3026 5.6 12C5.6 13.6974 6.27428 15.3253 7.47452 16.5255C8.67475 17.7257 10.3026 18.4 12 18.4C13.6974 18.4 15.3253 17.7257 16.5255 16.5255C17.7257 15.3253 18.4 13.6974 18.4 12C18.4 10.3026 17.7257 8.67475 16.5255 7.47452C15.3253 6.27428 13.6974 5.6 12 5.6ZM11.496 10.448C11.928 10.448 12.264 10.552 12.496 10.768C12.736 10.976 12.848 11.248 12.848 11.584V11.688L12.824 11.944C12.816 12.064 12.8 12.176 12.776 12.28L12.736 12.432L12.288 14.024L12.248 14.152C12.1976 14.376 12.1629 14.6032 12.144 14.832C12.144 15.04 12.192 15.184 12.288 15.264C12.384 15.344 12.544 15.376 12.776 15.376C12.888 15.376 13.016 15.36 13.152 15.32L13.392 15.24L13.448 15.216L13.328 15.712L12.848 15.896L12.584 15.992L12.464 16.032C12.248 16.112 12 16.144 11.72 16.144C11.28 16.144 10.944 16.04 10.696 15.824C10.5803 15.7241 10.488 15.5998 10.4258 15.4602C10.3636 15.3205 10.3329 15.1689 10.336 15.016C10.3355 14.787 10.3624 14.5587 10.416 14.336L10.448 14.176L10.896 12.576L10.936 12.424L11 12.144C11.024 12.008 11.04 11.88 11.04 11.768C11.04 11.56 11 11.424 10.912 11.344C10.832 11.264 10.672 11.224 10.432 11.224C10.312 11.224 10.192 11.24 10.072 11.272L9.856 11.352L9.76 11.376L9.88 10.888L10.168 10.776C10.36 10.696 10.544 10.632 10.728 10.576C11 10.496 11.256 10.448 11.496 10.448ZM12.496 7.536C12.792 7.536 13.04 7.632 13.248 7.832C13.464 8.024 13.568 8.264 13.568 8.544C13.568 8.816 13.464 9.056 13.248 9.248C13.04 9.44 12.792 9.544 12.496 9.544C12.2 9.544 11.944 9.44 11.736 9.248C11.52 9.056 11.416 8.816 11.416 8.544C11.416 8.264 11.52 8.024 11.736 7.824C11.944 7.632 12.2 7.536 12.496 7.536Z"/></svg>
2
+ `;
3
+ export {
4
+ C as default
5
+ };
@@ -26,6 +26,49 @@ const n = `.strategy-control-header {
26
26
  text-decoration: underline;
27
27
  }
28
28
 
29
+ .strategy-control-notice-row {
30
+ padding: 0 16px 16px;
31
+ }
32
+
33
+ .strategy-control-notice {
34
+ display: flex;
35
+ gap: 8px;
36
+ align-items: center;
37
+ padding: 12px;
38
+ border: 1px solid var(--guido-color-border-onpage-message-info);
39
+ border-radius: 4px;
40
+ background-color: var(--guido-color-background-onpage-message-info);
41
+ }
42
+
43
+ .strategy-control-notice::before {
44
+ content: '';
45
+ flex: none;
46
+ width: 24px;
47
+ height: 24px;
48
+ background-color: var(--guido-color-border-onpage-message-info);
49
+ mask-image: var(--guido-icon-line-info);
50
+ mask-repeat: no-repeat;
51
+ mask-position: center;
52
+ mask-size: 24px 24px;
53
+ }
54
+
55
+ .strategy-control-notice--error {
56
+ border-color: var(--guido-color-border-onpage-message-error);
57
+ background-color: var(--guido-color-background-onpage-message-error);
58
+ }
59
+
60
+ .strategy-control-notice--error::before {
61
+ background-color: var(--guido-color-border-onpage-message-error);
62
+ }
63
+
64
+ .strategy-control-notice-text {
65
+ margin: 0;
66
+ padding: 4px 0;
67
+ color: var(--guido-color-neutral-700);
68
+ font-size: 13px;
69
+ line-height: 16px;
70
+ }
71
+
29
72
  .recommendation-controls-container .container.strategy-control-cta-row {
30
73
  grid-template-columns: repeat(2, minmax(0, 180px));
31
74
  justify-content: start;
@@ -49,11 +92,8 @@ const n = `.strategy-control-header {
49
92
  white-space: nowrap;
50
93
  }
51
94
 
52
- .strategy-control-cta.primary > .button:disabled,
53
- .strategy-control-cta.primary > .button.disabled {
54
- opacity: 1;
95
+ .strategy-control-cta.primary > .button {
55
96
  color: var(--guido-color-gray-800);
56
- cursor: default;
57
97
  }
58
98
 
59
99
  .strategy-control-name-band {
@@ -64,6 +104,14 @@ const n = `.strategy-control-header {
64
104
  background-color: var(--guido-color-gray-0);
65
105
  }
66
106
 
107
+ /* Figma gives the legacy band a 59px row: 17.5px above and below its 24px content. */
108
+ [data-strategy-legacy-state] .strategy-control-name-band {
109
+ gap: 8px;
110
+ justify-content: space-between;
111
+ min-height: auto;
112
+ padding: 17.5px 16px;
113
+ }
114
+
67
115
  .strategy-control-name {
68
116
  color: var(--guido-color-gray-800);
69
117
  font-size: 15px;
@@ -71,6 +119,39 @@ const n = `.strategy-control-header {
71
119
  line-height: 24px;
72
120
  }
73
121
 
122
+ /* Each skeleton mirrors the footprint of the element it stands in for, so retiring
123
+ the loading state does not shift the panel. */
124
+ .guido-skeleton--strategy-title {
125
+ width: 366px;
126
+ height: 38px;
127
+ }
128
+
129
+ .guido-skeleton--strategy-description {
130
+ width: 366px;
131
+ height: 48px;
132
+ }
133
+
134
+ .guido-skeleton--strategy-cta {
135
+ width: 175px;
136
+ height: 40px;
137
+ }
138
+
139
+ .guido-skeleton--strategy-name {
140
+ width: 398px;
141
+ height: 48px;
142
+ }
143
+
144
+ .strategy-control-skeleton-row {
145
+ display: flex;
146
+ gap: 16px;
147
+ padding: 0 16px 16px;
148
+ }
149
+
150
+ [data-strategy-loading-state] .guido-skeleton {
151
+ display: block;
152
+ }
153
+
154
+
74
155
  .strategy-control-actions {
75
156
  display: flex;
76
157
  align-items: center;
@@ -117,6 +198,15 @@ const n = `.strategy-control-header {
117
198
  mask-image: var(--guido-icon-line-plus);
118
199
  }
119
200
 
201
+ .strategy-control-action--update::before {
202
+ mask-image: var(--guido-icon-filled-arrow-rising);
203
+ }
204
+
205
+ .strategy-control-name-band .strategy-control-action > span {
206
+ padding: 0 0 0 8px;
207
+ }
208
+
209
+ .strategy-control-action--update,
120
210
  .strategy-control-action--change {
121
211
  color: var(--guido-color-primary-500);
122
212
  }
@@ -129,24 +219,38 @@ const n = `.strategy-control-header {
129
219
  text-decoration: underline;
130
220
  }
131
221
 
132
- .recommendation-controls-container:not(.strategy-block) .strategy-control-container,
222
+ .strategy-control-action:disabled,
223
+ .strategy-control-action:disabled:hover {
224
+ color: var(--guido-color-gray-700);
225
+ text-decoration: none;
226
+ cursor: default;
227
+ }
228
+
229
+ .recommendation-controls-container:not(.strategy-block):not(.legacy-strategy-block) .strategy-control-container,
133
230
  .recommendation-controls-container.strategy-block .product-count-control-container,
134
231
  .recommendation-controls-container.strategy-block .algorithm-control-container,
135
232
  .recommendation-controls-container.strategy-block .filters-control-container,
136
- .recommendation-controls-container.strategy-block .shuffle-control-container {
233
+ .recommendation-controls-container.strategy-block .shuffle-control-container,
234
+ .recommendation-controls-container.legacy-strategy-block .product-count-control-container,
235
+ .recommendation-controls-container.legacy-strategy-block .algorithm-control-container,
236
+ .recommendation-controls-container.legacy-strategy-block .filters-control-container,
237
+ .recommendation-controls-container.legacy-strategy-block .shuffle-control-container {
137
238
  display: none;
138
239
  }
139
240
 
140
- .recommendation-controls-container.strategy-block {
241
+ .recommendation-controls-container.strategy-block,
242
+ .recommendation-controls-container.legacy-strategy-block {
141
243
  display: flex;
142
244
  flex-direction: column;
143
245
  }
144
246
 
145
- .recommendation-controls-container.strategy-block .price-placement-control-container {
247
+ .recommendation-controls-container.strategy-block .price-placement-control-container,
248
+ .recommendation-controls-container.legacy-strategy-block .price-placement-control-container {
146
249
  order: 1;
147
250
  }
148
251
 
149
- .recommendation-controls-container.strategy-block .product-layout-control-container {
252
+ .recommendation-controls-container.strategy-block .product-layout-control-container,
253
+ .recommendation-controls-container.legacy-strategy-block .product-layout-control-container {
150
254
  order: 2;
151
255
  }
152
256
  `;
@@ -0,0 +1,23 @@
1
+ const e = `/*
2
+ * Mirrors the design system's InSkeleton 1:1 (gradient stops, 200% size, 1.6s linear).
3
+ * The Stripo panel lives in the editor's shadow root and is built from raw HTML strings,
4
+ * so the Vue component cannot be used there. Hex values are literal in the DS too.
5
+ *
6
+ * Base only: each panel sizes its own \`.guido-skeleton--*\` modifier to the footprint of
7
+ * the element it stands in for.
8
+ */
9
+ .guido-skeleton {
10
+ display: none;
11
+ border-radius: 4px;
12
+ background: linear-gradient(90deg, #f0f0f0 39.5%, #e1e1e1 66.02%, #f0f0f0 89.42%);
13
+ background-size: 200% 100%;
14
+ animation: guido-skeleton-shine 1.6s linear infinite;
15
+ }
16
+
17
+ @keyframes guido-skeleton-shine {
18
+ to { background-position-x: -200%; }
19
+ }
20
+ `;
21
+ export {
22
+ e as default
23
+ };
@@ -1,4 +1,4 @@
1
- const n = `.patch-session-container {
1
+ const r = `.patch-session-container {
2
2
  row-gap: 16px;
3
3
  }
4
4
 
@@ -28,11 +28,7 @@ ue-vh-patch.selected .patch-wrapper {
28
28
  .change-history-panel-wrapper .control-panel-header {
29
29
  padding: 16px 0 16px 16px;
30
30
  }
31
-
32
- .change-history-panel-wrapper .header-control-panel-label {
33
- grid-area: 1 / 1 / 2 / 12;
34
- }
35
31
  `;
36
32
  export {
37
- n as default
33
+ r as default
38
34
  };
@@ -1,8 +1,8 @@
1
- import "../@types/config/schemas.js";
1
+ import { MessageType as r } from "../@types/config/schemas.js";
2
2
  import "../@types/config/defaults.js";
3
- import { parseConfig as o } from "../@types/config/validator.js";
4
- import { defineStore as r } from "pinia";
5
- const f = r("guido-config", {
3
+ import { parseConfig as a } from "../@types/config/validator.js";
4
+ import { defineStore as o } from "pinia";
5
+ const g = o("guido-config", {
6
6
  state: () => ({
7
7
  initialized: !1,
8
8
  config: null
@@ -75,57 +75,88 @@ const f = r("guido-config", {
75
75
  * Get the template ID
76
76
  */
77
77
  templateId: (i) => {
78
- var e, n;
79
- return ((n = (e = i.config) == null ? void 0 : e.identity) == null ? void 0 : n.templateId) ?? "";
78
+ var e, t;
79
+ return ((t = (e = i.config) == null ? void 0 : e.identity) == null ? void 0 : t.templateId) ?? "";
80
80
  },
81
81
  /**
82
82
  * Get the user ID
83
83
  */
84
84
  userId: (i) => {
85
- var e, n;
86
- return ((n = (e = i.config) == null ? void 0 : e.identity) == null ? void 0 : n.userId) ?? "";
85
+ var e, t;
86
+ return ((t = (e = i.config) == null ? void 0 : e.identity) == null ? void 0 : t.userId) ?? "";
87
87
  },
88
88
  /**
89
89
  * Get the variation ID
90
90
  */
91
91
  variationId: (i) => {
92
- var e, n;
93
- return ((n = (e = i.config) == null ? void 0 : e.identity) == null ? void 0 : n.variationId) ?? "";
92
+ var e, t;
93
+ return ((t = (e = i.config) == null ? void 0 : e.identity) == null ? void 0 : t.variationId) ?? "";
94
+ },
95
+ /**
96
+ * Get the campaign ID
97
+ */
98
+ campaignId: (i) => {
99
+ var e, t;
100
+ return ((t = (e = i.config) == null ? void 0 : e.identity) == null ? void 0 : t.campaignId) ?? "";
101
+ },
102
+ /**
103
+ * Get the template-library ID of the host template
104
+ */
105
+ templateLibraryId: (i) => {
106
+ var e, t;
107
+ return ((t = (e = i.config) == null ? void 0 : e.identity) == null ? void 0 : t.templateLibraryId) ?? "";
94
108
  },
95
109
  /**
96
110
  * Get the partner name
97
111
  */
98
112
  partnerName: (i) => {
99
- var e, n;
100
- return ((n = (e = i.config) == null ? void 0 : e.partner) == null ? void 0 : n.name) ?? "";
113
+ var e, t;
114
+ return ((t = (e = i.config) == null ? void 0 : e.partner) == null ? void 0 : t.name) ?? "";
101
115
  },
102
116
  /**
103
117
  * Get the product type
104
118
  */
105
119
  productType: (i) => {
106
- var e, n;
107
- return ((n = (e = i.config) == null ? void 0 : e.partner) == null ? void 0 : n.productType) ?? 60;
120
+ var e, t;
121
+ return ((t = (e = i.config) == null ? void 0 : e.partner) == null ? void 0 : t.productType) ?? 60;
108
122
  },
109
123
  /**
110
124
  * Get the message type
111
125
  */
112
126
  messageType: (i) => {
113
- var e, n;
114
- return ((n = (e = i.config) == null ? void 0 : e.partner) == null ? void 0 : n.messageType) ?? 1;
127
+ var e, t;
128
+ return ((t = (e = i.config) == null ? void 0 : e.partner) == null ? void 0 : t.messageType) ?? 1;
129
+ },
130
+ /**
131
+ * Transactional campaigns keep the hard save block. Reactive getter, so
132
+ * consumers stay safe in setup where a raw config read snapshots null (SD-147945).
133
+ */
134
+ isTransactional() {
135
+ return this.messageType === r.TRANSACTIONAL;
136
+ },
137
+ /**
138
+ * Soft-save policy: may the editor persist a template with validation errors?
139
+ * Default true (host sets features.allowSaveWithErrors=false for transactional +
140
+ * unsub). Reactive getter defaulting true — reading via isFeatureEnabled would
141
+ * floor to false pre-init and momentarily hide the soft-save option (SD-147430).
142
+ */
143
+ allowSaveWithErrors() {
144
+ var i;
145
+ return ((i = this.features) == null ? void 0 : i.allowSaveWithErrors) ?? !0;
115
146
  },
116
147
  /**
117
148
  * Get the username
118
149
  */
119
150
  username: (i) => {
120
- var e, n;
121
- return ((n = (e = i.config) == null ? void 0 : e.partner) == null ? void 0 : n.username) ?? "Guido User";
151
+ var e, t;
152
+ return ((t = (e = i.config) == null ? void 0 : e.partner) == null ? void 0 : t.username) ?? "Guido User";
122
153
  },
123
154
  /**
124
155
  * Check if header should be shown
125
156
  */
126
157
  showHeader: (i) => {
127
- var e, n;
128
- return ((n = (e = i.config) == null ? void 0 : e.ui) == null ? void 0 : n.showHeader) ?? !0;
158
+ var e, t;
159
+ return ((t = (e = i.config) == null ? void 0 : e.ui) == null ? void 0 : t.showHeader) ?? !0;
129
160
  },
130
161
  /**
131
162
  * Check if a specific feature is enabled.
@@ -134,8 +165,8 @@ const f = r("guido-config", {
134
165
  */
135
166
  // eslint-disable-next-line @stylistic/max-len
136
167
  isFeatureEnabled: (i) => (e) => {
137
- var n, t;
138
- return ((t = (n = i.config) == null ? void 0 : n.features) == null ? void 0 : t[e]) ?? !1;
168
+ var t, n;
169
+ return ((n = (t = i.config) == null ? void 0 : t.features) == null ? void 0 : n[e]) ?? !1;
139
170
  }
140
171
  },
141
172
  actions: {
@@ -143,7 +174,7 @@ const f = r("guido-config", {
143
174
  * Initialize the config store with validated configuration
144
175
  */
145
176
  init(i) {
146
- const e = o(i);
177
+ const e = a(i);
147
178
  this.config = e, this.initialized = !0;
148
179
  },
149
180
  /**
@@ -155,5 +186,5 @@ const f = r("guido-config", {
155
186
  }
156
187
  });
157
188
  export {
158
- f as useConfigStore
189
+ g as useConfigStore
159
190
  };
@@ -4,7 +4,9 @@ const d = e("guidoEmailEditor", {
4
4
  html: "",
5
5
  css: "",
6
6
  lastUpdatedAt: 0,
7
- templateId: ""
7
+ templateId: "",
8
+ bridgeActive: !1,
9
+ applyAcks: {}
8
10
  }),
9
11
  getters: {
10
12
  /** True once the bridge has published at least one snapshot. */
@@ -1,5 +1,5 @@
1
- import { useOnboardingApi as s } from "../services/onboardingApi.js";
2
- import { defineStore as e } from "pinia";
1
+ import { useOnboardingApi as e } from "../services/onboardingApi.js";
2
+ import { defineStore as s } from "pinia";
3
3
  const t = () => ({
4
4
  cardIndex: 0,
5
5
  isActive: !1,
@@ -11,49 +11,61 @@ const t = () => ({
11
11
  textBlockOnboarding: t(),
12
12
  versionHistoryOnboarding: t(),
13
13
  ampOnboarding: t(),
14
- itemsOnboarding: t()
14
+ itemsOnboarding: t(),
15
+ recommendationStrategyOnboarding: t(),
16
+ recommendationLegacyStrategyOnboarding: t()
15
17
  },
16
18
  userModalState: {},
17
19
  isFetched: !1
18
- }), c = e("guidoOnboarding", {
20
+ }), c = s("guidoOnboarding", {
19
21
  state: () => a(),
20
22
  getters: {
21
- getOnboarding: (n) => (i) => n.onboardings[i],
22
- isActive: (n) => (i) => n.onboardings[i].isActive,
23
- getCurrentCard: (n) => (i) => {
24
- const o = n.onboardings[i];
25
- return o.config[o.cardIndex];
23
+ /** @deprecated Components use the type-specific getters. Slated for deletion, see the SD-667788 dead-code ledger. */
24
+ getOnboarding: (n) => (o) => n.onboardings[o],
25
+ isActive: (n) => (o) => n.onboardings[o].isActive,
26
+ /** @deprecated Components use getGenericCurrentCard / getTextBlockCurrentCard. Slated for deletion, see the SD-667788 dead-code ledger. */
27
+ getCurrentCard: (n) => (o) => {
28
+ const i = n.onboardings[o];
29
+ return i.config[i.cardIndex];
26
30
  },
27
31
  getGenericCurrentCard: (n) => {
28
- const { genericOnboarding: i } = n.onboardings;
29
- return i.config[i.cardIndex];
32
+ const { genericOnboarding: o } = n.onboardings;
33
+ return o.config[o.cardIndex];
30
34
  },
31
35
  getTextBlockCurrentCard: (n) => {
32
- const { textBlockOnboarding: i } = n.onboardings;
33
- return i.config[i.cardIndex];
36
+ const { textBlockOnboarding: o } = n.onboardings;
37
+ return o.config[o.cardIndex];
34
38
  },
35
39
  getVersionHistoryCurrentCard: (n) => {
36
- const { versionHistoryOnboarding: i } = n.onboardings;
37
- return i.config[i.cardIndex];
40
+ const { versionHistoryOnboarding: o } = n.onboardings;
41
+ return o.config[o.cardIndex];
38
42
  },
39
43
  getAmpCurrentCard: (n) => {
40
- const { ampOnboarding: i } = n.onboardings;
41
- return i.config[i.cardIndex];
44
+ const { ampOnboarding: o } = n.onboardings;
45
+ return o.config[o.cardIndex];
42
46
  },
43
47
  getItemsCurrentCard: (n) => {
44
- const { itemsOnboarding: i } = n.onboardings;
45
- return i.config[i.cardIndex];
48
+ const { itemsOnboarding: o } = n.onboardings;
49
+ return o.config[o.cardIndex];
50
+ },
51
+ getRecommendationStrategyCurrentCard: (n) => {
52
+ const { recommendationStrategyOnboarding: o } = n.onboardings;
53
+ return o.config[o.cardIndex];
54
+ },
55
+ getRecommendationLegacyStrategyCurrentCard: (n) => {
56
+ const { recommendationLegacyStrategyOnboarding: o } = n.onboardings;
57
+ return o.config[o.cardIndex];
46
58
  },
47
- shouldShowOnboarding: (n) => (i) => {
48
- const o = n.userModalState.Guido;
49
- return i === "newVersionPopup" && (o != null && o.genericOnboarding) ? !1 : o ? !o[i] : !0;
59
+ shouldShowOnboarding: (n) => (o) => {
60
+ const i = n.userModalState.Guido;
61
+ return o === "newVersionPopup" && (i != null && i.genericOnboarding) ? !1 : i ? !i[o] : !0;
50
62
  }
51
63
  },
52
64
  actions: {
53
65
  closeOtherOnboardings(n) {
54
- Object.keys(this.onboardings).forEach((i) => {
55
- const o = i;
56
- o !== n && this.onboardings[o].isActive && (this.onboardings[o].isActive = !1, this.onboardings[o].cardIndex = 0, this.onboardings[o].config = []);
66
+ Object.keys(this.onboardings).forEach((o) => {
67
+ const i = o;
68
+ i !== n && this.onboardings[i].isActive && (this.onboardings[i].isActive = !1, this.onboardings[i].cardIndex = 0, this.onboardings[i].config = []);
57
69
  });
58
70
  },
59
71
  start(n) {
@@ -71,12 +83,13 @@ const t = () => ({
71
83
  previous(n) {
72
84
  this.onboardings[n].cardIndex > 0 && this.onboardings[n].cardIndex--;
73
85
  },
74
- updateCardPosition(n, i, o) {
75
- const r = this.onboardings[n].config[i];
76
- r && (r.top = o.top, r.position = o.position);
86
+ /** @deprecated No caller in src/. Slated for deletion, see the SD-667788 dead-code ledger. */
87
+ updateCardPosition(n, o, i) {
88
+ const r = this.onboardings[n].config[o];
89
+ r && (r.top = i.top, r.position = i.position);
77
90
  },
78
- setConfig(n, i) {
79
- this.onboardings[n].config = i ?? [], this.onboardings[n].cardIndex >= this.onboardings[n].config.length && (this.onboardings[n].cardIndex = 0);
91
+ setConfig(n, o) {
92
+ this.onboardings[n].config = o ?? [], this.onboardings[n].cardIndex >= this.onboardings[n].config.length && (this.onboardings[n].cardIndex = 0);
80
93
  },
81
94
  async onDiscoverNowClicked() {
82
95
  await this.setUserModalState("newVersionPopup", "true", "Guido"), await this.setUserModalState("genericOnboarding", "true", "Guido"), this.start("genericOnboarding");
@@ -87,22 +100,23 @@ const t = () => ({
87
100
  async onNewVersionPopupClose() {
88
101
  await this.setUserModalState("newVersionPopup", "true", "Guido");
89
102
  },
103
+ /** @deprecated No caller in src/. Slated for deletion, see the SD-667788 dead-code ledger. */
90
104
  isOnboardingActive() {
91
105
  return Object.values(this.onboardings).some((n) => n.isActive);
92
106
  },
93
107
  async fetchUserModalState() {
94
108
  if (this.isFetched)
95
109
  return;
96
- const { fetchUserModalState: n } = s();
110
+ const { fetchUserModalState: n } = e();
97
111
  try {
98
- const i = await n();
99
- this.userModalState = i, this.isFetched = !0;
112
+ const o = await n();
113
+ this.userModalState = o, this.isFetched = !0;
100
114
  } catch {
101
115
  }
102
116
  },
103
- async setUserModalState(n, i, o) {
104
- const { setUserModalState: r } = s();
105
- await r(n, i, o), this.isFetched = !1, await this.fetchUserModalState();
117
+ async setUserModalState(n, o, i) {
118
+ const { setUserModalState: r } = e();
119
+ await r(n, o, i), this.isFetched = !1, await this.fetchUserModalState();
106
120
  }
107
121
  }
108
122
  });