storefront-layouts 1.0.9 → 1.0.13

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 (108) hide show
  1. package/dist/components/shipping/ProductDeliveryInfoSection.d.ts.map +1 -1
  2. package/dist/components/shipping/ProductDeliveryInfoSection.js +10 -3
  3. package/dist/components/ui/address-selector.d.ts.map +1 -1
  4. package/dist/components/ui/address-selector.js +4 -3
  5. package/dist/components/ui/button.js +1 -1
  6. package/dist/components/ui/checkout-button.d.ts.map +1 -1
  7. package/dist/components/ui/checkout-button.js +2 -1
  8. package/dist/components/ui/product-card.d.ts.map +1 -1
  9. package/dist/components/ui/product-card.js +15 -4
  10. package/dist/components/ui/route-skeleton-loader.d.ts.map +1 -1
  11. package/dist/components/ui/route-skeleton-loader.js +6 -2
  12. package/dist/components/ui/sheet.d.ts.map +1 -1
  13. package/dist/components/ui/sheet.js +2 -2
  14. package/dist/components/ui/skeletons/checkout-skeleton.js +1 -1
  15. package/dist/editor/blocks/defaults/clothing-minimal-home.js +1 -1
  16. package/dist/editor/blocks/migrate-clothing-minimal.js +1 -1
  17. package/dist/hooks/use-pdp-variation.d.ts +57 -0
  18. package/dist/hooks/use-pdp-variation.d.ts.map +1 -0
  19. package/dist/hooks/use-pdp-variation.js +69 -0
  20. package/dist/hooks/use-product-by-slug.d.ts.map +1 -1
  21. package/dist/hooks/use-product-by-slug.js +0 -5
  22. package/dist/hooks/use-product-variation-selection.js +1 -1
  23. package/dist/hooks/use-shipping-quote.d.ts +1 -0
  24. package/dist/hooks/use-shipping-quote.d.ts.map +1 -1
  25. package/dist/hooks/use-shipping-quote.js +3 -0
  26. package/dist/layouts/booking/pages/ProductDetailPage.d.ts.map +1 -1
  27. package/dist/layouts/booking/pages/ProductDetailPage.js +130 -223
  28. package/dist/layouts/booking-agenda/pages/ProductDetailPage.d.ts.map +1 -1
  29. package/dist/layouts/booking-agenda/pages/ProductDetailPage.js +130 -223
  30. package/dist/layouts/clothing/components/ClothingHomePage.d.ts.map +1 -1
  31. package/dist/layouts/clothing/components/ClothingHomePage.js +40 -2
  32. package/dist/layouts/clothing/pages/ProductDetailPage.d.ts.map +1 -1
  33. package/dist/layouts/clothing/pages/ProductDetailPage.js +127 -209
  34. package/dist/layouts/clothing/pages/ProductsPage.d.ts.map +1 -1
  35. package/dist/layouts/clothing/pages/ProductsPage.js +2 -5
  36. package/dist/layouts/clothing-minimal/components/ClothingHomePageMinimal.d.ts.map +1 -1
  37. package/dist/layouts/clothing-minimal/components/ClothingHomePageMinimal.js +5 -3
  38. package/dist/layouts/clothing-minimal/components/clothing-minimal-block-render.d.ts.map +1 -1
  39. package/dist/layouts/clothing-minimal/components/clothing-minimal-block-render.js +13 -4
  40. package/dist/layouts/clothing-minimal/pages/ProductDetailPage.d.ts.map +1 -1
  41. package/dist/layouts/clothing-minimal/pages/ProductDetailPage.js +130 -223
  42. package/dist/layouts/clothing-minimal/pages/ProductsPage.d.ts.map +1 -1
  43. package/dist/layouts/clothing-minimal/pages/ProductsPage.js +2 -5
  44. package/dist/layouts/electronics/components/ElectronicsGridProductCard.js +1 -1
  45. package/dist/layouts/electronics/components/ElectronicsStoreHeader.d.ts.map +1 -1
  46. package/dist/layouts/electronics/components/ElectronicsStoreHeader.js +10 -9
  47. package/dist/layouts/electronics/pages/ProductDetailPage.d.ts.map +1 -1
  48. package/dist/layouts/electronics/pages/ProductDetailPage.js +130 -223
  49. package/dist/layouts/electronics/pages/ProductsPage.d.ts.map +1 -1
  50. package/dist/layouts/electronics/pages/ProductsPage.js +2 -5
  51. package/dist/layouts/electronics-grid/components/ElectronicsGridProductCard.js +1 -1
  52. package/dist/layouts/electronics-grid/components/ElectronicsHomePageGrid.d.ts.map +1 -1
  53. package/dist/layouts/electronics-grid/components/ElectronicsHomePageGrid.js +4 -5
  54. package/dist/layouts/electronics-grid/pages/ProductDetailPage.d.ts.map +1 -1
  55. package/dist/layouts/electronics-grid/pages/ProductDetailPage.js +130 -223
  56. package/dist/layouts/electronics-grid/pages/ProductsPage.d.ts.map +1 -1
  57. package/dist/layouts/electronics-grid/pages/ProductsPage.js +2 -5
  58. package/dist/layouts/food/pages/MenuPage.js +1 -1
  59. package/dist/layouts/food/pages/ProductDetailPage.d.ts.map +1 -1
  60. package/dist/layouts/food/pages/ProductDetailPage.js +37 -140
  61. package/dist/layouts/food/pages/ProductsPage.d.ts.map +1 -1
  62. package/dist/layouts/food/pages/ProductsPage.js +2 -5
  63. package/dist/layouts/food-modern/pages/MenuPage.js +1 -1
  64. package/dist/layouts/food-modern/pages/ProductDetailPage.d.ts.map +1 -1
  65. package/dist/layouts/food-modern/pages/ProductDetailPage.js +130 -223
  66. package/dist/layouts/food-modern/pages/ProductsPage.d.ts.map +1 -1
  67. package/dist/layouts/food-modern/pages/ProductsPage.js +2 -5
  68. package/dist/layouts/motivational-speaker/pages/ProductsPage.d.ts.map +1 -1
  69. package/dist/layouts/motivational-speaker/pages/ProductsPage.js +2 -5
  70. package/dist/layouts/shared/components/PdpColorSwatch.d.ts +11 -0
  71. package/dist/layouts/shared/components/PdpColorSwatch.d.ts.map +1 -0
  72. package/dist/layouts/shared/components/PdpColorSwatch.js +29 -0
  73. package/dist/layouts/shared/components/PdpVariationSelectors.d.ts +13 -0
  74. package/dist/layouts/shared/components/PdpVariationSelectors.d.ts.map +1 -0
  75. package/dist/layouts/shared/components/PdpVariationSelectors.js +65 -0
  76. package/dist/layouts/shared/components/StoreCartSheet.d.ts +8 -0
  77. package/dist/layouts/shared/components/StoreCartSheet.d.ts.map +1 -0
  78. package/dist/layouts/shared/components/StoreCartSheet.js +16 -0
  79. package/dist/layouts/shared/components/StoreHeader.d.ts.map +1 -1
  80. package/dist/layouts/shared/components/StoreHeader.js +13 -12
  81. package/dist/layouts/shared/components/headers/ClothingMinimalHeader.d.ts.map +1 -1
  82. package/dist/layouts/shared/components/headers/ClothingMinimalHeader.js +5 -7
  83. package/dist/layouts/shared/pages/CartPage.d.ts.map +1 -1
  84. package/dist/layouts/shared/pages/CartPage.js +6 -5
  85. package/dist/layouts/shared/pages/CheckoutPage.d.ts.map +1 -1
  86. package/dist/layouts/shared/pages/CheckoutPage.js +209 -107
  87. package/dist/layouts/shared/product-category-filter-chip.d.ts +2 -0
  88. package/dist/layouts/shared/product-category-filter-chip.d.ts.map +1 -0
  89. package/dist/layouts/shared/product-category-filter-chip.js +6 -0
  90. package/dist/lib/pdp-cart-actions.d.ts +5 -0
  91. package/dist/lib/pdp-cart-actions.d.ts.map +1 -0
  92. package/dist/lib/pdp-cart-actions.js +19 -0
  93. package/dist/lib/product-variation-utils.d.ts +17 -0
  94. package/dist/lib/product-variation-utils.d.ts.map +1 -1
  95. package/dist/lib/product-variation-utils.js +193 -14
  96. package/dist/lib/services/checkout.service.d.ts +11 -0
  97. package/dist/lib/services/checkout.service.d.ts.map +1 -1
  98. package/dist/lib/services/shipping.service.d.ts +3 -0
  99. package/dist/lib/services/shipping.service.d.ts.map +1 -1
  100. package/dist/lib/store-config-utils.d.ts.map +1 -1
  101. package/dist/lib/store-config-utils.js +104 -11
  102. package/dist/lib/store-context.d.ts.map +1 -1
  103. package/dist/lib/store-context.js +23 -8
  104. package/dist/lib/utils/asset-helpers.d.ts +2 -0
  105. package/dist/lib/utils/asset-helpers.d.ts.map +1 -1
  106. package/dist/lib/utils/asset-helpers.js +24 -0
  107. package/dist/styles/index.css +143 -45
  108. package/package.json +8 -2
