@useinsider/guido 3.14.0-beta.1e474dd → 3.14.0-beta.38ec3aa

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 (27) hide show
  1. package/dist/composables/useEmailTemplateApplier.js +46 -32
  2. package/dist/composables/useHtmlValidator.js +50 -50
  3. package/dist/config/i18n/en/labels.json.js +3 -7
  4. package/dist/config/migrator/recommendation/compositionMapper.js +23 -26
  5. package/dist/config/migrator/recommendation/htmlBuilder.js +155 -156
  6. package/dist/extensions/Blocks/Recommendation/constants/selectors.js +13 -15
  7. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +314 -346
  8. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +43 -44
  9. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +16 -16
  10. package/dist/extensions/Blocks/Recommendation/templates/list/template.js +16 -16
  11. package/dist/extensions/Blocks/Recommendation/templates/utils.js +120 -120
  12. package/dist/extensions/Blocks/Recommendation/utils/captureStyleTemplates.js +54 -55
  13. package/dist/extensions/Blocks/common-control.js +35 -42
  14. package/dist/src/composables/useHtmlValidator.d.ts +2 -3
  15. package/dist/src/config/migrator/recommendation/types.d.ts +0 -1
  16. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  17. package/dist/src/extensions/Blocks/Recommendation/constants/selectors.d.ts +0 -4
  18. package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +5 -22
  19. package/dist/src/extensions/Blocks/Recommendation/templates/utils.d.ts +11 -12
  20. package/dist/src/extensions/Blocks/common-control.d.ts +1 -3
  21. package/dist/src/stores/dynamic-content.d.ts +8 -0
  22. package/dist/src/utils/registerUsedDynamicContent.d.ts +8 -0
  23. package/dist/stores/dynamic-content.js +12 -2
  24. package/dist/utils/registerUsedDynamicContent.js +23 -0
  25. package/package.json +1 -1
  26. package/dist/extensions/Blocks/Recommendation/utils/compositionKeys.js +0 -89
  27. package/dist/src/extensions/Blocks/Recommendation/utils/compositionKeys.d.ts +0 -52
@@ -47,15 +47,15 @@ class d extends I {
47
47
  const t = this.getBlockInstanceId();
48
48
  if (!t)
49
49
  return !1;
50
- const E = t !== this.lastBlockInstanceId;
51
- return e(), E && (this.lastBlockInstanceId = t), E;
50
+ const o = t !== this.lastBlockInstanceId;
51
+ return e(), o && (this.lastBlockInstanceId = t), o;
52
52
  }
