@useinsider/guido 3.19.0-beta.f02eaa1 → 3.19.0-beta.f66e9de

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 (56) hide show
  1. package/dist/components/Guido.vue.js +8 -8
  2. package/dist/components/Guido.vue2.js +44 -43
  3. package/dist/components/organisms/base/AuthErrorModal.vue.js +18 -0
  4. package/dist/components/organisms/base/AuthErrorModal.vue2.js +42 -0
  5. package/dist/components/organisms/base/Toaster.vue2.js +13 -12
  6. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue.js +9 -7
  7. package/dist/components/organisms/extensions/recommendation/AssignStrategyDrawer.vue2.js +69 -52
  8. package/dist/components/organisms/extensions/recommendation/RemoveStrategyModal.vue2.js +28 -44
  9. package/dist/components/organisms/header/EditorActions.vue.js +4 -4
  10. package/dist/components/organisms/header/EditorActions.vue2.js +23 -25
  11. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue.js +3 -3
  12. package/dist/components/organisms/onboarding/RecommendationStrategyOnboarding.vue2.js +21 -20
  13. package/dist/composables/useActionsApi.js +52 -47
  14. package/dist/composables/useAuthError.js +54 -0
  15. package/dist/composables/useCodeEditorApi.js +23 -9
  16. package/dist/composables/useCustomInterfaceAppearance.js +61 -51
  17. package/dist/composables/useHtmlValidator.js +87 -82
  18. package/dist/composables/useHttp.js +54 -44
  19. package/dist/composables/useRecommendation.js +40 -35
  20. package/dist/composables/useStripo.js +30 -30
  21. package/dist/composables/useToaster.js +14 -20
  22. package/dist/composables/useTranslations.js +3 -2
  23. package/dist/composables/useVersionHistoryApi.js +33 -24
  24. package/dist/enums/extensions/recommendationBlock.js +32 -25
  25. package/dist/extensions/Blocks/Recommendation/block.js +61 -42
  26. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +21 -20
  27. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +63 -58
  28. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +109 -78
  29. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +96 -97
  30. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +209 -92
  31. package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.js +1 -1
  32. package/dist/extensions/Blocks/Recommendation/utils/nodeConfigWriter.js +26 -16
  33. package/dist/extensions/Blocks/Recommendation/utils/strategyCommit.js +24 -0
  34. package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +21 -12
  35. package/dist/guido.css +1 -1
  36. package/dist/src/components/organisms/base/AuthErrorModal.vue.d.ts +2 -0
  37. package/dist/src/components/wrappers/WpModal.vue.d.ts +1 -1
  38. package/dist/src/composables/useAuthError.d.ts +13 -0
  39. package/dist/src/enums/extensions/recommendationBlock.d.ts +2 -0
  40. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +10 -0
  41. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +1 -0
  42. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  43. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +2 -0
  44. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +8 -0
  45. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +7 -6
  46. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +92 -0
  47. package/dist/src/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.d.ts +1 -1
  48. package/dist/src/extensions/Blocks/Recommendation/utils/strategyCommit.d.ts +14 -0
  49. package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +4 -0
  50. package/dist/src/utils/stripoEditorApi.d.ts +4 -0
  51. package/dist/static/styles/components/recommendation-strategy.css.js +34 -4
  52. package/dist/static/styles/components/skeleton.css.js +23 -0
  53. package/dist/stores/unsubscribe.js +3 -3
  54. package/dist/utils/stripoEditorApi.js +11 -0
  55. package/dist/utils/templatePreparation.js +55 -55
  56. package/package.json +2 -1