@@ -0,0 +1,5 @@
1
+ import type { CartItem } from './store-context.js';
2
+ import type { StoreProduct } from './store-types.js';
3
+ import { type StoreProductVariant } from './product-variation-utils.js';
4
+ export declare function buildPdpBuyNowItem(product: StoreProduct, quantity: number, selectedVariation?: StoreProductVariant | null, displayPrice?: number, selectedAttributes?: Record<string, string>): CartItem;
5
+ //# sourceMappingURL=pdp-cart-actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pdp-cart-actions.d.ts","sourceRoot":"","sources":["../../src/lib/pdp-cart-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,+BAA+B,CAAC;AAEvC,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,MAAM,EAChB,iBAAiB,CAAC,EAAE,mBAAmB,GAAG,IAAI,EAC9C,YAAY,CAAC,EAAE,MAAM,EACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC1C,QAAQ,CAkBV"}
@@ -0,0 +1,19 @@
1
+ import { assertVariationSelected, buildCartLineProduct, formatVariationLabel, } from './product-variation-utils.js';
2
+ export function buildPdpBuyNowItem(product, quantity, selectedVariation, displayPrice, selectedAttributes) {
3
+ assertVariationSelected(product, selectedVariation, selectedAttributes);
4
+ const lineProduct = buildCartLineProduct(product, selectedVariation);
5
+ const variantId = selectedVariation?.id;
6
+ const price = displayPrice ?? lineProduct.price;
7
+ const variantName = formatVariationLabel(selectedVariation);
8
+ const id = variantId ? `${product.id}-${variantId}` : product.id;
9
+ return {
10
+ id,
11
+ productId: product.id,
12
+ quantity,
13
+ variantId,
14
+ variantName,
15
+ price,
16
+ product: { ...lineProduct, price },
17
+ currency: lineProduct.currency,
18
+ };
19
+ }
@@ -1,12 +1,29 @@
1
1
  import type { StoreProduct } from './store-types';