53
- _GuLabel({ text: e, name: t = "", hint: E }) {
53
+ _GuLabel({ text: e, name: t = "", hint: o }) {
54
54
  return `
55
55
  <${n.LABEL}
56
56
  ${$.LABEL.text}="${e}"
57
57
  ${$.LABEL.name}="${t || `${e} Label`}"
58
- ${E ? `${$.LABEL.hint}="${E}"` : ""}>
58
+ ${o ? `${$.LABEL.hint}="${o}"` : ""}>
59
59
  </${n.LABEL}>
60
60
  `;
61
61
  }
@@ -73,7 +73,7 @@ class d extends I {
73
73
  * Use in getTemplate() — the icon is registered in a hidden store so Stripo initializes it.
74
74
  * Pair with _setInfoMessageValue() in onRender() to set the text content.
75
75
  */
76
- _GuOnPageMessage({ name: e, icon: t = "not-found", type: E = "info" }) {
76
+ _GuOnPageMessage({ name: e, icon: t = "not-found", type: o = "info" }) {
77
77
  return `
78
78
  <div data-info-message="${e}" style="display: none; padding: 16px 16px 0;">
79
79
  <div class="icon-store" style="display: none;">
@@ -81,7 +81,7 @@ class d extends I {
81
81
  ${this._GuIcon({ src: t, className: "icon" })}
82
82
  </div>
83
83
  </div>
84
- ${this._GuMessage({ name: e, type: E })}
84
+ ${this._GuMessage({ name: e, type: o })}
85
85
  </div>
86
86
  `;
87
87
  }
@@ -91,7 +91,7 @@ class d extends I {
91
91
  * and combines it with the text in Stripo's alert-message layout.
92
92
  */
93
93
  _setInfoMessageValue(e, t) {
94
- const E = this.getContainer(), o = E.querySelector(`[data-icon-key="${e}"]`), a = o == null ? void 0 : o.querySelector("ue-icon-component"), l = (a == null ? void 0 : a.outerHTML) ?? "";
94
+ const o = this.getContainer(), E = o.querySelector(`[data-icon-key="${e}"]`), a = E == null ? void 0 : E.querySelector("ue-icon-component"), l = (a == null ? void 0 : a.outerHTML) ?? "";
95
95
  this.api.setUIEAttribute(
96
96
  e,
97
97
  "value",
@@ -104,7 +104,7 @@ class d extends I {
104
104
  </div>
105
105
  `
106
106
  );
107
- const T = E.querySelector(`[data-info-message="${e}"]`);
107
+ const T = o.querySelector(`[data-info-message="${e}"]`);
108
108
  T && (T.style.display = "");
109
109
  }
110
110
  _GuToggle(e) {
@@ -121,66 +121,59 @@ class d extends I {
121
121
  ${$.SELECT_ITEM.value}="${t}">
122
122
  </${n.SELECT_ITEM}>`;
123
123
  }
124
- _GuSelect({
125
- name: e,
126
- placeholder: t,
127
- options: E,
128
- className: o = "es-180w",
129
- searchable: a = !1
130
- }) {
124
+ _GuSelect({ name: e, placeholder: t, options: o, className: E = "es-180w" }) {
131
125
  return `
132
126
  <${n.SELECTPICKER}
133
- class="${o}"
127
+ class="${E}"
134
128
  ${$.SELECTPICKER.name}="${e}"
135
- ${a ? `${$.SELECTPICKER.searchable}="true"` : ""}
136
129
  ${$.SELECTPICKER.placeholder}="${t}">
137
- ${E.map((l) => this._GuSelectItem(l)).join("")}
130
+ ${o.map((a) => this._GuSelectItem(a)).join("")}
138
131
  </${n.SELECTPICKER}>
139
132
  `;
140
133
  }
141
- _GuTextInput({ name: e, placeholder: t, className: E = "", disabled: o = !1 }) {
134
+ _GuTextInput({ name: e, placeholder: t, className: o = "", disabled: E = !1 }) {
142
135
  return `
143
136
  <${n.TEXT}
144
- class=${E}
137
+ class=${o}
145
138
  ${$.TEXT.name}="${e}"
146
139
  placeholder="${t || e}"
147
- ${o ? `${$.TEXT.disabled}="true"` : ""}>
140
+ ${E ? `${$.TEXT.disabled}="true"` : ""}>
148
141
  </${n.TEXT}>
149
142
  `;
150
143
  }
151
- _GuCounter({ name: e, maxValue: t, minValue: E = 1, step: o = 1 }) {
144
+ _GuCounter({ name: e, maxValue: t, minValue: o = 1, step: E = 1 }) {
152
145
  return `
153
146
  <${n.COUNTER}
154
147
  ${$.COUNTER.name}="${e}"
155
- ${$.COUNTER.minValue}="${E}"
148
+ ${$.COUNTER.minValue}="${o}"
156
149
  ${$.COUNTER.maxValue}="${t}"
157
- ${$.COUNTER.step}="${o}">
150
+ ${$.COUNTER.step}="${E}">
158
151
  </${n.COUNTER}>
159
152
  `;
160
153
  }
161
- _GuRadioButtonItem({ text: e, value: t, icon: E }) {
154
+ _GuRadioButtonItem({ text: e, value: t, icon: o }) {
162
155
  return `
163
156
  <${n.RADIO_ITEM}
164
157
  ${$.RADIO_ITEM.value}="${t}"
165
158
  ${e ? `${$.RADIO_ITEM.text}="${e}"` : ""}
166
- ${E ? `${$.RADIO_ITEM.icon}="${E}"` : ""}>
159
+ ${o ? `${$.RADIO_ITEM.icon}="${o}"` : ""}>
167
160
  </${n.RADIO_ITEM}>
168
161
  `;
169
162
  }
170
- _GuRadioButton({ name: e, buttons: t, id: E = "" }) {
163
+ _GuRadioButton({ name: e, buttons: t, id: o = "" }) {
171
164
  return `
172
165
  <${n.RADIO_BUTTONS}
173
- ${E ? `id="${E}"` : ""}
166
+ ${o ? `id="${o}"` : ""}
174
167
  ${$.RADIO_BUTTONS.name}="${e}">
175
- ${t.map((o) => this._GuRadioButtonItem(o)).join("")}
168
+ ${t.map((E) => this._GuRadioButtonItem(E)).join("")}
176
169
  </${n.RADIO_BUTTONS}>
177
170
  `;
178
171
  }
179
- _GuButton({ name: e, label: t, id: E = "" }) {
172
+ _GuButton({ name: e, label: t, id: o = "" }) {
180
173
  return `
181
174
  <${n.BUTTON}
182
175
  ${$.BUTTON.name}="${e}"
183
- ${E ? `id="${E}"` : ""}
176
+ ${o ? `id="${o}"` : ""}
184
177
  ${$.BUTTON.caption}="${t}"}>
185
178
  </${n.BUTTON}>
186
179
  `;
@@ -198,10 +191,10 @@ class d extends I {
198
191
  * @param param0
199
192
  * @returns It returns a button with an icon.
200
193
  */
201
- _GuIconButton({ name: e, icon: t, className: E = "" }) {
194
+ _GuIconButton({ name: e, icon: t, className: o = "" }) {
202
195
  return `
203
196
  <${n.BUTTON}
204
- class="${E}"
197
+ class="${o}"
205
198
  ${$.BUTTON.name}="${e}"
206
199
  ${$.BUTTON.icon}="${t}">
207
200
  </${n.BUTTON}>
@@ -229,19 +222,19 @@ class d extends I {
229
222
  * @returns HTML string for the orderable control
230
223
  */
231
224
  _GuOrderable(e, t) {
232
- let E = "";
225
+ let o = "";
233
226
  t.forEach((a) => {
234
227
  const l = $.ORDERABLE_ITEM && "name" in $.ORDERABLE_ITEM ? $.ORDERABLE_ITEM.name : "name";
235
- E += `
228
+ o += `
236
229
  <${n.ORDERABLE_ITEM} ${l}="${a.key}">
237
230
  ${a.content}
238
231
  </${n.ORDERABLE_ITEM}>
239
232
  `;
240
233
  });
241
- const o = $.ORDERABLE && "name" in $.ORDERABLE ? $.ORDERABLE.name : "name";
234
+ const E = $.ORDERABLE && "name" in $.ORDERABLE ? $.ORDERABLE.name : "name";
242
235
  return `
243
- <${n.ORDERABLE} ${o}="${e}">
244
- ${E}
236
+ <${n.ORDERABLE} ${E}="${e}">
237
+ ${o}
245
238
  </${n.ORDERABLE}>
246
239
  `;
247
240
  }
@@ -282,16 +275,16 @@ class d extends I {
282
275
  `;
283
276
  }
284
277
  _GuRadioButtons(e, t) {
285
- const E = t.map((o) => `
278
+ const o = t.map((E) => `
286
279
  <${n.RADIO_ITEM}
287
- ${$.RADIO_ITEM.text}="${o.text}"
288
- ${$.RADIO_ITEM.value}="${o.value}">
280
+ ${$.RADIO_ITEM.text}="${E.text}"
281
+ ${$.RADIO_ITEM.value}="${E.value}">
289
282
  </${n.RADIO_ITEM}>
290
283
  `).join("");
291
284
  return `
292
285
  <${n.RADIO_BUTTONS}
293
286
  ${$.RADIO_BUTTONS.name}="${e}">
294
- ${E}
287
+ ${o}
295
288
  </${n.RADIO_BUTTONS}>
296
289
  `;
297
290
  }
@@ -14,9 +14,8 @@ export declare function parseRecommendationVariable(field: string): {
14
14
  * `{{recoId_index_attribute}}` variables: the built-in compiler attributes plus
15
15
  * each account attribute in its canonical token form — bare for
16
16
  * `defaultAttribute`, `product_attribute.<name>` for `productAttribute`. Using
17
- * `filterToProductAttrValue` (the same producer the block builder uses) keeps the
18
- * validator's notion of "valid form" identical to what is actually emitted, and
19
- * admits both forms when a default and a custom attribute share a name.
17
+ * `resolveProductAttrValue` (the same producer the block builder uses) keeps the
18
+ * validator's notion of "valid form" identical to what is actually emitted.
20
19
  */
21
20
  export declare function buildPartnerAttributeNameSet(filterList: FiltersResponse): Set<string>;
22
21
  /**
@@ -193,7 +193,6 @@ export type PerElementStyles = Record<string, MappedTextStyle | MappedButtonStyl
193
193
  export interface MappedComposition {
194
194
  composition: string[];
195
195
  visibility: Record<string, boolean>;
196
- /** Canonical `product-attr` values, mirrored into `data-custom-attributes`. */
197
196
  customAttributes: string[];
198
197
  /** Mapping of customAttr key → full `product-attr` value. */
199
198
  customAttrValues: Record<string, string>;
@@ -8,6 +8,6 @@
8
8
  */
9
9
  export { RecommendationBlockId } from './blockIds';
10
10
  export { RecommendationControlId } from './controlIds';
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_CUSTOM_PREFIX, ATTR_DATA_CUSTOM_ATTRIBUTES, ATTR_PRODUCT_ATTR, SELECTOR_ATTRIBUTE_ROW, ATTR_DATA_ATTRIBUTE_TYPE, PRODUCT_ATTRIBUTE_PREFIX, BUILT_IN_DEFAULT_ATTRIBUTES, } from './selectors';
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_CUSTOM_PREFIX, ATTR_DATA_CUSTOM_ATTRIBUTES, ATTR_PRODUCT_ATTR, 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
13
  export { DEFAULT_NODE_CONFIG, DEFAULT_CURRENCY, DEFAULT_COMPOSITION, DEFAULT_VISIBILITY, CURRENT_CONFIG_VERSION, EXCLUDED_ALGORITHM_IDS, } from './defaultConfig';
@@ -68,10 +68,6 @@ export declare const ATTR_CUSTOM_PREFIX = "customAttr:";
68
68
  export declare const ATTR_DATA_CUSTOM_ATTRIBUTES = "data-custom-attributes";
69
69
  /** HTML attribute on <td> elements identifying the product attribute for compiler template variable generation */
70
70
  export declare const ATTR_PRODUCT_ATTR = "product-attr";
71
- /** Row wrapper of one composition entry inside a product card */
72
- export declare const SELECTOR_ATTRIBUTE_ROW = ".recommendation-attribute-row";
73
- /** HTML attribute on an attribute row holding its composition key */
74
- export declare const ATTR_DATA_ATTRIBUTE_TYPE = "data-attribute-type";
75
71
  /** Prefix `resolveProductAttrValue` puts on custom (non-default) product attributes in `product-attr` values */
76
72
  export declare const PRODUCT_ATTRIBUTE_PREFIX = "product_attribute.";
77
73
  /**
@@ -29,8 +29,6 @@ export declare class RecommendationCardCompositionControl extends CommonControl
29
29
  private _initializeComposition;
30
30
  private _registerValueChangeListeners;
31
31
  private _readCompositionFromNode;
32
- /** Upgrades legacy bare-name custom keys to the canonical form. (SD-147101) */
33
- private _normalizeComposition;
34
32
  private _readCustomAttributesFromNode;
35
33
  private _readVisibilityFromRows;
36
34
  private _getDefaultVisibilities;
@@ -63,15 +61,7 @@ export declare class RecommendationCardCompositionControl extends CommonControl
63
61
  private _createPriceGroupItemHtml;
64
62
  private _createCustomItemHtml;
65
63
  /**
66
- * Dropdown label of an attribute. A partner can own a default and a custom
67
- * attribute under the same name; the type is spelled out only then, so partners
68
- * without a collision keep clean labels. (SD-147101)
69
- */
70
- private _toOptionLabel;
71
- /**
72
- * Builds select options from the store's filterList. Option values are
73
- * `product-attr` values, so a default attribute and a same-named custom one
74
- * never collapse onto a single option. (SD-147101)
64
+ * Builds select options from the store's filterList.
75
65
  * Falls back to a single option for the currently selected attribute.
76
66
  */
77
67
  private _getSelectOptions;
@@ -154,12 +144,6 @@ export declare class RecommendationCardCompositionControl extends CommonControl
154
144
  */
155
145
  private _onCustomAttributeChanged;
156
146
  private _onReorder;
157
- /**
158
- * Outer HTML of an existing attribute row, rewritten to the canonical key when
159
- * the row still carries a legacy bare-name one. Copying rows this way lets the
160
- * DOM converge on the next composition change without writing on open.
161
- */
162
- private _getExistingRowHtml;
163
147
  private _injectCustomAttributeHtml;
164
148
  private _injectGridAttributeRow;
165
149
  private _injectListAttributeRow;
@@ -220,14 +204,13 @@ export declare class RecommendationCardCompositionControl extends CommonControl
220
204
  */
221
205
  private _subscribeToStoreChanges;
222
206
  /**
223
- * Returns filters eligible for the custom attribute dropdown, excluding default
224
- * attributes already covered by built-in toggle items.
207
+ * Returns filters eligible for the custom attribute dropdown,
208
+ * excluding default attributes already covered by built-in toggle items.
225
209
  */
226
210
  private _getAddableFilters;
227
211
  /**
228
- * Looks up the display name for a `product-attr` value from the store's filterList.
229
- * Matches on the canonical value, so a default and a same-named custom attribute
230
- * resolve to their own entry. Falls back to Title Case of the bare name.
212
+ * Looks up the display name for an attribute from the store's filterList.
213
+ * Falls back to Title Case conversion of the snake_case attribute name.
231
214
  */
232
215
  private _getDisplayNameForAttribute;
233
216
  /**
@@ -43,23 +43,22 @@ export declare function resolveInlinePriceOrder(composition: string[]): {
43
43
  */
44
44
  export declare function toDisplayableAttributeValue(value: unknown): string | undefined;
45
45
  /**
46
- * Name-only type lookup — **legacy fallback only**; the canonical path uses
47
- * `isDefaultProductAttr` on the `product-attr` value. A bare name is the canonical
48
- * form of a default attribute, so a duplicated name resolves to the default rather
49
- * than to whichever entry the filter list happens to enumerate first. (SD-147101)
46
+ * Checks whether an attribute is a default (top-level) product attribute
47
+ * vs a custom product attribute (nested under `product_attributes`).
48
+ * Returns false when filterList is empty or the attribute is not found.
50
49
  */
51
50
  export declare function isDefaultAttribute(attrName: string, filterList: FiltersResponse): boolean;
52
51
  /**
53
- * Name-only `product-attr` resolution — **legacy fallback only**, see
54
- * `isDefaultAttribute`. Prefer `filterToProductAttrValue`, which reads the type off
55
- * the filter entry itself.
52
+ * Resolves the `product-attr` HTML attribute value based on attribute type from the filter list.
53
+ * - Default attributes → attribute name directly (e.g., "brand") → compiles to `{{1_0_brand}}`
54
+ * - Product attributes → "product_attribute.<name>" (e.g., "product_attribute.rating_star")
56
55
  */
57
56
  export declare function resolveProductAttrValue(attrName: string, filterList: FiltersResponse): string;
58
57
  /**
59
- * Maps a cell's `product-attr` value to its composition key. The value is the
60
- * canonical identity, so it is carried into the key verbatim — stripping the
61
- * `product_attribute.` prefix here would collapse a default and a same-named
62
- * custom attribute onto one key.
58
+ * Reverse of `resolveProductAttrValue`: maps a cell's `product-attr` value back to its
59
+ * `customAttr:<name>` composition key. The resolver only ever emits `<name>` (default
60
+ * attribute) or `product_attribute.<name>` (custom product attribute), so stripping the
61
+ * prefix recovers the attribute name without needing the store's filter list.
63
62
  */
64
63
  export declare function toCustomCompositionKey(productAttrValue: string): string;
65
64
  /**
@@ -185,7 +184,7 @@ export interface RenderOptions {
185
184
  * `RenderOptions`. Single source for both the stacked per-cell options and the two inline
186
185
  * (price + old-price) option sets, so style capture → re-bake stays consistent across layouts.
187
186
  */
188
- export declare function buildCellOptions(attrType: string, renderOptions: RenderOptions, composition?: string[]): CellRenderOptions;
187
+ export declare function buildCellOptions(attrType: string, renderOptions: RenderOptions): CellRenderOptions;
189
188
  /**
190
189
  * Options for prepareProductRows unified function
191
190
  */
@@ -34,8 +34,6 @@ interface SelectProps {
34
34
  placeholder: string;
35
35
  options: TextValueObject[];
36
36
  className?: string;
37
- /** Adds the picker's built-in search box. Worth it once the list gets long. */
38
- searchable?: boolean;
39
37
  }
40
38
  interface CounterProps {
41
39
  name: string;
@@ -107,7 +105,7 @@ export declare abstract class CommonControl extends Control {
107
105
  text: string;
108
106
  value: string;
109
107
  }): string;
110
- _GuSelect({ name, placeholder, options, className, searchable, }: SelectProps): string;
108
+ _GuSelect({ name, placeholder, options, className }: SelectProps): string;
111
109
  _GuTextInput({ name, placeholder, className, disabled }: TextInputProps): string;
112
110
  _GuCounter({ name, maxValue, minValue, step }: CounterProps): string;
113
111
  _GuRadioButtonItem({ text, value, icon }: {
@@ -36,4 +36,12 @@ export declare const useDynamicContentStore: import("pinia").StoreDefinition<"gu
36
36
  }[];
37
37
  }, {
38
38
  setSelectedDynamicContent(dynamicContent: DynamicContent): void;
39
+ /**
40
+ * Append-only bulk registration for dynamic content used by an
41
+ * AI-applied template. Unlike `setSelectedDynamicContent` it doesn't
42
+ * touch `selectedDynamicContent`; the getter removes duplicates, so
43
+ * re-registering the same entries is harmless. Items are shallow-copied so Pinia
44
+ * reactivity can't write a later mutation back into the host's catalog.
45
+ */
46
+ registerDynamicContent(items: DynamicContent[]): void;
39
47
  }>;
@@ -0,0 +1,8 @@
1
+ import type { DynamicContent } from '@@/Types/generic';
2
+ export declare const extractUsedDynamicContent: (html: string, flattenedCatalog: DynamicContent[] | undefined | null) => DynamicContent[];
3
+ /**
4
+ * Dev-diagnostic sibling of `extractUsedDynamicContent`: the used token names
5
+ * with NO catalog match (so intentionally not registered). Surfaced via a
6
+ * dev-gated `console.debug` to spot a neo↔guido vocabulary mismatch. Never throws.
7
+ */
8
+ export declare const getUnmatchedDynamicContentTokens: (html: string, flattenedCatalog: DynamicContent[] | undefined | null) => string[];
@@ -1,6 +1,6 @@
1
1
  import { removeDuplicatesFromArray as n } from "../utils/arrayUtil.js";
2
2
  import { defineStore as a } from "pinia";
3
- const s = a("guidoDynamicContent", {
3
+ const c = a("guidoDynamicContent", {
4
4
  state: () => ({
5
5
  selectedDynamicContent: { text: "", value: "" },
6
6
  selectedDynamicContentList: []
@@ -8,6 +8,16 @@ const s = a("guidoDynamicContent", {
8
8
  actions: {
9
9
  setSelectedDynamicContent(t) {
10
10
  this.selectedDynamicContent = t, this.selectedDynamicContentList.push(t);
11
+ },
12
+ /**
13
+ * Append-only bulk registration for dynamic content used by an
14
+ * AI-applied template. Unlike `setSelectedDynamicContent` it doesn't
15
+ * touch `selectedDynamicContent`; the getter removes duplicates, so
16
+ * re-registering the same entries is harmless. Items are shallow-copied so Pinia
17
+ * reactivity can't write a later mutation back into the host's catalog.
18
+ */
19
+ registerDynamicContent(t) {
20
+ this.selectedDynamicContentList.push(...t.map((e) => ({ ...e })));
11
21
  }
12
22
  },
13
23
  getters: {
@@ -20,5 +30,5 @@ const s = a("guidoDynamicContent", {
20
30
  }
21
31
  });
22
32
  export {
23
- s as useDynamicContentStore
33
+ c as useDynamicContentStore
24
34
  };
@@ -0,0 +1,23 @@
1
+ import { DATA_ATTRIBUTE_REGEX as T } from "../enums/html-validator.js";
2
+ const d = /{{([a-zA-Z0-9_.\s]*)}}/gm, h = (n, e) => {
3
+ if (!e || e.length === 0)
4
+ return { matched: [], unmatchedTokens: [] };
5
+ const s = n.replace(T, "$1").match(d);
6
+ if (!s)
7
+ return { matched: [], unmatchedTokens: [] };
8
+ const u = new Map(
9
+ e.map((c) => [c.value.trim().toLowerCase(), c])
10
+ ), a = /* @__PURE__ */ new Set(), o = [], m = [];
11
+ return s.forEach((c) => {
12
+ const t = c.slice(2, -2).trim().toLowerCase();
13
+ if (t === "" || a.has(t))
14
+ return;
15
+ a.add(t);
16
+ const r = u.get(t);
17
+ r ? o.push(r) : m.push(t);
18
+ }), { matched: o, unmatchedTokens: m };
19
+ }, E = (n, e) => h(n, e).matched, k = (n, e) => h(n, e).unmatchedTokens;
20
+ export {
21
+ E as extractUsedDynamicContent,
22
+ k as getUnmatchedDynamicContentTokens
23
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "3.14.0-beta.1e474dd",
3
+ "version": "3.14.0-beta.38ec3aa",
4
4
  "description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
5
5
  "main": "./dist/guido.umd.cjs",
6
6
  "module": "./dist/library.js",
@@ -1,89 +0,0 @@
1
- import { ATTR_CUSTOM_PREFIX as i, ATTR_PRODUCT_ATTR as c, PRODUCT_ATTRIBUTE_PREFIX as l, ATTR_DATA_ATTRIBUTE_TYPE as f, SELECTOR_ATTRIBUTE_ROW as R } from "../constants/selectors.js";
2
- function d(t) {
3
- return !t.startsWith(l);
4
- }
5
- function y(t) {
6
- return t.startsWith(l) ? t.substring(l.length) : t;
7
- }
8
- function T(t) {
9
- return t.startsWith(i) ? t.substring(i.length) : t;
10
- }
11
- function A(t) {
12
- return `${i}${t}`;
13
- }
14
- function P(t) {
15
- return t.type === "defaultAttribute" ? t.attributeName : `${l}${t.attributeName}`;
16
- }
17
- function _(t, r) {
18
- const n = Object.values(r).filter((e) => e.attributeName === t);
19
- return n.find((e) => e.type === "defaultAttribute") ?? n[0];
20
- }
21
- function o(t, r) {
22
- return t && "getAttribute" in t ? t.getAttribute(r) : null;
23
- }
24
- function m(t, r, n = {}) {
25
- const e = `${i}${t}`, u = r == null ? void 0 : r.querySelector(
26
- `${R}[${f}="${e}"]`
27
- ), a = o(u, c) ?? o(u == null ? void 0 : u.querySelector(`[${c}]`), c);
28
- if (a)
29
- return a;
30
- const s = _(t, n);
31
- return s ? P(s) : t;
32
- }
33
- function g(t, r, n = {}) {
34
- return t.startsWith(l) ? t : m(t, r, n);
35
- }
36
- function C(t, r, n = {}) {
37
- return t.map((e) => {
38
- if (!e.startsWith(i))
39
- return e;
40
- const u = T(e);
41
- return A(g(u, r, n));
42
- });
43
- }
44
- function E(t, r, n = {}) {
45
- return t.map((e) => g(e, r, n));
46
- }
47
- function S(t) {
48
- const r = o(t, f);
49
- if (!(r != null && r.startsWith(i)))
50
- return r;
51
- const n = "querySelector" in t ? t.querySelector(`[${c}]`) : void 0, e = o(n, c);
52
- return e ? A(e) : r;
53
- }
54
- function $(t, r) {
55
- const n = o(t, c), e = o(t.querySelector(`[${c}]`), c), u = n ?? e;
56
- return u === null || u === r;
57
- }
58
- function W(t, r) {
59
- const n = (h) => t.querySelector(
60
- `${R}[${f}="${h}"]`
61
- );
62
- if (!r.startsWith(i))
63
- return n(r) ?? null;
64
- const e = T(r), u = n(r);
65
- if (u && $(u, e))
66
- return u;
67
- const a = A(y(e)), s = a === r ? void 0 : n(a);
68
- return s && $(s, e) ? s : null;
69
- }
70
- function q(t, r) {
71
- const n = T(r), e = A(y(n));
72
- return e === r ? t : t.replace(
73
- `${f}="${e}"`,
74
- `${f}="${r}"`
75
- );
76
- }
77
- export {
78
- y as bareAttributeName,
79
- T as compositionKeyToProductAttr,
80
- P as filterToProductAttrValue,
81
- W as findAttributeRow,
82
- _ as findFilterByBareName,
83
- d as isDefaultProductAttr,
84
- C as normalizeCompositionKeys,
85
- E as normalizeCustomAttrValues,
86
- A as productAttrToCompositionKey,
87
- S as resolveRowCompositionKey,
88
- q as rewriteLegacyRowKeyHtml
89
- };
@@ -1,52 +0,0 @@
1
- import type { FiltersResponse } from '@@/Types/recommendation';
2
- import type { ImmutableHtmlNode } from '@stripoinc/ui-editor-extensions';
3
- /**
4
- * Canonical identity of a card-composition custom attribute is its `product-attr`
5
- * value — `brand` for a default attribute, `product_attribute.brand` for a custom
6
- * one. A partner can own both under the same name, and only this form tells them
7
- * apart. (SD-147101)
8
- */
9
- type FilterEntry = FiltersResponse[string];
10
- /** True when a `product-attr` value refers to a top-level (default) product field. */
11
- export declare function isDefaultProductAttr(productAttrValue: string): boolean;
12
- /** The bare attribute name behind a `product-attr` value (`product_attribute.brand` → `brand`). */
13
- export declare function bareAttributeName(productAttrValue: string): string;
14
- /** `customAttr:product_attribute.brand` → `product_attribute.brand`. */
15
- export declare function compositionKeyToProductAttr(compositionKey: string): string;
16
- /** `product_attribute.brand` → `customAttr:product_attribute.brand`. */
17
- export declare function productAttrToCompositionKey(productAttrValue: string): string;
18
- /**
19
- * Canonical identity of a filter entry. Reads the type off the entry itself, so
20
- * two same-named filters never collapse onto one value.
21
- */
22
- export declare function filterToProductAttrValue(filter: FilterEntry): string;
23
- /**
24
- * Filter entry behind a bare attribute name. A bare name is the canonical form of a
25
- * DEFAULT attribute, so the default wins a name collision; the custom entry is only
26
- * reached when it is the sole match (a genuinely legacy key). (SD-147101)
27
- */
28
- export declare function findFilterByBareName(bareName: string, filterList: FiltersResponse): FilterEntry | undefined;
29
- /** Composition array with every `customAttr:*` key upgraded to the canonical form. */
30
- export declare function normalizeCompositionKeys(composition: string[], blockNode?: ImmutableHtmlNode | null, filterList?: FiltersResponse): string[];
31
- /**
32
- * `data-custom-attributes` upgraded to canonical values. Index-preserving: the
33
- * Nth entry must keep mapping to the Nth `customAttr:*` composition key.
34
- */
35
- export declare function normalizeCustomAttrValues(values: string[], blockNode?: ImmutableHtmlNode | null, filterList?: FiltersResponse): string[];
36
- /**
37
- * Composition key of an attribute row. Custom rows are keyed by their `product-attr`
38
- * value, which stays correct on rows still tagged with a legacy bare name.
39
- */
40
- export declare function resolveRowCompositionKey(row: ImmutableHtmlNode): string | null;
41
- /**
42
- * Finds an attribute row by composition key, tolerating rows still tagged with the
43
- * legacy bare-name key. Custom candidates are validated against their `product-attr`,
44
- * so a legacy custom `brand` row is never mistaken for the default `brand`.
45
- */
46
- export declare function findAttributeRow(container: ImmutableHtmlNode, compositionKey: string): ImmutableHtmlNode | null;
47
- /**
48
- * Rewrites a copied row's legacy `data-attribute-type` to the canonical key so the
49
- * DOM converges on the user's next composition change (no write on mere open).
50
- */
51
- export declare function rewriteLegacyRowKeyHtml(rowHtml: string, compositionKey: string): string;
52
- export {};