@@ -1,34 +1,43 @@
1
- const l = [
1
+ const o = "strategy", u = [
2
2
  {
3
3
  key: "locale",
4
4
  getValue: (e) => e.language,
5
5
  getAvailableOptions: (e) => Object.keys(e.languages)
6
6
  },
7
+ {
8
+ // A block feeds from either an assigned strategy (RRS) or an algorithm (legacy).
9
+ // Only a fresh RRS block has neither, and its feed URL would otherwise be built
10
+ // from an empty algorithm path.
11
+ key: o,
12
+ getValue: (e) => e.strategyId || e.strategy
13
+ },
7
14
  {
8
15
  key: "currency",
9
16
  getValue: (e) => e.currencySettings.value,
10
17
  getAvailableOptions: (e) => e.currencyList.map((n) => n.text),
11
18
  canBeEmpty: !0
12
19
  }
13
- ], o = "newsletter.recommendation-fill-required-fields";
14
- function c(e, n, i = l) {
20
+ ], l = "newsletter.recommendation-fill-required-fields", g = "newsletter.recommendation-assign-strategy";
21
+ function c(e, n, i = u) {
15
22
  return i.filter((t) => {
16
- var u;
23
+ var s;
17
24
  if (t.condition && !t.condition(e))
18
25
  return !1;
19
- const r = (u = t.getAvailableOptions) == null ? void 0 : u.call(t, n);
20
- if (t.canBeEmpty && (r == null ? void 0 : r.length) === 0)
26
+ const a = (s = t.getAvailableOptions) == null ? void 0 : s.call(t, n);
27
+ if (t.canBeEmpty && (a == null ? void 0 : a.length) === 0)
21
28
  return !1;
22
- const a = t.getValue(e);
23
- return a ? r !== void 0 && !r.includes(a) : !0;
29
+ const r = t.getValue(e);
30
+ return r ? a !== void 0 && !a.includes(r) : !0;
24
31
  }).map((t) => t.key);
25
32
  }
26
- function s(e, n) {
33
+ function y(e, n) {
27
34
  return c(e, n).length === 0;
28
35
  }
29
36
  export {
30
- l as REQUIRED_RECOMMENDATION_FIELDS,
31
- o as RecommendationRequiredFieldsKey,
37
+ u as REQUIRED_RECOMMENDATION_FIELDS,
38
+ g as RecommendationAssignStrategyKey,
39
+ l as RecommendationRequiredFieldsKey,
40
+ o as STRATEGY_FIELD_KEY,
32
41
  c as getInvalidFields,
33
- s as isConfigValid
42
+ y as isConfigValid
34
43
  };
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- @charset "UTF-8";.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-1ca6baf0]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-17b3c665]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-17b3c665]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-17b3c665]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-19d8cb42] .vueperslides__bullets,[data-v-1f4a4044] .vueperslides__bullets,[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6bbe5862]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-6bbe5862] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}.legacy-strategy-updated-modal[data-v-da2225a1]{position:relative;z-index:145}
1
+ @charset "UTF-8";.auth-error-modal[data-v-a6429465]{position:relative;z-index:145}.gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-c61cc8ea]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-080ff767]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-080ff767]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-080ff767]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-19d8cb42] .vueperslides__bullets,[data-v-ec2027ff] .vueperslides__bullets,[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd]{width:100%;max-width:none}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-skeleton{width:100%!important}.assign-strategy-drawer-content .assign-strategy-select[data-v-6ce48dfd] .in-dropdown-box__container{width:413px}.assign-strategy-drawer .spaced-dot-sep{background-image:linear-gradient(90deg,#91949f 20%,#fff0 0);background-position:center bottom;background-repeat:repeat-x;background-size:5px 1px}.assign-strategy-drawer .spaced-dot-sep--top{background-position:center top}.assign-strategy-drawer .spaced-dot-sep--fc-n:first-child{background:none}.legacy-strategy-updated-modal[data-v-da2225a1]{position:relative;z-index:145}
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
2
+ export default _default;
@@ -34,9 +34,9 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_WithDefaults<
34
34
  }>>>, {
35
35
  size: "X-small" | "small" | "medium" | "large";
36
36
  description: string;
37
- closeOnOutsideClick: boolean;
38
37
  footerButtonOptions: FooterButtonGroup;
39
38
  closeButtonStatus: boolean;
39
+ closeOnOutsideClick: boolean;
40
40
  footerStatus: boolean;
41
41
  }>;
42
42
  declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
@@ -0,0 +1,13 @@
1
+ export interface AuthErrorState {
2
+ status: number;
3
+ data: Record<string, unknown> | null;
4
+ }
5
+ export declare const releaseAuthFreeze: () => void;
6
+ export declare const reportAuthError: (status: number, body: string, url: string) => void;
7
+ export declare const useAuthError: () => {
8
+ authError: import("vue").Ref<{
9
+ status: number;
10
+ data: Record<string, unknown> | null;
11
+ } | null>;
12
+ releaseAuthFreeze: () => void;
13
+ };
@@ -8,7 +8,9 @@ export declare const URLS: {
8
8
  NEWSLETTER_RECOMMENDATIONS_PATH: string;
9
9
  MIGRATE_STRATEGIES_PATH: string;
10
10
  TEMPLATE_MIGRATE_STRATEGIES_PATH: string;
11
+ RECOMMENDATION_STRATEGY_CREATE_PATH: string;
11
12
  };
13
+ export declare const strategyEditPath: (strategyId: string | number) => string;
12
14
  export declare const MIGRATION_PATHS: Record<RrsMigrationTarget['scope'], string>;
13
15
  export declare const QUERY_PARAMS: {
14
16
  CLIENT_ID: string;
@@ -15,6 +15,8 @@ export declare class RecommendationBlock extends Block {
15
15
  * This avoids generating a new (different) ID in onCreated().
16
16
  */
17
17
  private _pendingBlockId;
18
+ /** Ids already reset under their new name, so the deferred pass skips their stale snapshot. */
19
+ private _resetSourceIds;
18
20
  constructor();
19
21
  getId(): string;
20
22
  getIcon(): string;
@@ -73,6 +75,14 @@ export declare class RecommendationBlock extends Block {
73
75
  * in the document and finding the maximum existing ID + 1.
74
76
  */
75
77
  private _generateNextId;
78
+ /**
79
+ * Drops the "already fetched" claims of a block that arrived holding a baked id
80
+ * (saved module, paste, duplicate), so the settings panel reads its strategy again.
81
+ *
82
+ * Deferred a tick: the collision handlers rename a sibling first, and either sibling can be
83
+ * the renamed one depending on where the module was dropped (SD-149916).
84
+ */
85
+ private _scheduleArrivalReset;
76
86
  /**
77
87
  * Heals a duplicate that slipped past the create-time `_detectDuplicate`
78
88
  * scan (or that was persisted by an older template before SD-142352).
@@ -10,6 +10,7 @@
10
10
  import type { RecommendationNodeConfig, CurrencyConfig, OmnibusTextConfig } from '../types/nodeConfig';
11
11
  export declare const PRE_RRS_CONFIG_VERSION = 1;
12
12
  export declare const CURRENT_CONFIG_VERSION = 2;
13
+ export declare const RRS_CONFIG_VERSION = 2;
13
14
  /**
14
15
  * Default currency configuration
15
16
  * Uses USD as the base currency with standard formatting
@@ -10,4 +10,4 @@ export { RecommendationBlockId } from './blockIds';
10
10
  export { RecommendationControlId } from './controlIds';
11
11
  export { BLOCK_ROOT_SELECTOR, CONTAINER_SELECTOR, DESKTOP_CONTAINER_SELECTOR, MOBILE_CONTAINER_SELECTOR, MOBILE_ROW_SELECTOR, CSS_CLASS_RECO_BUTTON, CSS_CLASS_SKIP_COMPILE, RECOMMENDATION_VARIABLE_BUILTIN_ATTRIBUTES, CURRENCY_ATTR, ATTR_PRODUCT_IMAGE, ATTR_PRODUCT_NAME, ATTR_PRODUCT_PRICE, ATTR_PRODUCT_OLD_PRICE, ATTR_PRODUCT_OMNIBUS_PRICE, ATTR_PRODUCT_OMNIBUS_DISCOUNT, ATTR_PRODUCT_BUTTON, ATTR_RECOMMENDATION_TITLE, SELECTOR_TITLE_CELL, ATTR_CUSTOM_PREFIX, ATTR_DATA_CARD_COMPOSITION, ATTR_DATA_CUSTOM_ATTRIBUTES, ATTR_PRODUCT_ATTR, CSS_CLASS_ATTRIBUTE_ROW, CSS_CLASS_SPACER, SELECTOR_ATTRIBUTE_ROW, ATTR_DATA_ATTRIBUTE_TYPE, ATTR_DATA_VISIBILITY, PRODUCT_ATTRIBUTE_PREFIX, BUILT_IN_DEFAULT_ATTRIBUTES, } from './selectors';
12
12
  export { LAYOUT_VALUES, LAYOUT_OPTIONS, DEFAULT_PRODUCTS_PER_ROW, DEFAULT_CARDS_IN_ROW, DEFAULT_MOBILE_CARDS_IN_ROW, MAX_PRODUCT_COUNT, MIN_PRODUCT_COUNT, MAX_PRODUCTS_PER_ROW, MIN_PRODUCTS_PER_ROW, MAX_MOBILE_PRODUCTS_PER_ROW, MIN_MOBILE_PRODUCTS_PER_ROW, DEFAULT_COLUMN_SPACING, DEFAULT_ROW_SPACING, DEFAULT_MOBILE_COLUMN_SPACING, DEFAULT_MOBILE_ROW_SPACING, MIN_SPACING, MAX_SPACING, SPACING_STEP, } from './layout';
13
- export { DEFAULT_NODE_CONFIG, DEFAULT_CURRENCY, DEFAULT_COMPOSITION, DEFAULT_VISIBILITY, CURRENT_CONFIG_VERSION, PRE_RRS_CONFIG_VERSION, EXCLUDED_ALGORITHM_IDS, } from './defaultConfig';
13
+ export { DEFAULT_NODE_CONFIG, DEFAULT_CURRENCY, DEFAULT_COMPOSITION, DEFAULT_VISIBILITY, CURRENT_CONFIG_VERSION, PRE_RRS_CONFIG_VERSION, RRS_CONFIG_VERSION, EXCLUDED_ALGORITHM_IDS, } from './defaultConfig';
@@ -70,6 +70,8 @@ export declare class RecommendationBlockControl extends CommonControl {
70
70
  * state was rebuilt with (SD-150347).
71
71
  */
72
72
  private _syncNodeConfigIfChanged;
73
+ /** Whether the deferred write would move the node's strategyId — see the caller (SD-149916). */
74
+ private _isPendingStrategyIdChange;
73
75
  private _capturePendingNodeConfigWrite;
74
76
  /**
75
77
  * Accumulates the pending write into `documentModifier` without applying, so the
@@ -11,6 +11,14 @@ export declare class StrategyControl extends CommonControl {
11
11
  getTemplate(): string;
12
12
  private _strategyAction;
13
13
  onRender(): void;
14
+ /**
15
+ * Whether the document itself says this block has no strategy.
16
+ *
17
+ * Read the node, not the store: when the main control cannot resolve the block id off the
18
+ * node it never syncs the persisted config, so the store still holds defaults (empty
19
+ * strategyId) for an assigned block.
20
+ */
21
+ private _isNodeUnassigned;
14
22
  onDestroy(): void;
15
23
  private _teardown;
16
24
  private _setupButtonListeners;
@@ -88,8 +88,6 @@ export interface RegenerateWithStylesOptions extends Omit<RegenerateProductRowsO
88
88
  products?: RecommendationProduct[];
89
89
  /** Optional: pass layout directly to avoid stale DOM reads after setAttribute */
90
90
  layout?: Orientation;
91
- /** Applies the batch even when the rows are unchanged, for callers that staged their own edits. */
92
- forceApply?: boolean;
93
91
  }
94
92
  /**
95
93
  * Regenerates product rows while preserving user-applied styles, in a SINGLE commit.
@@ -109,7 +107,7 @@ export interface RegenerateWithStylesOptions extends Omit<RegenerateProductRowsO
109
107
  * HTML removes the need for any post-rebuild reapply pass.
110
108
  * @param options - Configuration options for regeneration
111
109
  */
112
- export declare function regenerateProductRowsWithStyles(options: RegenerateWithStylesOptions): void;
110
+ export declare function regenerateProductRowsWithStyles(options: RegenerateWithStylesOptions): boolean;
113
111
  /**
114
112
  * Adjusts a products array to a target size.
115
113
  * Used by ProductLayoutControl to synchronously match products to the new size
@@ -153,8 +151,11 @@ export interface UpdateProductContentInPlaceOptions {
153
151
  currentNode: ImmutableHtmlNode | null | undefined;
154
152
  documentModifier: DocumentModifier;
155
153
  products: RecommendationProduct[];
156
- /** Applies the batch even when the cards are unchanged, for callers that staged their own edits. */
157
- forceApply?: boolean;
154
+ /**
155
+ * Called when the batch was actually committed. Identical products commit nothing, which
156
+ * leaves anything a caller staged into the same batch unwritten unless it applies itself.
157
+ */
158
+ onApplied?: () => void;
158
159
  }
159
160
  /**
160
161
  * Updates product content in-place without regenerating HTML structure.
@@ -165,7 +166,7 @@ export interface UpdateProductContentInPlaceOptions {
165
166
  * After updating desktop, also updates mobile container to keep them in sync.
166
167
  *
167
168
  * Falls back to false when product count changed (need to add/remove elements).
168
- * @param options - Configuration options
169
+ * @param options - Configuration options; `onApplied` fires only when a batch was committed
169
170
  * @returns true if in-place update was successful, false to fall back to full regeneration
170
171
  */
171
172
  export declare function updateProductContentInPlace(options: UpdateProductContentInPlaceOptions): boolean;
@@ -86,8 +86,11 @@ interface StoreState {
86
86
  strategies: RrsStrategy[];
87
87
  strategiesLoading: boolean;
88
88
  strategyUrlTemplates: Record<string, string>;
89
+ strategiesFetched: boolean;
90
+ strategiesSettled: boolean;
89
91
  blockStates: Record<number, PerBlockState>;
90
92
  currentRecommendationId: number | null;
93
+ strategyPanelOpen: boolean;
91
94
  configVersion: number;
92
95
  }
93
96
  export declare const useRecommendationExtensionStore: import("pinia").StoreDefinition<"guidoRecommendationExtension", StoreState, {
@@ -114,8 +117,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
114
117
  }[];
115
118
  strategiesLoading: boolean;
116
119
  strategyUrlTemplates: Record<string, string>;
120
+ strategiesFetched: boolean;
121
+ strategiesSettled: boolean;
117
122
  blockStates: Record<number, PerBlockState>;
118
123
  currentRecommendationId: number | null;
124
+ strategyPanelOpen: boolean;
119
125
  configVersion: number;
120
126
  } & import("pinia").PiniaCustomStateProperties<StoreState>): PerBlockConfigs;
