@akinon/pz-theme 2.0.103-rc.0 → 2.0.103

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.
@@ -134,6 +134,40 @@ export const resolveSliderRowProduct = (
134
134
  return { ...item, pk } as ThemeProduct;
135
135
  };
136
136
 
137
+ /**
138
+ * The section data sources whose rows are products.
139
+ *
140
+ * The same declared-not-sniffed rule as the two allow-lists above, applied to
141
+ * a section's own repeat: a custom section iterating a COLLECTION data source
142
+ * is, by the source's definition, a list of commerce products, so a card
143
+ * dropped into it (ZERO-4829's "Product Cards" on any page) gets the same
144
+ * product scope a product grid row gets — and its favourite and add-to-basket
145
+ * address the right product instead of rendering nothing for want of one.
146
+ * A static or API source says nothing about its rows and opens no scope.
147
+ */
148
+ const PRODUCT_ROW_DATA_SOURCE_TYPES = new Set(['collection']);
149
+
150
+ export const publishesProductRows = (
151
+ sectionDataSource: { type?: unknown } | null | undefined
152
+ ): boolean =>
153
+ typeof sectionDataSource?.type === 'string' &&
154
+ PRODUCT_ROW_DATA_SOURCE_TYPES.has(sectionDataSource.type);
155
+
156
+ /**
157
+ * A collection row seen as the ambient product, or null for the padding rows
158
+ * the count floor draws when the source has answered with fewer products.
159
+ */
160
+ export const resolveCollectionRowProduct = (
161
+ item: Record<string, unknown> | null | undefined
162
+ ): ThemeProduct | null => {
163
+ if (!item || Object.keys(item).length === 0) return null;
164
+
165
+ const pk = readProductPk(item);
166
+ if (pk === undefined) return null;
167
+
168
+ return { ...item, pk } as ThemeProduct;
169
+ };
170
+
137
171
  /**
138
172
  * What a product row shows in the editor when the page has no live data.
139
173
  *
@@ -4,6 +4,7 @@ import React from 'react';
4
4
  import ThemeBlock, { Block } from '../theme-block';
5
5
  import {
6
6
  buildIteratorBlock,
7
+ expandNestedIterators,
7
8
  sliceIteratorItems
8
9
  } from '../utils/iterator-utils';
9
10
  import {
@@ -107,7 +108,11 @@ export const ItemTemplateList = ({
107
108
  isDesigner
108
109
  });
109
110
 
110
- const clones = expanded.blocks || [];
111
+ // A repeat inside the row (a colour-swatch strip over `item.colors`) was
112
+ // handed its list while the row was built; it expands here, per clone.
113
+ const clones = (expanded.blocks || []).map((clone) =>
114
+ expandNestedIterators(clone, { isDesigner })
115
+ );
111
116
  // Only lists whose rows ARE products open a scope. An attribute row or a
112
117
  // gallery thumbnail row must keep falling through to the page's product:
113
118
  // those templates live on a PDP, and a scope there — even an empty one —