@useinsider/guido 3.12.0-beta.d2745e7 → 3.12.0-beta.d77b0d2

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 (73) hide show
  1. package/dist/@types/config/schemas.js +9 -4
  2. package/dist/components/Guido.vue.js +6 -6
  3. package/dist/components/Guido.vue2.js +50 -49
  4. package/dist/components/organisms/extensions/recommendation/StrategyDetailDrawer.vue.js +38 -0
  5. package/dist/components/organisms/extensions/recommendation/StrategyDetailDrawer.vue2.js +271 -0
  6. package/dist/components/organisms/extensions/recommendation/strategy-detail/CampaignTable.vue.js +18 -0
  7. package/dist/components/organisms/extensions/recommendation/strategy-detail/CampaignTable.vue2.js +42 -0
  8. package/dist/components/organisms/extensions/recommendation/strategy-detail/FilterHumanizer.vue.js +20 -0
  9. package/dist/components/organisms/extensions/recommendation/strategy-detail/FilterHumanizer.vue2.js +18 -0
  10. package/dist/components/organisms/extensions/recommendation/strategy-detail/HumanizerCondition.vue.js +20 -0
  11. package/dist/components/organisms/extensions/recommendation/strategy-detail/HumanizerCondition.vue2.js +60 -0
  12. package/dist/components/organisms/extensions/recommendation/strategy-detail/HumanizerGroup.vue.js +19 -0
  13. package/dist/components/organisms/extensions/recommendation/strategy-detail/HumanizerGroup.vue2.js +19 -0
  14. package/dist/components/organisms/extensions/recommendation/strategy-detail/InfoDisplayValue.vue.js +22 -0
  15. package/dist/components/organisms/extensions/recommendation/strategy-detail/InfoDisplayValue.vue2.js +29 -0
  16. package/dist/composables/useHtmlValidator.js +68 -60
  17. package/dist/composables/useHttp.js +61 -52
  18. package/dist/composables/useRecommendation.js +56 -40
  19. package/dist/composables/useSave.js +22 -22
  20. package/dist/composables/useStrategyFilters.js +16 -0
  21. package/dist/config/migrator/recommendationMigrator.js +7 -4
  22. package/dist/enums/date.js +4 -3
  23. package/dist/enums/extensions/filteringV2.js +1024 -0
  24. package/dist/enums/extensions/recommendationBlock.js +45 -24
  25. package/dist/enums/extensions/strategyDetail.js +149 -0
  26. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +12 -11
  27. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +141 -123
  28. package/dist/extensions/Blocks/Recommendation/controls/main/strategy.js +297 -0
  29. package/dist/extensions/Blocks/Recommendation/iconsRegistry.js +16 -2
  30. package/dist/extensions/Blocks/Recommendation/recommendation.css.js +137 -0
  31. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +549 -165
  32. package/dist/extensions/Blocks/Recommendation/utils/strategyHumanizer.js +97 -0
  33. package/dist/extensions/Blocks/Recommendation/utils/strategyNavigation.js +8 -0
  34. package/dist/extensions/Blocks/Recommendation/utils/strategySummary.js +95 -0
  35. package/dist/extensions/Blocks/Recommendation/utils/strategyUrl.js +43 -0
  36. package/dist/extensions/Blocks/Recommendation/validation/requiredFields.js +24 -10
  37. package/dist/extensions/Blocks/common-control.js +37 -35
  38. package/dist/guido.css +1 -1
  39. package/dist/services/recommendationApi.js +127 -33
  40. package/dist/services/stripoApi.js +18 -18
  41. package/dist/src/@types/config/schemas.d.ts +10 -0
  42. package/dist/src/components/organisms/extensions/recommendation/StrategyDetailDrawer.vue.d.ts +2 -0
  43. package/dist/src/components/organisms/extensions/recommendation/strategy-detail/CampaignTable.vue.d.ts +43 -0
  44. package/dist/src/components/organisms/extensions/recommendation/strategy-detail/FilterHumanizer.vue.d.ts +29 -0
  45. package/dist/src/components/organisms/extensions/recommendation/strategy-detail/HumanizerCondition.vue.d.ts +40 -0
  46. package/dist/src/components/organisms/extensions/recommendation/strategy-detail/HumanizerGroup.vue.d.ts +38 -0
  47. package/dist/src/components/organisms/extensions/recommendation/strategy-detail/InfoDisplayValue.vue.d.ts +51 -0
  48. package/dist/src/composables/useConfig.d.ts +2 -0
  49. package/dist/src/composables/useHtmlValidator.d.ts +2 -0
  50. package/dist/src/composables/useRecommendation.d.ts +2 -0
  51. package/dist/src/composables/useStrategyFilters.d.ts +24 -0
  52. package/dist/src/enums/extensions/filteringV2.d.ts +72 -0
  53. package/dist/src/enums/extensions/recommendationBlock.d.ts +33 -0
  54. package/dist/src/enums/extensions/strategyDetail.d.ts +90 -0
  55. package/dist/src/extensions/Blocks/Recommendation/controls/main/index.d.ts +10 -4
  56. package/dist/src/extensions/Blocks/Recommendation/controls/main/strategy.d.ts +118 -0
  57. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +958 -1
  58. package/dist/src/extensions/Blocks/Recommendation/types/nodeConfig.d.ts +7 -0
  59. package/dist/src/extensions/Blocks/Recommendation/utils/strategyHumanizer.d.ts +50 -0
  60. package/dist/src/extensions/Blocks/Recommendation/utils/strategyNavigation.d.ts +10 -0
  61. package/dist/src/extensions/Blocks/Recommendation/utils/strategySummary.d.ts +34 -0
  62. package/dist/src/extensions/Blocks/Recommendation/utils/strategyUrl.d.ts +51 -0
  63. package/dist/src/extensions/Blocks/Recommendation/validation/requiredFields.d.ts +8 -1
  64. package/dist/src/extensions/Blocks/common-control.d.ts +5 -2
  65. package/dist/src/mock/api/recommendation-strategies.d.ts +2 -0
  66. package/dist/src/services/recommendationApi.d.ts +9 -1
  67. package/dist/src/stores/config.d.ts +18 -0
  68. package/dist/src/utils/genericUtil.d.ts +9 -0
  69. package/dist/static/styles/components/base-input.css.js +6 -7
  70. package/dist/utils/dateUtil.js +23 -10
  71. package/dist/utils/genericUtil.js +10 -1
  72. package/dist/utils/templatePreparation.js +70 -57
  73. package/package.json +1 -1