121
127
  /**
@@ -140,8 +146,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
140
146
  }[];
141
147
  strategiesLoading: boolean;
142
148
  strategyUrlTemplates: Record<string, string>;
149
+ strategiesFetched: boolean;
150
+ strategiesSettled: boolean;
143
151
  blockStates: Record<number, PerBlockState>;
144
152
  currentRecommendationId: number | null;
153
+ strategyPanelOpen: boolean;
145
154
  configVersion: number;
146
155
  } & import("pinia").PiniaCustomStateProperties<StoreState>): RecommendationProduct[];
147
156
  /**
@@ -166,8 +175,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
166
175
  }[];
167
176
  strategiesLoading: boolean;
168
177
  strategyUrlTemplates: Record<string, string>;
178
+ strategiesFetched: boolean;
179
+ strategiesSettled: boolean;
169
180
  blockStates: Record<number, PerBlockState>;
170
181
  currentRecommendationId: number | null;
182
+ strategyPanelOpen: boolean;
171
183
  configVersion: number;
172
184
  } & import("pinia").PiniaCustomStateProperties<StoreState>): boolean;
173
185
  assignStrategyDrawerStatus(state: {
@@ -189,8 +201,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
189
201
  }[];
190
202
  strategiesLoading: boolean;
191
203
  strategyUrlTemplates: Record<string, string>;
204
+ strategiesFetched: boolean;
205
+ strategiesSettled: boolean;
192
206
  blockStates: Record<number, PerBlockState>;
193
207
  currentRecommendationId: number | null;
208
+ strategyPanelOpen: boolean;
194
209
  configVersion: number;
195
210
  } & import("pinia").PiniaCustomStateProperties<StoreState>): boolean;
196
211
  removeStrategyModalStatus(state: {
@@ -212,8 +227,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
212
227
  }[];
213
228
  strategiesLoading: boolean;
214
229
  strategyUrlTemplates: Record<string, string>;
230
+ strategiesFetched: boolean;
231
+ strategiesSettled: boolean;
215
232
  blockStates: Record<number, PerBlockState>;
216
233
  currentRecommendationId: number | null;
234
+ strategyPanelOpen: boolean;
217
235
  configVersion: number;
218
236
  } & import("pinia").PiniaCustomStateProperties<StoreState>): boolean;
219
237
  isLegacyStrategyBlock(): boolean;
@@ -236,8 +254,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
236
254
  }[];
237
255
  strategiesLoading: boolean;
238
256
  strategyUrlTemplates: Record<string, string>;
257
+ strategiesFetched: boolean;
258
+ strategiesSettled: boolean;
239
259
  blockStates: Record<number, PerBlockState>;
240
260
  currentRecommendationId: number | null;
261
+ strategyPanelOpen: boolean;
241
262
  configVersion: number;
242
263
  } & import("pinia").PiniaCustomStateProperties<StoreState>): boolean;
243
264
  legacyStrategyUpdatedModalStatus(state: {
@@ -259,8 +280,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
259
280
  }[];
260
281
  strategiesLoading: boolean;
261
282
  strategyUrlTemplates: Record<string, string>;
283
+ strategiesFetched: boolean;
284
+ strategiesSettled: boolean;
262
285
  blockStates: Record<number, PerBlockState>;
263
286
  currentRecommendationId: number | null;
287
+ strategyPanelOpen: boolean;
264
288
  configVersion: number;
265
289
  } & import("pinia").PiniaCustomStateProperties<StoreState>): boolean;
266
290
  assignedStrategy(state: {
@@ -282,8 +306,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
282
306
  }[];
283
307
  strategiesLoading: boolean;
284
308
  strategyUrlTemplates: Record<string, string>;
309
+ strategiesFetched: boolean;
310
+ strategiesSettled: boolean;
285
311
  blockStates: Record<number, PerBlockState>;
286
312
  currentRecommendationId: number | null;
313
+ strategyPanelOpen: boolean;
287
314
  configVersion: number;
288
315
  } & import("pinia").PiniaCustomStateProperties<StoreState>): RrsStrategy | null;
289
316
  /**
@@ -308,8 +335,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
308
335
  }[];
309
336
  strategiesLoading: boolean;
310
337
  strategyUrlTemplates: Record<string, string>;
338
+ strategiesFetched: boolean;
339
+ strategiesSettled: boolean;
311
340
  blockStates: Record<number, PerBlockState>;
312
341
  currentRecommendationId: number | null;
342
+ strategyPanelOpen: boolean;
313
343
  configVersion: number;
314
344
  } & import("pinia").PiniaCustomStateProperties<StoreState>): boolean;
315
345
  /**
@@ -334,8 +364,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
334
364
  }[];
335
365
  strategiesLoading: boolean;
336
366
  strategyUrlTemplates: Record<string, string>;
367
+ strategiesFetched: boolean;
368
+ strategiesSettled: boolean;
337
369
  blockStates: Record<number, PerBlockState>;
338
370
  currentRecommendationId: number | null;
371
+ strategyPanelOpen: boolean;
339
372
  configVersion: number;
340
373
  } & import("pinia").PiniaCustomStateProperties<StoreState>): number;
341
374
  hasFilters(): boolean;
@@ -361,8 +394,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
361
394
  }[];
362
395
  strategiesLoading: boolean;
363
396
  strategyUrlTemplates: Record<string, string>;
397
+ strategiesFetched: boolean;
398
+ strategiesSettled: boolean;
364
399
  blockStates: Record<number, PerBlockState>;
365
400
  currentRecommendationId: number | null;
401
+ strategyPanelOpen: boolean;
366
402
  configVersion: number;
367
403
  } & import("pinia").PiniaCustomStateProperties<StoreState>) => {
368
404
  text: string;
@@ -387,8 +423,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
387
423
  }[];
388
424
  strategiesLoading: boolean;
389
425
  strategyUrlTemplates: Record<string, string>;
426
+ strategiesFetched: boolean;
427
+ strategiesSettled: boolean;
390
428
  blockStates: Record<number, PerBlockState>;
391
429
  currentRecommendationId: number | null;
430
+ strategyPanelOpen: boolean;
392
431
  configVersion: number;
393
432
  } & import("pinia").PiniaCustomStateProperties<StoreState>) => {
394
433
  text: string;
@@ -413,8 +452,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
413
452
  }[];
414
453
  strategiesLoading: boolean;
415
454
  strategyUrlTemplates: Record<string, string>;
455
+ strategiesFetched: boolean;
456
+ strategiesSettled: boolean;
416
457
  blockStates: Record<number, PerBlockState>;
417
458
  currentRecommendationId: number | null;
459
+ strategyPanelOpen: boolean;
418
460
  configVersion: number;
419
461
  } & import("pinia").PiniaCustomStateProperties<StoreState>) => {
420
462
  text: string;
@@ -440,6 +482,10 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
440
482
  /**
441
483
  * Deep-clones a block's state and mirrors its campaign URL under a new id.
442
484
  * Invoked from `onCreated` when a duplicate is detected (SD-142352).
485
+ *
486
+ * The clone keeps the source's data but drops its "already fetched / already
487
+ * synced" claims for strategy blocks, so it fetches again like a fresh drop
488
+ * (SD-149916).
443
489
  */