2
2
  export type StoreProductVariant = NonNullable<StoreProduct['variants']>[number];
3
+ /** Collapse display labels (e.g. from legacy mapping) onto attribute keys used in admin. */
4
+ export declare function canonicalVariationOptionGroupKey(rawKey: string): string;
5
+ /** Matches storefront-admin ProductForm variation fields (e.g. Label "Name/Color" → `attributes.color`). */
6
+ export declare const VARIATION_ATTRIBUTE_LABELS: Record<string, string>;
7
+ export declare function getVariationAttributeLabel(attributeKey: string): string;
8
+ export declare function getSortedVariationOptionKeys(optionGroups: Record<string, string[]>): string[];
3
9
  export declare function getVariationOptionGroups(variants: StoreProductVariant[] | undefined): Record<string, string[]>;
4
10
  export declare function getDefaultSelectedAttributes(optionGroups: Record<string, string[]>): Record<string, string>;
5
11
  export declare function findMatchingVariation(variants: StoreProductVariant[] | undefined, selectedAttributes: Record<string, string>): StoreProductVariant | undefined;
12
+ /**
13
+ * Prefer an exact combo; otherwise keep the new value and fill from a
14
+ * compatible variation that includes it.
15
+ */
16
+ export declare function reconcileSelectedAttributes(variants: StoreProductVariant[] | undefined, current: Record<string, string>, key: string, value: string): Record<string, string>;
17
+ /** True when a variation has this option and still matches the other selected attributes. */
18
+ export declare function isVariationOptionAvailable(variants: StoreProductVariant[] | undefined, selected: Record<string, string>, key: string, value: string): boolean;
6
19
  type VariantStockFields = Pick<StoreProduct, 'trackInventory' | 'availableStock' | 'inStock' | 'lowStockThreshold' | 'name'>;
7
20
  export declare function resolveVariantStockProduct(product: VariantStockFields, variant?: StoreProductVariant): VariantStockFields;
8
21
  export declare function resolveVariantPrice(product: Pick<StoreProduct, 'price'>, variant?: StoreProductVariant): number;
9
22
  export declare function resolveVariantSKU(product: Pick<StoreProduct, 'sku' | 'slug'>, variant?: StoreProductVariant): string;
23
+ export declare function resolveProductGalleryImageUrls(product: Pick<StoreProduct, 'images'>, variant?: StoreProductVariant | null): string[];
24
+ export declare function formatVariationLabel(variant?: StoreProductVariant | null): string | undefined;
25
+ export declare function getVariationOptionImage(variants: StoreProductVariant[] | undefined, attributeKey: string, value: string, product?: Pick<StoreProduct, 'images'> | null): string | undefined;
26
+ export declare function assertVariationSelected(product: StoreProduct, variant?: StoreProductVariant | null, _selectedAttributes?: Record<string, string>): void;
10
27
  export declare function resolveVariantImageUrls(variant?: StoreProductVariant | null): string[];
11
28
  export declare function buildCartLineProduct(product: StoreProduct, variant?: StoreProductVariant | null): StoreProduct;