@@ -54,6 +54,13 @@ export interface RecommendationNodeConfig {
54
54
  * @example 'mostPopular', 'complementaryItems', 'manualMerchandising'
55
55
  */
56
56
  strategy: string;
57
+ /**
58
+ * Reusable Recommendation Strategy (RRS) id from Smart Recommender.
59
+ * Empty string means no strategy is assigned.
60
+ * Only used when the `reusableRecommendationStrategy` feature is enabled;
61
+ * when set, it supersedes `strategy` for building the recommendation URL.
62
+ */
63
+ strategyId: string;
57
64
  /**
58
65
  * Product IDs for manual merchandising strategy
59
66
  * Only used when strategy === 'manualMerchandising'
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Renders one RRS filter condition as readable text for the detail drawer.
3
+ *
4
+ * Ported from design-system-organisms
5
+ * `src/organisms/OrgStrategyDetailModal/helpers/humanizer.helper.ts` (branch `develop`).
6
+ *
7
+ * Two deliberate deviations from the source:
8
+ *
9
+ * 1. `trans` is injected rather than read from a module-level `translations` object,
10
+ * so this stays pure and testable and picks up Guido's editor-config translations.
11
+ * 2. The source wraps every date in `getUnixTimestampFromDate(...)` before formatting.
12
+ * Guido's `formatShortDate` already accepts a raw date string via
13
+ * `convertToDateObject`, so that conversion hop is dropped rather than reimplemented.
14
+ *
15
+ * This humanizes the same JSON as `strategySummary.ts` but for a different surface —
16
+ * see the note in `@@/Enums/extensions/strategyDetail` on why the operator tables differ.
17
+ */
18
+ import type { RrsDetailCondition } from '@@/Types/recommendation';
19
+ /** Translation lookup, matching `useTranslations()`. */
20
+ type TranslateFn = (key: string, params?: Record<string, string | number | boolean>) => string;
21
+ export interface TimeUnitOption {
22
+ text: string;
23
+ value: string;
24
+ }
25
+ export declare const capitalizeFirstLetter: (text: string) => string;
26
+ export declare const getUserEventLabel: (userEvent: string, trans: TranslateFn) => string;
27
+ /** Describes a user-attribute or user-event condition, e.g. "Users' last viewed 3 items". */
28
+ export declare const getUserContextValue: (condition: RrsDetailCondition, trans: TranslateFn) => string;
29
+ /** Renders a `7d`-style duration as " in last 7 days", or '' when absent or malformed. */
30
+ export declare const getDurationSuffix: (duration: string | undefined, timeUnitOptions: TimeUnitOption[], trans: TranslateFn) => string;
31
+ export interface SuitableValueParams {
32
+ condition: RrsDetailCondition;
33
+ selectedOperator: string;
34
+ filterValue: string;
35
+ timeUnit: string;
36
+ inBetweenValues: string[];
37
+ timeUnitOptions: TimeUnitOption[];
38
+ isDateAttribute: () => boolean;
39
+ isMultiSelect: () => boolean;
40
+ isInOrNotInOperator: () => boolean;
41
+ trans: TranslateFn;
42
+ }
43
+ export declare const bracketJoin: (items: string[], and: string) => string;
44
+ /**
45
+ * A multi-select condition stores its values either as a JSON array or, on older
46
+ * strategies, as a bare comma-separated string. Both must humanize the same way.
47
+ */
48
+ export declare const parseMultiSelectValue: (value: string) => string[];
49
+ export declare function getSuitableValue(params: SuitableValueParams): string;
50
+ export {};
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Smart Recommender pages live outside the editor. The task spec is explicit that
3
+ * Create and Edit open in the *same* tab and that the flow finishes over there —
4
+ * there is no return trip, so nothing is stashed before leaving.
5
+ *
6
+ * ponytail: a full page load, not a router push. Guido has no router and is
7
+ * embedded in inone; whatever unload handling the host registers still applies.
8
+ */
9
+ export declare const navigateToStrategyPage: (path: string) => void;
10
+ export declare const buildStrategyEditPath: (id: string | number) => string;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Human-readable summary of a Reusable Recommendation Strategy (RRS).
3
+ *
4
+ * Ported from discovery-strategies-fe
5
+ * `src/components/atoms/GptAppBuilder/StrategyInfoBoxContent.composition.vue`.
6
+ *
7
+ * The source is a Vue SFC whose template is fourteen lines of plain `<div>`s over
8
+ * a `{ title, value }[]` computed. Only the computed carries meaning, so the port
9
+ * is a pure function instead: the panel renders it as an HTML string and the
10
+ * detail drawer renders it as components, both from this one implementation.
11
+ *
12
+ * Produces four rows — Algorithms and Method, Exclusions, Filters, Manual
13
+ * Merchandising — each truncated with "and N more." and falling back to
14
+ * `recommendation-strategy.none` when empty.
15
+ *
16
+ * `trans` is injected rather than pulled from `useTranslations()` so this stays a
17
+ * pure function: no composable lifetime to reason about, and tests need no config.
18
+ */
19
+ import type { RrsStrategy, RrsSummaryRow } from '@@/Types/recommendation';
20
+ /** Translation lookup, matching `useTranslations().trans`. */
21
+ type TranslateFn = (key: string, params?: Record<string, string | number | boolean>) => string;
22
+ /**
23
+ * `TOP_SELLERS` -> `recommendation-algorithm-names.top-sellers`.
24
+ * A pure string transform — Smart Recommender has no algorithm lookup table.
25
+ */
26
+ export declare const getAlgorithmTranslationKey: (algorithm: string) => string;
27
+ export declare const getMethodTranslationKey: (algorithm: string) => string;
28
+ /**
29
+ * Builds the four-row summary shown beside the strategy dropdown.
30
+ * @param strategy - A strategy row as returned by the RRS listing endpoint.
31
+ * @param trans - Translation lookup, e.g. `useTranslations().trans`.
32
+ */
33
+ export declare const buildStrategySummary: (strategy: RrsStrategy, trans: TranslateFn) => RrsSummaryRow[];
34
+ export {};
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Placeholder substitution for a strategy's product-feed URL.
3
+ *
4
+ * Smart Recommender's `endpoint-generate` answers one template per strategy with
5
+ * tokens left in it. The same template drives two consumers with different rules,
6
+ * which is why this lives outside `useRecommendation` (the store would otherwise
7
+ * import the composable that imports the store):
8
+ *
9
+ * compile — the URL is baked into the email. Per-recipient tokens must survive
10
+ * as merge tags, and anything we cannot resolve is left for the ESP.
11
+ * preview — the URL is fetched right now, in the editor. Per-recipient tokens
12
+ * have no value yet, and a leftover `{token}` would be sent literally,
13
+ * so those params are dropped.
14
+ */
15
+ /**
16
+ * Tokens carrying a value the editor knows. Two spellings exist in the wild for
17
+ * the same thing — the web runtime's templates write `{language}`/`{partnerId}`,
18
+ * the Smart Recommender previewer writes `{locale}`/`{partnerName}` — so both are
19
+ * substituted rather than guessing which one a given template used.
20
+ */
21
+ declare const RESOLVED_PLACEHOLDERS: {
22
+ readonly LOCALE: readonly ["{locale}", "{language}"];
23
+ readonly CURRENCY: readonly ["{currency}"];
24
+ readonly CAMPAIGN_ID: readonly ["{campaignId}"];
25
+ readonly STRATEGY_ID: readonly ["{strategyId}"];
26
+ readonly CLIENT_ID: readonly ["{clientId}"];
27
+ readonly PARTNER_NAME: readonly ["{partnerName}", "{partnerId}"];
28
+ readonly SIZE: readonly ["{size}"];
29
+ };
30
+ export type StrategyUrlValues = Record<keyof typeof RESOLVED_PLACEHOLDERS, string>;
31
+ export type StrategyUrlMode = 'compile' | 'preview';
32
+ /**
33
+ * Collect the token values from the block's config plus the editor's own context.
34
+ *
35
+ * Shared so the compiled URL and the canvas preview cannot drift: the preview is
36
+ * only trustworthy if it is the *same* URL the email will carry.
37
+ */
38
+ export declare const buildStrategyUrlValues: (block: {
39
+ language: string;
40
+ currencyCode: string;
41
+ size: string;
42
+ strategyId: string;
43
+ }) => StrategyUrlValues;
44
+ /**
45
+ * Substitute the editor-owned tokens in a strategy feed template.
46
+ *
47
+ * Unknown tokens are preserved in `compile` mode — an unknown token means someone
48
+ * downstream owns it, and blanking it would silently corrupt the feed URL.
49
+ */
50
+ export declare const resolveStrategyUrl: (template: string, values: StrategyUrlValues, mode: StrategyUrlMode) => string;
51
+ export {};
@@ -7,13 +7,20 @@ import type { Currency, Languages } from '@@/Types/recommendation';
7
7
  export interface ExtensionStoreSlice {
8
8
  languages: Languages;
9
9
  currencyList: Currency[];
10
+ /** Whether the `reusableRecommendationStrategy` feature is enabled. */
11
+ isRrsEnabled: boolean;
12
+ /** Ids of the strategies Smart Recommender currently offers for email. */
13
+ strategyIds: string[];
14
+ /** False while the strategy listing is unavailable, when nothing can be judged. */
15
+ canValidateStrategy: boolean;
10
16
  }
11
17
  export interface RequiredField {
12
18
  key: string;
13
19
  canBeEmpty?: boolean;
20
+ optional?: boolean;
14
21
  getValue: (config: PerBlockConfigs) => string;
15
22
  getAvailableOptions?: (store: ExtensionStoreSlice) => string[];
16
- condition?: (config: PerBlockConfigs) => boolean;
23
+ condition?: (config: PerBlockConfigs, store: ExtensionStoreSlice) => boolean;
17
24
  }
18
25
  export declare const REQUIRED_RECOMMENDATION_FIELDS: RequiredField[];
19
26
  export declare const RecommendationRequiredFieldsKey = "newsletter.recommendation-fill-required-fields";
@@ -28,12 +28,15 @@ interface IconButtonProps {
28
28
  name: string;
29
29
  icon: string;
30
30
  className?: string;
31
+ id?: string;
31
32
  }
32
33
  interface SelectProps {
33
34
  name: string;
34
35
  placeholder: string;
35
36
  options: TextValueObject[];
36
37
  className?: string;
38
+ /** Stripo's built-in filter box. Always shown when on — its threshold defaults to 0. */
39
+ searchable?: boolean;
37
40
  }
38
41
  interface CounterProps {
39
42
  name: string;
@@ -105,7 +108,7 @@ export declare abstract class CommonControl extends Control {
105
108
  text: string;
106
109
  value: string;
107
110
  }): string;
108
- _GuSelect({ name, placeholder, options, className }: SelectProps): string;
111
+ _GuSelect({ name, placeholder, options, className, searchable }: SelectProps): string;
109
112
  _GuTextInput({ name, placeholder, className, disabled }: TextInputProps): string;
110
113
  _GuCounter({ name, maxValue, minValue, step }: CounterProps): string;
111
114
  _GuRadioButtonItem({ text, value, icon }: {
@@ -121,7 +124,7 @@ export declare abstract class CommonControl extends Control {
121
124
  * @param param0
122
125
  * @returns It returns a button with an icon.
123
126
  */
124
- _GuIconButton({ name, icon, className }: IconButtonProps): string;
127
+ _GuIconButton({ name, icon, className, id }: IconButtonProps): string;
125
128
  _GuOneColumn(children: string[], className?: string): string;
126
129
  _GuTwoColumns(children: string[], className?: string): string;
127
130
  /**
@@ -0,0 +1,2 @@
1
+ declare const _default: import("msw").HttpHandler[];
2
+ export default _default;
@@ -1,6 +1,14 @@
1
- import type { InitialResponse, FiltersResponse, RecommendationProduct, RecommendationProductsParams } from '@@/Types/recommendation';
1
+ import type { InitialResponse, FiltersResponse, RecommendationProduct, RecommendationProductsParams, RrsCampaign, RrsStrategy, RrsStrategyUrl } from '@@/Types/recommendation';
2
+ /** Translation lookup, matching `useTranslations()`. */
3
+ type TranslateFn = (key: string, params?: Record<string, string | number | boolean>) => string;
2
4
  export declare const useRecommendationApi: () => {
5
+ duplicateStrategy: (strategyId: string) => Promise<string | null>;
3
6
  fetchRecommendationCreateData: () => Promise<InitialResponse>;
4
7
  fetchRecommendationFilters: () => Promise<FiltersResponse>;
5
8
  fetchRecommendationProducts: (strategy: string, params: RecommendationProductsParams) => Promise<RecommendationProduct[]>;
9
+ fetchRecommendationProductsByUrl: (url: string) => Promise<RecommendationProduct[]>;
10
+ fetchRecommendationStrategies: () => Promise<RrsStrategy[]>;
11
+ fetchStrategyCampaigns: (strategyId: string, trans: TranslateFn) => Promise<RrsCampaign[]>;
12
+ generateStrategyEndpoint: (strategy: RrsStrategy, campaignId: string) => Promise<RrsStrategyUrl | null>;
6
13
  };
14
+ export {};
@@ -101,6 +101,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
101
101
  modulesDisabled: boolean;
102
102
  liquidSyntax: boolean;
103
103
  autosave: boolean;
104
+ reusableRecommendationStrategy: boolean;
104
105
  };
105
106
  blocks: {
106
107
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -238,6 +239,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
238
239
  modulesDisabled: boolean;
239
240
  liquidSyntax: boolean;
240
241
  autosave: boolean;
242
+ reusableRecommendationStrategy: boolean;
241
243
  };
242
244
  blocks: {
243
245
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -375,6 +377,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
375
377
  modulesDisabled: boolean;
376
378
  liquidSyntax: boolean;
377
379
  autosave: boolean;
380
+ reusableRecommendationStrategy: boolean;
378
381
  };
379
382
  blocks: {
380
383
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -512,6 +515,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
512
515
  modulesDisabled: boolean;
513
516
  liquidSyntax: boolean;
514
517
  autosave: boolean;
518
+ reusableRecommendationStrategy: boolean;
515
519
  };
516
520
  blocks: {
517
521
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -649,6 +653,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
649
653
  modulesDisabled: boolean;
650
654
  liquidSyntax: boolean;
651
655
  autosave: boolean;
656
+ reusableRecommendationStrategy: boolean;
652
657
  };
653
658
  blocks: {
654
659
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -786,6 +791,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
786
791
  modulesDisabled: boolean;
787
792
  liquidSyntax: boolean;
788
793
  autosave: boolean;
794
+ reusableRecommendationStrategy: boolean;
789
795
  };
790
796
  blocks: {
791
797
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -923,6 +929,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
923
929
  modulesDisabled: boolean;
924
930
  liquidSyntax: boolean;
925
931
  autosave: boolean;
932
+ reusableRecommendationStrategy: boolean;
926
933
  };
927
934
  blocks: {
928
935
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1060,6 +1067,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1060
1067
  modulesDisabled: boolean;
1061
1068
  liquidSyntax: boolean;
1062
1069
  autosave: boolean;
1070
+ reusableRecommendationStrategy: boolean;
1063
1071
  };
1064
1072
  blocks: {
1065
1073
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1197,6 +1205,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1197
1205
  modulesDisabled: boolean;
1198
1206
  liquidSyntax: boolean;
1199
1207
  autosave: boolean;
1208
+ reusableRecommendationStrategy: boolean;
1200
1209
  };
1201
1210
  blocks: {
1202
1211
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1334,6 +1343,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1334
1343
  modulesDisabled: boolean;
1335
1344
  liquidSyntax: boolean;
1336
1345
  autosave: boolean;
1346
+ reusableRecommendationStrategy: boolean;
1337
1347
  };
1338
1348
  blocks: {
1339
1349
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1471,6 +1481,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1471
1481
  modulesDisabled: boolean;
1472
1482
  liquidSyntax: boolean;
1473
1483
  autosave: boolean;
1484
+ reusableRecommendationStrategy: boolean;
1474
1485
  };
1475
1486
  blocks: {
1476
1487
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1608,6 +1619,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1608
1619
  modulesDisabled: boolean;
1609
1620
  liquidSyntax: boolean;
1610
1621
  autosave: boolean;
1622
+ reusableRecommendationStrategy: boolean;
1611
1623
  };
1612
1624
  blocks: {
1613
1625
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1745,6 +1757,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1745
1757
  modulesDisabled: boolean;
1746
1758
  liquidSyntax: boolean;
1747
1759
  autosave: boolean;
1760
+ reusableRecommendationStrategy: boolean;
1748
1761
  };
1749
1762
  blocks: {
1750
1763
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -1882,6 +1895,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
1882
1895
  modulesDisabled: boolean;
1883
1896
  liquidSyntax: boolean;
1884
1897
  autosave: boolean;
1898
+ reusableRecommendationStrategy: boolean;
1885
1899
  };
1886
1900
  blocks: {
1887
1901
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -2019,6 +2033,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2019
2033
  modulesDisabled: boolean;
2020
2034
  liquidSyntax: boolean;
2021
2035
  autosave: boolean;
2036
+ reusableRecommendationStrategy: boolean;
2022
2037
  };
2023
2038
  blocks: {
2024
2039
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -2156,6 +2171,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2156
2171
  modulesDisabled: boolean;
2157
2172
  liquidSyntax: boolean;
2158
2173
  autosave: boolean;
2174
+ reusableRecommendationStrategy: boolean;
2159
2175
  };
2160
2176
  blocks: {
2161
2177
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -2293,6 +2309,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2293
2309
  modulesDisabled: boolean;
2294
2310
  liquidSyntax: boolean;
2295
2311
  autosave: boolean;
2312
+ reusableRecommendationStrategy: boolean;
2296
2313
  };
2297
2314
  blocks: {
2298
2315
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -2430,6 +2447,7 @@ export declare const useConfigStore: import("pinia").StoreDefinition<"guido-conf
2430
2447
  modulesDisabled: boolean;
2431
2448
  liquidSyntax: boolean;
2432
2449
  autosave: boolean;
2450
+ reusableRecommendationStrategy: boolean;
2433
2451
  };
2434
2452
  blocks: {
2435
2453
  excludeDefaults: ("amp-accordion" | "amp-carousel" | "amp-form-controls" | "banner-block" | "button-block" | "html-block" | "image-block" | "menu-block" | "social-block" | "spacer-block" | "text-block" | "timer-block" | "video-block")[];
@@ -25,3 +25,12 @@ export declare const getCsrfToken: () => string;
25
25
  export declare const getUrlParams: () => URLSearchParams;
26
26
  export declare const getUrlParam: (paramName: string, defaultValue?: string) => string;
27
27
  export declare const replaceString: (string?: string, values?: Record<string, string | number>, isRemoveEmptyValues?: boolean) => string;
28
+ /**
29
+ * Parses a JSON-string field, yielding `fallback` on absent or malformed input.
30
+ *
31
+ * Smart Recommender returns several strategy fields (`filters`, `base_product`, ...)
32
+ * as embedded JSON strings, and every surface that reads them must degrade to a
33
+ * sensible empty value rather than break. Shared so a hardening change (rejecting
34
+ * non-object payloads, logging a malformed blob) lands on all of them at once.
35
+ */
36
+ export declare const parseJsonField: <T>(raw: string | undefined, fallback: T) => T;
@@ -3,8 +3,12 @@ const n = `.base-input {
3
3
  border-radius: 4px;
4
4
  background-color: var(--guido-color-gray-0);
5
5
  align-items: center;
6
- height: 40px;
7
- max-height: 40px;
6
+ /* 40px is a floor, never a cap: \`.base-input\` is shared by every settings field,
7
+ including Stripo's own auto-height inputs (e.g. the link field) that expand on
8
+ focus. A fixed max-height clamped their inner box; keep 40px only as the floor. */
9
+ min-height: 40px;
10
+ height: auto;
11
+ max-height: none;
8
12
  box-sizing: content-box;
9
13
  outline: none;
10
14
  resize: vertical;
@@ -36,11 +40,6 @@ ue-contenteditable .base-input {
36
40
  line-height: 24px;
37
41
  }
38
42
 
39
- /* Image link input is auto-height; lift the fixed 40px cap so it can grow. */
40
- ue-contenteditable.link-autoheight-contenteditable .base-input {
41
- max-height: none;
42
- }
43
-
44
43
  ue-icon-component.icon-button.icon-clear-input {
45
44
  right: 2px;
46
45
  top: 2px;
@@ -1,10 +1,19 @@
1
- import { DEFAULT_LOCALE as r, DEFAULT as o } from "../enums/date.js";
2
- const c = () => {
1
+ import { DEFAULT_LOCALE as r, DEFAULT as a, DEFAULT_TZ as c } from "../enums/date.js";
2
+ const m = (t) => t ? t instanceof Date ? t : typeof t == "string" ? t.length === 10 && /^\d{10}$/.test(t) ? new Date(Number(t) * 1e3) : new Date(t) : typeof t == "number" ? t.toString().length === 10 ? new Date(t * 1e3) : new Date(t) : /* @__PURE__ */ new Date() : /* @__PURE__ */ new Date(), s = () => {
3
3
  const t = window.l10n;
4
- return (t == null ? void 0 : t.locale) === o ? r : (t == null ? void 0 : t.locale) || r;
5
- };
6
- new Intl.DateTimeFormat().resolvedOptions().timeZone;
7
- const i = (t) => {
4
+ return (t == null ? void 0 : t.locale) === a ? r : (t == null ? void 0 : t.locale) || r;
5
+ }, u = new Intl.DateTimeFormat().resolvedOptions().timeZone, f = () => {
6
+ const t = window.l10n;
7
+ return (t == null ? void 0 : t.timezone) || u || c;
8
+ }, D = (t, e = s(), n = f()) => {
9
+ const o = {
10
+ year: "numeric",
11
+ month: "2-digit",
12
+ day: "2-digit",
13
+ timeZone: n
14
+ }, i = m(t);
15
+ return new Intl.DateTimeFormat(e, o).format(i);
16
+ }, T = (t) => {
8
17
  if (!t)
9
18
  return "";
10
19
  const e = new Date(t);
@@ -16,9 +25,13 @@ const i = (t) => {
16
25
  second: "2-digit",
17
26
  hour12: !1
18
27
  }).format(e);
19
- }, m = (t) => t ? Math.floor(Date.now() / 1e3) >= t : !1;
28
+ }, h = (t) => t ? Math.floor(Date.now() / 1e3) >= t : !1;
20
29
  export {
21
- i as formatPatchDate,
22
- m as isAfterDate,
23
- c as locale
30
+ m as convertToDateObject,
31
+ T as formatPatchDate,
32
+ D as formatShortDate,
33
+ h as isAfterDate,
34
+ u as localTz,
35
+ s as locale,
36
+ f as timezone
24
37
  };
@@ -58,11 +58,20 @@ const o = (l) => {
58
58
  }, i = () => {
59
59
  var l;
60
60
  return ((l = document.head.querySelector('meta[name="csrf-token"]')) == null ? void 0 : l.getAttribute("content")) ?? "";
61
+ }, k = (l, s) => {
62
+ if (!l)
63
+ return s;
64
+ try {
65
+ return JSON.parse(l);
66
+ } catch {
67
+ return s;
68
+ }
61
69
  };
62
70
  export {
63
71
  v as buildMergeTagEntries,
64
72
  f as dynamicContentToMergeTags,
65
73
  b as flattenDynamicContentList,
66
74
  i as getCsrfToken,
67
- o as mergeTagToDynamicContent
75
+ o as mergeTagToDynamicContent,
76
+ k as parseJsonField
68
77
  };