444
490
  cloneBlockState(sourceId: number, newId: number): void;
445
491
  /**
@@ -497,6 +543,47 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
497
543
  openRemoveStrategyModal(): void;
498
544
  closeRemoveStrategyModal(): void;
499
545
  fetchStrategies(): Promise<void>;
546
+ /**
547
+ * Clears what a block inherited from the id it arrived holding, so the panel fetches for it.
548
+ * A re-dropped saved module can keep the source's id — and its "already fetched" entry —
549
+ * while the strategy's product count has moved on (SD-149916).
550
+ */
551
+ resetArrivedBlock(id: number): void;
552
+ invalidateStrategies(): void;
553
+ /**
554
+ * Opens a Smart Recommender strategy page in a new tab and refreshes the list every time
555
+ * the user comes back. `visibilitychange` only: a `focus` listener would also fire when
556
+ * focus merely returns from the Stripo canvas iframe to the panel, refetching and
557
+ * regenerating the canvas while the user never left the editor (SD-149916).
558
+ *
559
+ * Deliberately NOT one-shot: the strategy tab stays open, so a user can create a second
560
+ * strategy in it and come back again — a listener that disarmed on the first return would
561
+ * leave that one missing from the list. It disarms on the first return AFTER that tab is
562
+ * closed instead, so an ordinary alt-tab later in the session costs nothing. Armed only
563
+ * once the user actually opens a strategy page, so anyone who never does pays nothing.
564
+ * @returns whether a tab actually opened, so callers can skip work that assumes one did
565
+ */
566
+ _armStrategyPageReturn(url: string): boolean;
567
+ /**
568
+ * Reloads the products of the block the user is on, so an edit made in the strategy tab
569
+ * lands on the canvas instead of waiting for the assign drawer to be reopened.
570
+ *
571
+ * Only the selected block: the canvas regeneration is driven off the active block's
572
+ * product array, so refreshing an unselected block would fetch without redrawing it.
573
+ */
574
+ _refreshAssignedStrategyProducts(): Promise<void>;
575
+ /** Lets the editor tear the return listeners down when it unmounts. */
576
+ disposeStrategyPageReturn(): void;
577
+ /**
578
+ * Opens Smart Recommender's strategy creation page. Every return refreshes the list so the
579
+ * new strategy is offered; the user picks it themselves.
580
+ */
581
+ openStrategyCreation(): boolean;
582
+ /**
583
+ * Opens the strategy's edit page. Every return refreshes the list so the block reflects the
584
+ * edited configuration.
585
+ */
586
+ openStrategyEdit(strategyId: string | number): boolean;
500
587
  resolveStrategyUrlTemplate(strategy: RrsStrategy, currency: string): Promise<string>;