12
29
  export declare function getCartLineImage(item: {
@@ -1 +1 @@
1
- {"version":3,"file":"product-variation-utils.d.ts","sourceRoot":"","sources":["../../src/lib/product-variation-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,MAAM,mBAAmB,GAAG,WAAW,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAIhF,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,mBAAmB,EAAE,GAAG,SAAS,GAC1C,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CA0C1B;AAED,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GACrC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAaxB;AAED,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,mBAAmB,EAAE,GAAG,SAAS,EAC3C,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACzC,mBAAmB,GAAG,SAAS,CA4BjC;AAED,KAAK,kBAAkB,GAAG,IAAI,CAC5B,YAAY,EACZ,gBAAgB,GAAG,gBAAgB,GAAG,SAAS,GAAG,mBAAmB,GAAG,MAAM,CAC/E,CAAC;AAEF,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,mBAAmB,GAC5B,kBAAkB,CAapB;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,EACpC,OAAO,CAAC,EAAE,mBAAmB,GAC5B,MAAM,CAER;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,KAAK,GAAG,MAAM,CAAC,EAC3C,OAAO,CAAC,EAAE,mBAAmB,GAC5B,MAAM,CAOR;AAED,wBAAgB,uBAAuB,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,IAAI,GAAG,MAAM,EAAE,CAyBtF;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE,mBAAmB,GAAG,IAAI,GACnC,YAAY,CAkBd;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,MAAM,GAAG,SAAS,CAerB;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGxD;AAED,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAYzD,CAAC"}
1
+ {"version":3,"file":"product-variation-utils.d.ts","sourceRoot":"","sources":["../../src/lib/product-variation-utils.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,41 @@
1
+ import { extractImageUrls } from './store-config-utils';
1
2
  const ATTRIBUTE_ORDER = ['color', 'size', 'material', 'style'];
3
+ /** Collapse display labels (e.g. from legacy mapping) onto attribute keys used in admin. */
4
+ export function canonicalVariationOptionGroupKey(rawKey) {
5
+ const key = rawKey.toLowerCase().trim();
6
+ if (key === 'name / color' || key === 'name/color' || key === 'name / colour') {
7
+ return 'color';
8
+ }
9
+ return key;
10
+ }
11
+ /** Matches storefront-admin ProductForm variation fields (e.g. Label "Name/Color" → `attributes.color`). */
12
+ export const VARIATION_ATTRIBUTE_LABELS = {
13
+ color: 'Name / Color',
14
+ size: 'Size',
15
+ material: 'Material',
16
+ style: 'Style',
17
+ option: 'Option',
18
+ };
19
+ export function getVariationAttributeLabel(attributeKey) {
20
+ const key = attributeKey.toLowerCase();
21
+ return (VARIATION_ATTRIBUTE_LABELS[key] ??
22
+ key.charAt(0).toUpperCase() + key.slice(1));
23
+ }
24
+ export function getSortedVariationOptionKeys(optionGroups) {
25
+ const keys = Object.keys(optionGroups).filter((key) => (optionGroups[key]?.length ?? 0) > 0);
26
+ return keys.sort((a, b) => {
27
+ const order = ATTRIBUTE_ORDER;
28
+ const indexA = order.indexOf(a);
29
+ const indexB = order.indexOf(b);
30
+ if (indexA === -1 && indexB === -1)
31
+ return a.localeCompare(b);
32
+ if (indexA === -1)
33
+ return 1;
34
+ if (indexB === -1)
35
+ return -1;
36
+ return indexA - indexB;
37
+ });
38
+ }
2
39
  export function getVariationOptionGroups(variants) {
3
40
  if (!variants?.length)
4
41
  return {};
@@ -6,19 +43,20 @@ export function getVariationOptionGroups(variants) {
6
43
  for (const variant of variants) {
7
44
  if (variant.isActive === false)
8
45
  continue;
9
- if (variant.name && variant.value) {
10
- const key = variant.name.toLowerCase();
46
+ const attributes = variant.attributes || {};
47
+ const hasStructuredAttributes = Object.keys(attributes).length > 0;
48
+ if (variant.name && variant.value && !hasStructuredAttributes) {
49
+ const key = canonicalVariationOptionGroupKey(variant.name);
11
50
  if (!groups[key])
12
51
  groups[key] = [];
13
52
  if (!groups[key].includes(variant.value)) {
14
53
  groups[key].push(variant.value);
15
54
  }
16
55
  }
17
- const attributes = variant.attributes || {};
18
56
  for (const [rawKey, rawValue] of Object.entries(attributes)) {
19
57
  if (typeof rawValue !== 'string' || rawValue.trim() === '')
20
58
  continue;
21
- const key = rawKey.toLowerCase();
59
+ const key = canonicalVariationOptionGroupKey(rawKey);
22
60
  if (!groups[key])
23
61
  groups[key] = [];
24
62
  if (!groups[key].includes(rawValue)) {
@@ -56,6 +94,48 @@ export function getDefaultSelectedAttributes(optionGroups) {
56
94
  }
57
95
  return defaults;
58
96
  }
97
+ function getVariantAttributeValue(variant, attributeKey) {
98
+ const canonicalKey = canonicalVariationOptionGroupKey(attributeKey);
99
+ const attrs = variant.attributes || {};
100
+ const direct = attrs[canonicalKey];
101
+ if (typeof direct === 'string' && direct.trim() !== '')
102
+ return direct;
103
+ for (const [rawKey, rawValue] of Object.entries(attrs)) {
104
+ if (canonicalVariationOptionGroupKey(rawKey) === canonicalKey &&
105
+ typeof rawValue === 'string' &&
106
+ rawValue.trim() !== '') {
107
+ return rawValue;
108
+ }
109
+ }
110
+ if (variant.name &&
111
+ canonicalVariationOptionGroupKey(variant.name) === canonicalKey &&
112
+ typeof variant.value === 'string' &&
113
+ variant.value.trim() !== '') {
114
+ return variant.value;
115
+ }
116
+ return undefined;
117
+ }
118
+ function attributesFromVariant(variant) {
119
+ const result = {};
120
+ const attrs = variant.attributes || {};
121
+ for (const [rawKey, rawValue] of Object.entries(attrs)) {
122
+ if (typeof rawValue !== 'string' || rawValue.trim() === '')
123
+ continue;
124
+ result[canonicalVariationOptionGroupKey(rawKey)] = rawValue;
125
+ }
126
+ if (Object.keys(result).length === 0 &&
127
+ variant.name &&
128
+ typeof variant.value === 'string' &&
129
+ variant.value.trim() !== '') {
130
+ result[canonicalVariationOptionGroupKey(variant.name)] = variant.value;
131
+ }
132
+ return result;
133
+ }
134
+ function variantMatchesSelected(variant, selectedEntries) {
135
+ return selectedEntries.every(([key, value]) => {
136
+ return getVariantAttributeValue(variant, key) === value;
137
+ });
138
+ }
59
139
  export function findMatchingVariation(variants, selectedAttributes) {
60
140
  if (!variants?.length)
61
141
  return undefined;
@@ -63,21 +143,67 @@ export function findMatchingVariation(variants, selectedAttributes) {
63
143
  if (activeVariants.length === 0)
64
144
  return undefined;
65
145
  const selectedEntries = Object.entries(selectedAttributes).filter(([, value]) => typeof value === 'string' && value.trim() !== '');
146
+ // No shopper selection → no match (keep base product price / stock until they click).
66
147
  if (selectedEntries.length === 0) {
67
- return activeVariants.length === 1 ? activeVariants[0] : undefined;
148
+ return undefined;
68
149
  }
69
- return activeVariants.find((variant) => {
70
- const attrs = variant.attributes || {};
71
- return selectedEntries.every(([key, value]) => {
72
- const normalizedKey = key.toLowerCase();
73
- const attributeValue = attrs[normalizedKey];
74
- if (attributeValue && attributeValue === value)
150
+ return activeVariants.find((variant) => variantMatchesSelected(variant, selectedEntries));
151
+ }
152
+ /**
153
+ * Prefer an exact combo; otherwise keep the new value and fill from a
154
+ * compatible variation that includes it.
155
+ */
156
+ export function reconcileSelectedAttributes(variants, current, key, value) {
157
+ const canonicalKey = canonicalVariationOptionGroupKey(key);
158
+ if (!value) {
159
+ return {};
160
+ }
161
+ const next = { ...current, [canonicalKey]: value };
162
+ const exact = findMatchingVariation(variants, next);
163
+ if (exact) {
164
+ return attributesFromVariant(exact);
165
+ }
166
+ const activeVariants = (variants || []).filter((variant) => variant.isActive !== false);
167
+ const candidates = activeVariants.filter((variant) => getVariantAttributeValue(variant, canonicalKey) === value);
168
+ if (candidates.length === 0) {
169
+ return { [canonicalKey]: value };
170
+ }
171
+ let best = candidates[0];
172
+ let bestScore = -1;
173
+ for (const candidate of candidates) {
174
+ let score = 0;
175
+ for (const [selectedKey, selectedValue] of Object.entries(current)) {
176
+ if (selectedKey === canonicalKey)
177
+ continue;
178
+ if (getVariantAttributeValue(candidate, selectedKey) === selectedValue) {
179
+ score += 1;
180
+ }
181
+ }
182
+ if (score > bestScore) {
183
+ bestScore = score;
184
+ best = candidate;
185
+ }
186
+ }
187
+ return attributesFromVariant(best);
188
+ }
189
+ /** True when a variation has this option and still matches the other selected attributes. */
190
+ export function isVariationOptionAvailable(variants, selected, key, value) {
191
+ if (!variants?.length)
192
+ return true;
193
+ if (!value)
194
+ return true;
195
+ const canonicalKey = canonicalVariationOptionGroupKey(key);
196
+ const activeVariants = variants.filter((variant) => variant.isActive !== false);
197
+ return activeVariants.some((variant) => {
198
+ if (getVariantAttributeValue(variant, canonicalKey) !== value)
199
+ return false;
200
+ return Object.entries(selected).every(([selectedKey, selectedValue]) => {
201
+ if (!selectedValue)
75
202
  return true;
76
- if (variant.name?.toLowerCase() === normalizedKey &&
77
- variant.value === value) {
203
+ if (canonicalVariationOptionGroupKey(selectedKey) === canonicalKey) {
78
204
  return true;
79
205
  }
80
- return false;
206
+ return getVariantAttributeValue(variant, selectedKey) === selectedValue;
81
207
  });
82
208
  });
83
209
  }
@@ -102,6 +228,59 @@ export function resolveVariantSKU(product, variant) {
102
228
  product.slug?.toUpperCase().replace(/-/g, '').substring(0, 12).padEnd(8, 'X') ||
103
229
  'N/A');
104
230
  }
231
+ export function resolveProductGalleryImageUrls(product, variant) {
232
+ const base = extractImageUrls(product.images).filter((url) => url.trim().length > 0);
233
+ const variantUrls = resolveVariantImageUrls(variant);
234
+ if (variantUrls.length > 0) {
235
+ const merged = [...variantUrls];
236
+ for (const url of base) {
237
+ if (!merged.includes(url))
238
+ merged.push(url);
239
+ }
240
+ return merged;
241
+ }
242
+ return base;
243
+ }
244
+ export function formatVariationLabel(variant) {
245
+ if (!variant)
246
+ return undefined;
247
+ const fromAttrs = Object.values(variant.attributes || {})
248
+ .filter((value) => typeof value === 'string' && value.trim() !== '')
249
+ .join(' / ');
250
+ if (fromAttrs)
251
+ return fromAttrs;
252
+ if (variant.value)
253
+ return variant.value;
254
+ if (variant.name)
255
+ return variant.name;
256
+ return undefined;
257
+ }
258
+ export function getVariationOptionImage(variants, attributeKey, value, product) {
259
+ const productImage = product
260
+ ? extractImageUrls(product.images).find((url) => url.trim().length > 0)
261
+ : undefined;
262
+ if (!variants?.length)
263
+ return productImage;
264
+ const match = variants.find((variant) => {
265
+ if (variant.isActive === false)
266
+ return false;
267
+ const attrs = variant.attributes || {};
268
+ const attrValue = attrs[attributeKey];
269
+ if (attrValue === value)
270
+ return true;
271
+ return variant.name?.toLowerCase() === attributeKey.toLowerCase() && variant.value === value;
272
+ });
273
+ return resolveVariantImageUrls(match)[0] || productImage;
274
+ }
275
+ export function assertVariationSelected(product, variant, _selectedAttributes) {
276
+ const groups = getVariationOptionGroups(product.variants);
277
+ const hasOptions = Object.values(groups).some((values) => values.length > 0);
278
+ if (!hasOptions)
279
+ return;
280
+ if (variant?.id)
281
+ return;
282
+ throw new Error('Please select a variation');
283
+ }
105
284
  export function resolveVariantImageUrls(variant) {
106
285
  if (!variant?.images)
107
286
  return [];
@@ -5,6 +5,7 @@ export interface CheckoutItem {
5
5
  storeId?: string;
6
6
  quantity: number;
7
7
  price: number;
8
+ currency?: string;
8
9
  variationId?: string;
9
10
  variantId?: string;
10
11
  options?: {
@@ -60,6 +61,10 @@ export interface MarketplaceCheckoutRequest {
60
61
  customerId?: string;
61
62
  isPickup?: boolean;
62
63
  pickupLocationId?: string;
64
+ /** Currency used for browsing/display. */
65
+ displayCurrency?: string;
66
+ /** Currency to send to the payment provider. */
67
+ chargeCurrency?: string;
63
68
  }
64
69
  export interface CheckoutRequest {
65
70
  storeId: string;
@@ -100,6 +105,12 @@ export interface CheckoutRequest {
100
105
  deliveryProviderKey?: string;
101
106
  deliveryMethodId?: string;
102
107
  deliveryQuoteId?: string;
108
+ deliveryPrice?: number;
109
+ deliveryCurrency?: string;
110
+ /** Currency used for browsing/display. */
111
+ displayCurrency?: string;
112
+ /** Currency to send to the payment provider. */
113
+ chargeCurrency?: string;
103
114
  }
104
115
  export interface CheckoutResponse {
105
116
  orderId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"checkout.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/checkout.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"checkout.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/checkout.service.ts"],"names":[],"mappings":"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"}
@@ -9,12 +9,15 @@ export interface ShippingMethod {
9
9
  providerKey?: string;
10
10
  deliveryMethodId?: string;
11
11
  deliveryQuoteId?: string;
12
+ quoteCurrency?: string;
13
+ quoteCost?: number;
12
14
  }
13
15
  export interface ShippingCalculation {
14
16
  methods: ShippingMethod[];
15
17
  selectedMethod?: ShippingMethod;
16
18
  freeShippingEligible: boolean;
17
19
  freeShippingThreshold?: number;
20
+ freeShippingEnabled?: boolean;
18
21
  }
19
22
  export interface DeliveryStatus {
20
23
  enabled: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"shipping.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/shipping.service.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,oBAAoB,EAAE,OAAO,CAAC;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,eAAe;IAC1B;;OAEG;4BAC2B;QAC5B,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,GAAG,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE;YACb,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAQhC;;;OAGG;+BAC8B,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAYjE;;OAEG;uBACsB;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,GAAG,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,CAAC;CAOvG,CAAC"}
1
+ {"version":3,"file":"shipping.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/shipping.service.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,oBAAoB,EAAE,OAAO,CAAC;IAC9B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,eAAe;IAC1B;;OAEG;4BAC2B;QAC5B,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,GAAG,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,GAAG,EAAE,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,YAAY,CAAC,EAAE;YACb,SAAS,CAAC,EAAE,MAAM,CAAC;YACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,KAAK,CAAC,EAAE,MAAM,CAAC;YACf,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAQhC;;;OAGG;+BAC8B,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAYjE;;OAEG;uBACsB;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,GAAG,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,CAAC;CAOvG,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"store-config-utils.d.ts","sourceRoot":"","sources":["../../src/lib/store-config-utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAkB,KAAK,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAkB,KAAK,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAmB,aAAa,EAAE,YAAY,EAAE,YAAY,EAAqB,MAAM,eAAe,CAAC;AAYhI;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,EAAE,CAgGrD;AAgVD;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,WAAW,EAAE,QAAQ,GAAG,aAAa,CAarF;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,UAAU,EAAE,OAAO,GAAG,YAAY,CA0IhF;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,UAAU,EAAE,OAAO,GAAG,YAAY,CA6DhF;AA00BD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAyHvF"}
1
+ {"version":3,"file":"store-config-utils.d.ts","sourceRoot":"","sources":["../../src/lib/store-config-utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAmB,KAAK,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,EAAkB,KAAK,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAkB,KAAK,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAmB,aAAa,EAAE,YAAY,EAAE,YAAY,EAAqB,MAAM,eAAe,CAAC;AAYhI;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,GAAG,GAAG,MAAM,EAAE,CAgGrD;AAgVD;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,WAAW,EAAE,QAAQ,GAAG,aAAa,CAarF;AA6GD;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,UAAU,EAAE,OAAO,GAAG,YAAY,CAgIhF;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,UAAU,EAAE,OAAO,GAAG,YAAY,CA6DhF;AA00BD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAyHvF"}
@@ -424,6 +424,109 @@ export function transformCategoryToStoreCategory(apiCategory) {
424
424
  parentId: apiCategory.parentId,
425
425
  };
426
426
  }
427
+ const LEGACY_VARIANT_KEYS = ['color', 'size', 'material', 'style', 'option'];
428
+ const LEGACY_VARIANT_LABELS = {
429
+ color: 'Name / Color',
430
+ size: 'Size',
431
+ material: 'Material',
432
+ style: 'Style',
433
+ option: 'Option',
434
+ };
435
+ function normalizeVariationAttributes(variation) {
436
+ const attributes = {};
437
+ const raw = variation.attributes || {};
438
+ for (const [key, value] of Object.entries(raw)) {
439
+ if (typeof value === 'string' && value.trim() !== '') {
440
+ attributes[key.toLowerCase()] = value.trim();
441
+ }
442
+ }
443
+ if (Object.keys(attributes).length === 0) {
444
+ const sku = typeof variation.sku === 'string' ? variation.sku.trim() : '';
445
+ if (sku) {
446
+ attributes.option = sku;
447
+ }
448
+ }
449
+ return attributes;
450
+ }
451
+ function legacyVariantNameValue(attributes) {
452
+ for (const key of LEGACY_VARIANT_KEYS) {
453
+ const value = attributes[key];
454
+ if (value) {
455
+ return { name: LEGACY_VARIANT_LABELS[key] ?? key, value };
456
+ }
457
+ }
458
+ return { name: '', value: '' };
459
+ }
460
+ function mapApiVariationsToStoreVariants(apiProduct) {
461
+ const variations = apiProduct.variations;
462
+ if (!Array.isArray(variations) || variations.length === 0) {
463
+ return undefined;
464
+ }
465
+ return variations
466
+ .filter((variation) => variation.isActive !== false)
467
+ .map((variation) => {
468
+ const attributes = normalizeVariationAttributes(variation);
469
+ const optionValue = attributes.option;
470
+ const legacy = legacyVariantNameValue(attributes);
471
+ const hasStructuredAttributes = Object.keys(attributes).length > 0;
472
+ const mappedName = typeof variation.name === 'string' && variation.name.trim()
473
+ ? variation.name.trim()
474
+ : !hasStructuredAttributes && legacy.name
475
+ ? legacy.name
476
+ : !hasStructuredAttributes && optionValue
477
+ ? 'Option'
478
+ : '';
479
+ return {
480
+ id: variation.id,
481
+ attributes,
482
+ name: mappedName,
483
+ value: variation.value || legacy.value || optionValue || '',
484
+ price: variation.price
485
+ ? typeof variation.price === 'string'
486
+ ? parseFloat(variation.price)
487
+ : Number(variation.price)
488
+ : undefined,
489
+ compareAtPrice: variation.compareAtPrice
490
+ ? typeof variation.compareAtPrice === 'string'
491
+ ? parseFloat(variation.compareAtPrice)
492
+ : Number(variation.compareAtPrice)
493
+ : undefined,
494
+ sku: variation.sku,
495
+ stock: variation.stock != null
496
+ ? typeof variation.stock === 'string'
497
+ ? parseFloat(variation.stock)
498
+ : Number(variation.stock)
499
+ : undefined,
500
+ inStock: variation.inStock !== false,
501
+ isActive: variation.isActive !== false,
502
+ images: (() => {
503
+ const raw = variation.images;
504
+ let parsed = raw;
505
+ if (typeof raw === 'string') {
506
+ try {
507
+ parsed = JSON.parse(raw);
508
+ }
509
+ catch {
510
+ return raw.trim() ? [raw.trim()] : undefined;
511
+ }
512
+ }
513
+ if (!Array.isArray(parsed) || parsed.length === 0)
514
+ return undefined;
515
+ const urls = parsed
516
+ .map((img) => {
517
+ if (typeof img === 'string')
518
+ return img.trim();
519
+ if (img && typeof img === 'object' && typeof img.url === 'string') {
520
+ return img.url.trim();
521
+ }
522
+ return '';
523
+ })
524
+ .filter(Boolean);
525
+ return urls.length > 0 ? urls : undefined;
526
+ })(),
527
+ };
528
+ });
529
+ }
427
530
  /**
428
531
  * Transforms API Product to StoreProduct format
429
532
  * Calculates inStock based on trackInventory and inventory data
@@ -547,17 +650,7 @@ export function transformProductToStoreProduct(apiProduct) {
547
650
  reviewCount,
548
651
  sku: generateSKU(apiProduct),
549
652
  currency: apiProduct.currency || 'USD',
550
- variants: apiProduct.variations?.map((variation) => ({
551
- id: variation.id || variation.name || '',
552
- name: variation.name || '',
553
- value: variation.value || '',
554
- price: variation.price
555
- ? (typeof variation.price === 'string'
556
- ? parseFloat(variation.price)
557
- : Number(variation.price))
558
- : undefined,
559
- sku: variation.sku,
560
- })),
653
+ variants: mapApiVariationsToStoreVariants(apiProduct),
561
654
  specifications: apiProduct.brand ? { Brand: apiProduct.brand, brand: apiProduct.brand } : undefined,
562
655
  isActive: apiProduct.isActive,
563
656
  status: apiProduct.status,
@@ -1 +1 @@
1
- {"version":3,"file":"store-context.d.ts","sourceRoot":"","sources":["../../src/lib/store-context.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAc/D,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,gBAAgB;IACxB,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAGrB,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,SAAS,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3F,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,wBAAwB,CAAC,EAAE,CAAC,UAAU,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxH,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,aAAa,EAAE,OAAO,CAAC;IAGvB,UAAU,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,eAAe,EAAE,MAAM,IAAI,CAAC;IAG5B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7C,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,eAAO,MAAM,YAAY,2CAsBvB,CAAC;AAEH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,SAAS,EACT,aAAa,EACd,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CACpC,+BAgcA;AAED,eAAO,MAAM,QAAQ,wBAAiC,CAAC"}
1
+ {"version":3,"file":"store-context.d.ts","sourceRoot":"","sources":["../../src/lib/store-context.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAmB/D,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,gBAAgB;IACxB,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAGrB,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,SAAS,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3F,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,kBAAkB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,wBAAwB,CAAC,EAAE,CAAC,UAAU,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxH,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,aAAa,EAAE,OAAO,CAAC;IAGvB,UAAU,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC;IAC/C,eAAe,EAAE,MAAM,IAAI,CAAC;IAG5B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,YAAY,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7C,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,eAAO,MAAM,YAAY,2CAsBvB,CAAC;AAEH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,SAAS,EACT,aAAa,EACd,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CACpC,+BAgdA;AAED,eAAO,MAAM,QAAQ,wBAAiC,CAAC"}
@@ -1,6 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
3
  import { createContext, useContext, useEffect, useState, useMemo, useCallback } from 'react';
4
+ import { usePathname } from 'next/navigation';
4
5
  import { getStoreConfig } from './store-config';
5
6
  import { shouldUseAPI, getBaseStoreSlug } from './utils/demo-detection';
6
7
  import { storeService } from './services/store.service';
@@ -12,6 +13,7 @@ import { serviceService } from './services/service.service';
12
13
  import { transformCategoryToStoreCategory, transformProductToStoreProduct, transformServiceToStoreService } from './store-config-utils';
13
14
  import { useLoading } from './loading-context';
14
15
  import { normalizePrice } from './utils';
16
+ import { assertVariationSelected, buildCartLineProduct, formatVariationLabel, } from './product-variation-utils';
15
17
  import { useAuth } from './auth-context';
16
18
  import { analyticsService } from './services/analytics.service';
17
19
  export const StoreContext = createContext({
@@ -68,6 +70,10 @@ export function StoreProvider({ children, storeSlug, initialConfig }) {
68
70
  const [cart, setCart] = useState([]);
69
71
  const [isCartOpen, setIsCartOpen] = useState(false);
70
72
  const [isCartLoading, setIsCartLoading] = useState(false);
73
+ const pathname = usePathname();
74
+ useEffect(() => {
75
+ setIsCartOpen(false);
76
+ }, [pathname]);
71
77
  // Buy Now State (temporary single-item for direct checkout)
72
78
  // Initialize from sessionStorage to persist across navigation
73
79
  const [buyNowItem, setBuyNowItemState] = useState(() => {
@@ -288,21 +294,28 @@ export function StoreProvider({ children, storeSlug, initialConfig }) {
288
294
  localStorage.setItem(`wishlist_${storeSlug}`, JSON.stringify(wishlist));
289
295
  }, [cart, wishlist, storeSlug, store]);
290
296
  const addToCart = useCallback(async (product, quantity = 1, variantId) => {
291
- // Validate product is in stock
292
- if (!product.inStock) {
297
+ const variant = variantId
298
+ ? product.variants?.find((entry) => entry.id === variantId)
299
+ : undefined;
300
+ if (variantId && !variant) {
301
+ throw new Error('Please select a variation');
302
+ }
303
+ assertVariationSelected(product, variant);
304
+ const lineProduct = buildCartLineProduct(product, variant);
305
+ if (!lineProduct.inStock) {
293
306
  console.warn('[StoreContext] Attempted to add out-of-stock product to cart:', product.id);
294
- // Note: Error message should be shown by the calling component
295
307
  throw new Error('This product is currently out of stock');
296
308
  }
297
309
  setIsCartLoading(true);
298
310
  try {
299
- // Use local storage only (cartService removed)
311
+ const variantName = formatVariationLabel(variant);
312
+ const linePrice = lineProduct.price;
300
313
  setCart(prev => {
301
314
  const cartItemId = variantId ? `${product.id}-${variantId}` : product.id;
302
315
  const existingItem = prev.find(item => item.id === cartItemId);
303
316
  if (existingItem) {
304
317
  return prev.map(item => item.id === cartItemId
305
- ? { ...item, quantity: item.quantity + quantity }
318
+ ? { ...item, quantity: item.quantity + quantity, price: linePrice, product: lineProduct }
306
319
  : item);
307
320
  }
308
321
  return [...prev, {
@@ -310,8 +323,10 @@ export function StoreProvider({ children, storeSlug, initialConfig }) {
310
323
  productId: product.id,
311
324
  quantity,
312
325
  variantId,
313
- price: product.price,
314
- product
326
+ variantName,
327
+ price: linePrice,
328
+ product: lineProduct,
329
+ currency: lineProduct.currency,
315
330
  }];
316
331
  });
317
332
  // Track add to cart event
@@ -325,7 +340,7 @@ export function StoreProvider({ children, storeSlug, initialConfig }) {
325
340
  productName: product.name,
326
341
  categoryId: product.categoryId,
327
342
  quantity,
328
- price: product.price,
343
+ price: linePrice,
329
344
  variantId,
330
345
  },
331
346
  }).catch(err => console.warn('Failed to track add to cart:', err));
@@ -1,6 +1,8 @@
1
1
  import { StoreConfig } from '../store-types.js';
2
2
  import { shouldUseAPI } from './demo-detection';
3
3
  export { shouldUseAPI };
4
+ /** Hero badge for clothing-minimal: no template placeholder on live stores. */
5
+ export declare function resolveClothingMinimalHeroBadge(storeConfig: StoreConfig | null | undefined): unknown | null;
4
6
  /**
5
7
  * Normalizes store image URLs to absolute URLs
6
8
  * Handles both absolute URLs (R2/Cloudflare/etc.) and relative paths