501
588
  assignStrategy(strategy: RrsStrategy): void;
502
589
  convertLegacyStrategy(payload: RrsMigrationPayload, target?: RrsMigrationTarget): Promise<string>;
@@ -525,6 +612,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
525
612
  * every block's recommendationConfigs across user edits.
526
613
  */
527
614
  hasInvalidBlock(): boolean;
615
+ /**
616
+ * Which required fields are missing across the design's blocks, so the save
617
+ * toaster can name the cause instead of always showing the generic message.
618
+ */
619
+ invalidBlockFields(): string[];
528
620
  fetchRecommendationProducts(): Promise<void>;
529
621
  _doFetchProducts(): Promise<void>;
530
622
  /**
@@ -2,7 +2,7 @@ import type { RrsMigrationPayload, RrsMigrationTarget } from '@@/Types/recommend
2
2
  /**
3
3
  * A block authored before reusable strategies: it still carries a plain feed
4
4
  * configuration (compiled into a feed URL string) instead of a strategy id.
5
- * Blocks created under RRS stamp `CURRENT_CONFIG_VERSION`, so the version is
5
+ * Blocks created under RRS stamp at least `RRS_CONFIG_VERSION`, so the version is
6
6
  * what separates "never converted" from "not assigned yet".
7
7
  */
8
8
  export declare function isLegacyStrategyConfig({ strategyId, nodeConfigVersion }: {
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Writes a strategy change and its products straight to the document, without the settings panel.
3
+ *
4
+ * Every entry point is host-rendered UI outside `ui-editor`, and none of them can rely on the
5
+ * panel control: opening the strategy page deselects the block, so by the time the user comes back
6
+ * and presses Assign the control — and with it the subscription that does the node write, the
7
+ * product fetch and the repaint — is gone. The assignment then reaches Pinia and nothing else
8
+ * (SD-149916).
9
+ *
10
+ * Call AFTER the store change (`assignStrategy` / `removeStrategy`).
11
+ * @param description - labels the undo entry
12
+ * @returns whether the write reached a node
13
+ */
14
+ export declare function commitStrategyChange(blockId: number, description: string): Promise<boolean>;
@@ -15,7 +15,11 @@ export interface RequiredField {
15
15
  getAvailableOptions?: (store: ExtensionStoreSlice) => string[];
16
16
  condition?: (config: PerBlockConfigs) => boolean;
17
17
  }
18
+ /** Field key of the strategy/algorithm descriptor, used to pick the toaster message. */
19
+ export declare const STRATEGY_FIELD_KEY = "strategy";
18
20
  export declare const REQUIRED_RECOMMENDATION_FIELDS: RequiredField[];
19
21
  export declare const RecommendationRequiredFieldsKey = "newsletter.recommendation-fill-required-fields";
22
+ /** Shown instead of the generic message when the only thing missing is the strategy. */
23
+ export declare const RecommendationAssignStrategyKey = "newsletter.recommendation-assign-strategy";
20
24
  export declare function getInvalidFields(config: PerBlockConfigs, store: ExtensionStoreSlice, fields?: RequiredField[]): string[];
21
25
  export declare function isConfigValid(config: PerBlockConfigs, store: ExtensionStoreSlice): boolean;
@@ -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;
@@ -83,11 +83,8 @@ const n = `.strategy-control-header {
83
83
  white-space: nowrap;
84
84
  }
85
85
 
86
- .strategy-control-cta.primary > .button:disabled,
87
- .strategy-control-cta.primary > .button.disabled {
88
- opacity: 1;
86
+ .strategy-control-cta.primary > .button {
89
87
  color: var(--guido-color-gray-800);
90
- cursor: default;
91
88
  }
92
89
 
93
90
  .strategy-control-name-band {
@@ -113,6 +110,39 @@ const n = `.strategy-control-header {
113
110
  line-height: 24px;
114
111
  }
115
112
 
113
+ /* Each skeleton mirrors the footprint of the element it stands in for, so retiring
114
+ the loading state does not shift the panel. */
115
+ .guido-skeleton--strategy-title {
116
+ width: 366px;
117
+ height: 38px;
118
+ }
119
+
120
+ .guido-skeleton--strategy-description {
121
+ width: 366px;
122
+ height: 48px;
123
+ }
124
+
125
+ .guido-skeleton--strategy-cta {
126
+ width: 175px;
127
+ height: 40px;
128
+ }
129
+
130
+ .guido-skeleton--strategy-name {
131
+ width: 398px;
132
+ height: 48px;
133
+ }
134
+
135
+ .strategy-control-skeleton-row {
136
+ display: flex;
137
+ gap: 16px;
138
+ padding: 0 16px 16px;
139
+ }
140
+
141
+ [data-strategy-loading-state] .guido-skeleton {
142
+ display: block;
143
+ }
144
+
145
+
116
146
  .strategy-control-actions {
117
147
  display: flex;
118
148
  align-items: center;
@@ -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
+ };
@@ -39,16 +39,16 @@ const r = () => ({
39
39
  });
40
40
  },
41
41
  isActiveTypeFirstInCollection: (e) => {
42
- const t = i[e.selectedCollectionType];
42
+ const t = i[e.selectedCollectionType] ?? [];
43
43
  return e.activeType === t[0];
44
44
  },
45
45
  isActiveTypeLastInCollection: (e) => {
46
- const t = i[e.selectedCollectionType];
46
+ const t = i[e.selectedCollectionType] ?? [];
47
47
  return e.activeType === t[t.length - 1];
48
48
  },
49
49
  hasTemplatesByCollectionType: (e) => {
50
50
  const t = {};
51
- return i[e.selectedCollectionType].forEach((s) => {
51
+ return (i[e.selectedCollectionType] ?? []).forEach((s) => {
52
52
  t[s] = e.templates.some((c) => c.type === s);
53
53
  }), t;
54
54
  },
@@ -0,0 +1,11 @@
1
+ const o = "The editor is not ready yet. Please wait for it to load and try again.", i = () => window.StripoEditorApi, r = () => {
2
+ const t = i();
3
+ if (!t)
4
+ throw new Error(o);
5
+ return t;
6
+ };
7
+ export {
8
+ o as EDITOR_NOT_READY_MESSAGE,
9
+ i as findEditorApi,
10
+ r as getEditorApi
11
+ };