@athoscommerce/snap-preact 1.11.0 → 1.12.0

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 (275) hide show
  1. package/dist/cjs/components/src/components/Atoms/Dropdown/Dropdown.js +18 -10
  2. package/dist/cjs/components/src/components/Atoms/Image/Image.js +10 -2
  3. package/dist/cjs/components/src/components/Atoms/ProductDetail/ProductDetail.js +98 -0
  4. package/dist/cjs/components/src/components/Atoms/ProductDetail/index.js +7 -0
  5. package/dist/cjs/components/src/components/Atoms/TemplateSelect/TemplateSelect.js +13 -4
  6. package/dist/cjs/components/src/components/Molecules/CalloutBadge/CalloutBadge.js +4 -1
  7. package/dist/cjs/components/src/components/Molecules/Gallery/Gallery.js +298 -0
  8. package/dist/cjs/components/src/components/Molecules/Gallery/index.js +17 -0
  9. package/dist/cjs/components/src/components/Molecules/Modal/Modal.js +21 -2
  10. package/dist/cjs/components/src/components/Molecules/OverlayBadge/OverlayBadge.js +1 -1
  11. package/dist/cjs/components/src/components/Molecules/ProductDetailTable/ProductDetailTable.js +115 -0
  12. package/dist/cjs/components/src/components/Molecules/ProductDetailTable/index.js +17 -0
  13. package/dist/cjs/components/src/components/Molecules/QuantityPicker/QuantityPicker.js +136 -0
  14. package/dist/cjs/components/src/components/Molecules/QuantityPicker/index.js +17 -0
  15. package/dist/cjs/components/src/components/Molecules/Result/Result.js +43 -4
  16. package/dist/cjs/components/src/components/Molecules/Slideout/Slideout.js +5 -2
  17. package/dist/cjs/components/src/components/Molecules/Slideshow/Slideshow.js +38 -5
  18. package/dist/cjs/components/src/components/Molecules/Swatches/Swatches.js +1 -1
  19. package/dist/cjs/components/src/components/Molecules/VariantSelection/VariantSelection.js +7 -1
  20. package/dist/cjs/components/src/components/Organisms/AutocompleteLayout/AutocompleteLayout.js +8 -8
  21. package/dist/cjs/components/src/components/Organisms/Facet/Facet.js +1 -5
  22. package/dist/cjs/components/src/components/Organisms/QuickviewLayout/QuickviewLayout.js +612 -0
  23. package/dist/cjs/components/src/components/Organisms/QuickviewLayout/index.js +17 -0
  24. package/dist/cjs/components/src/components/Templates/AutocompleteFixed/AutocompleteFixed.js +3 -3
  25. package/dist/cjs/components/src/components/Templates/AutocompleteModal/AutocompleteModal.js +3 -3
  26. package/dist/cjs/components/src/components/Templates/AutocompleteSlideout/AutocompleteSlideout.js +2 -2
  27. package/dist/cjs/components/src/components/Templates/QuickviewModal/QuickviewModal.js +153 -0
  28. package/dist/cjs/components/src/components/Templates/QuickviewModal/index.js +17 -0
  29. package/dist/cjs/components/src/components/Templates/QuickviewSlideout/QuickviewSlideout.js +124 -0
  30. package/dist/cjs/components/src/components/Templates/QuickviewSlideout/index.js +17 -0
  31. package/dist/cjs/components/src/components/Templates/Recommendation/Recommendation.js +2 -1
  32. package/dist/cjs/components/src/components/Templates/RecommendationBundle/RecommendationBundle.js +2 -1
  33. package/dist/cjs/components/src/components/Templates/RecommendationGrid/RecommendationGrid.js +2 -1
  34. package/dist/cjs/components/src/hooks/useA11y.js +3 -1
  35. package/dist/cjs/components/src/hooks/useAcRenderedInput.js +1 -1
  36. package/dist/cjs/components/src/hooks/useClickOutside.js +6 -3
  37. package/dist/cjs/components/src/hooks/useTracking.js +14 -8
  38. package/dist/cjs/components/src/index.js +6 -0
  39. package/dist/cjs/components/src/providers/themeComponents.js +4 -0
  40. package/dist/cjs/components/src/setupTests.js +10 -0
  41. package/dist/cjs/components/src/utilities/createImpressionObserver.js +1 -1
  42. package/dist/cjs/components/src/utilities/index.js +1 -0
  43. package/dist/cjs/components/src/utilities/lazyRenderMinSize.js +10 -0
  44. package/dist/cjs/src/Instantiators/RecommendationInstantiator.js +2 -1
  45. package/dist/cjs/src/Snap.js +41 -0
  46. package/dist/cjs/src/Templates/SnapTemplates.js +51 -0
  47. package/dist/cjs/src/Templates/Stores/LibraryStore.js +77 -9
  48. package/dist/cjs/src/Templates/Stores/TemplateEditor/TemplateEditorStore.js +6 -1
  49. package/dist/cjs/src/Templates/Stores/TemplateEditor/uiAbstractions/configUI.js +2 -5
  50. package/dist/cjs/src/Templates/Stores/TemplateStore.js +26 -10
  51. package/dist/cjs/src/Templates/Stores/library/components/QuickviewModal.js +5 -0
  52. package/dist/cjs/src/Templates/Stores/library/components/QuickviewSlideout.js +5 -0
  53. package/dist/cjs/src/Templates/Stores/library/currencies/currencies.js +1433 -0
  54. package/dist/cjs/src/Templates/Stores/library/languages/ar.js +487 -0
  55. package/dist/cjs/src/Templates/Stores/library/languages/de.js +487 -0
  56. package/dist/cjs/src/Templates/Stores/library/languages/en.js +1 -0
  57. package/dist/cjs/src/Templates/Stores/library/languages/es.js +84 -41
  58. package/dist/cjs/src/Templates/Stores/library/languages/fr.js +85 -40
  59. package/dist/cjs/src/Templates/Stores/library/languages/hi.js +487 -0
  60. package/dist/cjs/src/Templates/Stores/library/languages/it.js +487 -0
  61. package/dist/cjs/src/Templates/Stores/library/languages/ja.js +487 -0
  62. package/dist/cjs/src/Templates/Stores/library/languages/ko.js +487 -0
  63. package/dist/cjs/src/Templates/Stores/library/languages/nl.js +487 -0
  64. package/dist/cjs/src/Templates/Stores/library/languages/pt.js +487 -0
  65. package/dist/cjs/src/Templates/Stores/library/languages/ru.js +487 -0
  66. package/dist/cjs/src/Templates/Stores/library/languages/tr.js +487 -0
  67. package/dist/cjs/src/Templates/Stores/library/languages/vi.js +487 -0
  68. package/dist/cjs/src/Templates/Stores/library/languages/zh.js +487 -0
  69. package/dist/cjs/src/Templates/index.js +3 -1
  70. package/dist/cjs/src/create/createAutocompleteController.js +1 -0
  71. package/dist/cjs/src/create/createRecommendationController.js +1 -0
  72. package/dist/cjs/src/create/createSearchController.js +1 -0
  73. package/dist/cjs/src/index.js +3 -1
  74. package/dist/esm/components/src/components/Atoms/Button/Button.d.ts +1 -1
  75. package/dist/esm/components/src/components/Atoms/Button/Button.d.ts.map +1 -1
  76. package/dist/esm/components/src/components/Atoms/Dropdown/Dropdown.d.ts.map +1 -1
  77. package/dist/esm/components/src/components/Atoms/Dropdown/Dropdown.js +19 -11
  78. package/dist/esm/components/src/components/Atoms/Image/Image.d.ts +5 -0
  79. package/dist/esm/components/src/components/Atoms/Image/Image.d.ts.map +1 -1
  80. package/dist/esm/components/src/components/Atoms/Image/Image.js +10 -2
  81. package/dist/esm/components/src/components/Atoms/ProductDetail/ProductDetail.d.ts +18 -0
  82. package/dist/esm/components/src/components/Atoms/ProductDetail/ProductDetail.d.ts.map +1 -0
  83. package/dist/esm/components/src/components/Atoms/ProductDetail/ProductDetail.js +89 -0
  84. package/dist/esm/components/src/components/Atoms/ProductDetail/index.d.ts +3 -0
  85. package/dist/esm/components/src/components/Atoms/ProductDetail/index.d.ts.map +1 -0
  86. package/dist/esm/components/src/components/Atoms/ProductDetail/index.js +3 -0
  87. package/dist/esm/components/src/components/Atoms/TemplateSelect/TemplateSelect.d.ts +1 -1
  88. package/dist/esm/components/src/components/Atoms/TemplateSelect/TemplateSelect.d.ts.map +1 -1
  89. package/dist/esm/components/src/components/Atoms/TemplateSelect/TemplateSelect.js +13 -4
  90. package/dist/esm/components/src/components/Molecules/CalloutBadge/CalloutBadge.d.ts.map +1 -1
  91. package/dist/esm/components/src/components/Molecules/CalloutBadge/CalloutBadge.js +4 -1
  92. package/dist/esm/components/src/components/Molecules/Gallery/Gallery.d.ts +28 -0
  93. package/dist/esm/components/src/components/Molecules/Gallery/Gallery.d.ts.map +1 -0
  94. package/dist/esm/components/src/components/Molecules/Gallery/Gallery.js +292 -0
  95. package/dist/esm/components/src/components/Molecules/Gallery/index.d.ts +2 -0
  96. package/dist/esm/components/src/components/Molecules/Gallery/index.d.ts.map +1 -0
  97. package/dist/esm/components/src/components/Molecules/Gallery/index.js +1 -0
  98. package/dist/esm/components/src/components/Molecules/Modal/Modal.d.ts.map +1 -1
  99. package/dist/esm/components/src/components/Molecules/Modal/Modal.js +22 -3
  100. package/dist/esm/components/src/components/Molecules/OverlayBadge/OverlayBadge.d.ts.map +1 -1
  101. package/dist/esm/components/src/components/Molecules/OverlayBadge/OverlayBadge.js +1 -1
  102. package/dist/esm/components/src/components/Molecules/ProductDetailTable/ProductDetailTable.d.ts +14 -0
  103. package/dist/esm/components/src/components/Molecules/ProductDetailTable/ProductDetailTable.d.ts.map +1 -0
  104. package/dist/esm/components/src/components/Molecules/ProductDetailTable/ProductDetailTable.js +109 -0
  105. package/dist/esm/components/src/components/Molecules/ProductDetailTable/index.d.ts +2 -0
  106. package/dist/esm/components/src/components/Molecules/ProductDetailTable/index.d.ts.map +1 -0
  107. package/dist/esm/components/src/components/Molecules/ProductDetailTable/index.js +1 -0
  108. package/dist/esm/components/src/components/Molecules/QuantityPicker/QuantityPicker.d.ts +43 -0
  109. package/dist/esm/components/src/components/Molecules/QuantityPicker/QuantityPicker.d.ts.map +1 -0
  110. package/dist/esm/components/src/components/Molecules/QuantityPicker/QuantityPicker.js +130 -0
  111. package/dist/esm/components/src/components/Molecules/QuantityPicker/index.d.ts +2 -0
  112. package/dist/esm/components/src/components/Molecules/QuantityPicker/index.d.ts.map +1 -0
  113. package/dist/esm/components/src/components/Molecules/QuantityPicker/index.js +1 -0
  114. package/dist/esm/components/src/components/Molecules/Result/Result.d.ts +3 -0
  115. package/dist/esm/components/src/components/Molecules/Result/Result.d.ts.map +1 -1
  116. package/dist/esm/components/src/components/Molecules/Result/Result.js +43 -4
  117. package/dist/esm/components/src/components/Molecules/Slideout/Slideout.d.ts.map +1 -1
  118. package/dist/esm/components/src/components/Molecules/Slideout/Slideout.js +6 -3
  119. package/dist/esm/components/src/components/Molecules/Slideshow/Slideshow.d.ts +1 -0
  120. package/dist/esm/components/src/components/Molecules/Slideshow/Slideshow.d.ts.map +1 -1
  121. package/dist/esm/components/src/components/Molecules/Slideshow/Slideshow.js +38 -5
  122. package/dist/esm/components/src/components/Molecules/Swatches/Swatches.js +1 -1
  123. package/dist/esm/components/src/components/Molecules/VariantSelection/VariantSelection.d.ts.map +1 -1
  124. package/dist/esm/components/src/components/Molecules/VariantSelection/VariantSelection.js +7 -1
  125. package/dist/esm/components/src/components/Organisms/AutocompleteLayout/AutocompleteLayout.js +8 -8
  126. package/dist/esm/components/src/components/Organisms/Facet/Facet.d.ts.map +1 -1
  127. package/dist/esm/components/src/components/Organisms/Facet/Facet.js +1 -5
  128. package/dist/esm/components/src/components/Organisms/QuickviewLayout/QuickviewLayout.d.ts +53 -0
  129. package/dist/esm/components/src/components/Organisms/QuickviewLayout/QuickviewLayout.d.ts.map +1 -0
  130. package/dist/esm/components/src/components/Organisms/QuickviewLayout/QuickviewLayout.js +605 -0
  131. package/dist/esm/components/src/components/Organisms/QuickviewLayout/index.d.ts +2 -0
  132. package/dist/esm/components/src/components/Organisms/QuickviewLayout/index.d.ts.map +1 -0
  133. package/dist/esm/components/src/components/Organisms/QuickviewLayout/index.js +1 -0
  134. package/dist/esm/components/src/components/Templates/AutocompleteFixed/AutocompleteFixed.js +3 -3
  135. package/dist/esm/components/src/components/Templates/AutocompleteModal/AutocompleteModal.js +3 -3
  136. package/dist/esm/components/src/components/Templates/AutocompleteSlideout/AutocompleteSlideout.js +2 -2
  137. package/dist/esm/components/src/components/Templates/QuickviewModal/QuickviewModal.d.ts +12 -0
  138. package/dist/esm/components/src/components/Templates/QuickviewModal/QuickviewModal.d.ts.map +1 -0
  139. package/dist/esm/components/src/components/Templates/QuickviewModal/QuickviewModal.js +147 -0
  140. package/dist/esm/components/src/components/Templates/QuickviewModal/index.d.ts +2 -0
  141. package/dist/esm/components/src/components/Templates/QuickviewModal/index.d.ts.map +1 -0
  142. package/dist/esm/components/src/components/Templates/QuickviewModal/index.js +1 -0
  143. package/dist/esm/components/src/components/Templates/QuickviewSlideout/QuickviewSlideout.d.ts +16 -0
  144. package/dist/esm/components/src/components/Templates/QuickviewSlideout/QuickviewSlideout.d.ts.map +1 -0
  145. package/dist/esm/components/src/components/Templates/QuickviewSlideout/QuickviewSlideout.js +118 -0
  146. package/dist/esm/components/src/components/Templates/QuickviewSlideout/index.d.ts +2 -0
  147. package/dist/esm/components/src/components/Templates/QuickviewSlideout/index.d.ts.map +1 -0
  148. package/dist/esm/components/src/components/Templates/QuickviewSlideout/index.js +1 -0
  149. package/dist/esm/components/src/components/Templates/Recommendation/Recommendation.d.ts.map +1 -1
  150. package/dist/esm/components/src/components/Templates/Recommendation/Recommendation.js +3 -2
  151. package/dist/esm/components/src/components/Templates/RecommendationBundle/RecommendationBundle.d.ts.map +1 -1
  152. package/dist/esm/components/src/components/Templates/RecommendationBundle/RecommendationBundle.js +3 -2
  153. package/dist/esm/components/src/components/Templates/RecommendationGrid/RecommendationGrid.d.ts.map +1 -1
  154. package/dist/esm/components/src/components/Templates/RecommendationGrid/RecommendationGrid.js +3 -2
  155. package/dist/esm/components/src/hooks/useA11y.d.ts.map +1 -1
  156. package/dist/esm/components/src/hooks/useA11y.js +3 -1
  157. package/dist/esm/components/src/hooks/useAcRenderedInput.js +1 -1
  158. package/dist/esm/components/src/hooks/useClickOutside.d.ts +1 -1
  159. package/dist/esm/components/src/hooks/useClickOutside.d.ts.map +1 -1
  160. package/dist/esm/components/src/hooks/useClickOutside.js +6 -3
  161. package/dist/esm/components/src/hooks/useTracking.d.ts +9 -3
  162. package/dist/esm/components/src/hooks/useTracking.d.ts.map +1 -1
  163. package/dist/esm/components/src/hooks/useTracking.js +14 -8
  164. package/dist/esm/components/src/index.d.ts +6 -0
  165. package/dist/esm/components/src/index.d.ts.map +1 -1
  166. package/dist/esm/components/src/index.js +6 -0
  167. package/dist/esm/components/src/providers/langComponents.d.ts +6 -0
  168. package/dist/esm/components/src/providers/langComponents.d.ts.map +1 -1
  169. package/dist/esm/components/src/providers/themeComponents.d.ts +104 -57
  170. package/dist/esm/components/src/providers/themeComponents.d.ts.map +1 -1
  171. package/dist/esm/components/src/providers/themeComponents.js +4 -0
  172. package/dist/esm/components/src/setupTests.js +10 -0
  173. package/dist/esm/components/src/utilities/createImpressionObserver.js +1 -1
  174. package/dist/esm/components/src/utilities/index.d.ts +1 -0
  175. package/dist/esm/components/src/utilities/index.d.ts.map +1 -1
  176. package/dist/esm/components/src/utilities/index.js +1 -0
  177. package/dist/esm/components/src/utilities/lazyRenderMinSize.d.ts +5 -0
  178. package/dist/esm/components/src/utilities/lazyRenderMinSize.d.ts.map +1 -0
  179. package/dist/esm/components/src/utilities/lazyRenderMinSize.js +7 -0
  180. package/dist/esm/src/Instantiators/RecommendationInstantiator.d.ts +4 -2
  181. package/dist/esm/src/Instantiators/RecommendationInstantiator.d.ts.map +1 -1
  182. package/dist/esm/src/Instantiators/RecommendationInstantiator.js +2 -1
  183. package/dist/esm/src/Snap.d.ts +7 -0
  184. package/dist/esm/src/Snap.d.ts.map +1 -1
  185. package/dist/esm/src/Snap.js +43 -2
  186. package/dist/esm/src/Templates/SnapTemplates.d.ts +25 -0
  187. package/dist/esm/src/Templates/SnapTemplates.d.ts.map +1 -1
  188. package/dist/esm/src/Templates/SnapTemplates.js +48 -0
  189. package/dist/esm/src/Templates/Stores/LibraryStore.d.ts +22 -2
  190. package/dist/esm/src/Templates/Stores/LibraryStore.d.ts.map +1 -1
  191. package/dist/esm/src/Templates/Stores/LibraryStore.js +76 -8
  192. package/dist/esm/src/Templates/Stores/TemplateEditor/TemplateEditorStore.d.ts.map +1 -1
  193. package/dist/esm/src/Templates/Stores/TemplateEditor/TemplateEditorStore.js +6 -1
  194. package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/configUI.d.ts.map +1 -1
  195. package/dist/esm/src/Templates/Stores/TemplateEditor/uiAbstractions/configUI.js +2 -5
  196. package/dist/esm/src/Templates/Stores/TemplateStore.d.ts +14 -6
  197. package/dist/esm/src/Templates/Stores/TemplateStore.d.ts.map +1 -1
  198. package/dist/esm/src/Templates/Stores/TemplateStore.js +26 -10
  199. package/dist/esm/src/Templates/Stores/library/components/QuickviewModal.d.ts +2 -0
  200. package/dist/esm/src/Templates/Stores/library/components/QuickviewModal.d.ts.map +1 -0
  201. package/dist/esm/src/Templates/Stores/library/components/QuickviewModal.js +1 -0
  202. package/dist/esm/src/Templates/Stores/library/components/QuickviewSlideout.d.ts +2 -0
  203. package/dist/esm/src/Templates/Stores/library/components/QuickviewSlideout.d.ts.map +1 -0
  204. package/dist/esm/src/Templates/Stores/library/components/QuickviewSlideout.js +1 -0
  205. package/dist/esm/src/Templates/Stores/library/currencies/currencies.d.ts +1270 -0
  206. package/dist/esm/src/Templates/Stores/library/currencies/currencies.d.ts.map +1 -0
  207. package/dist/esm/src/Templates/Stores/library/currencies/currencies.js +1430 -0
  208. package/dist/esm/src/Templates/Stores/library/languages/ar.d.ts +3 -0
  209. package/dist/esm/src/Templates/Stores/library/languages/ar.d.ts.map +1 -0
  210. package/dist/esm/src/Templates/Stores/library/languages/ar.js +484 -0
  211. package/dist/esm/src/Templates/Stores/library/languages/de.d.ts +3 -0
  212. package/dist/esm/src/Templates/Stores/library/languages/de.d.ts.map +1 -0
  213. package/dist/esm/src/Templates/Stores/library/languages/de.js +484 -0
  214. package/dist/esm/src/Templates/Stores/library/languages/en.d.ts.map +1 -1
  215. package/dist/esm/src/Templates/Stores/library/languages/en.js +1 -0
  216. package/dist/esm/src/Templates/Stores/library/languages/es.d.ts.map +1 -1
  217. package/dist/esm/src/Templates/Stores/library/languages/es.js +84 -41
  218. package/dist/esm/src/Templates/Stores/library/languages/fr.d.ts.map +1 -1
  219. package/dist/esm/src/Templates/Stores/library/languages/fr.js +85 -40
  220. package/dist/esm/src/Templates/Stores/library/languages/hi.d.ts +3 -0
  221. package/dist/esm/src/Templates/Stores/library/languages/hi.d.ts.map +1 -0
  222. package/dist/esm/src/Templates/Stores/library/languages/hi.js +484 -0
  223. package/dist/esm/src/Templates/Stores/library/languages/it.d.ts +3 -0
  224. package/dist/esm/src/Templates/Stores/library/languages/it.d.ts.map +1 -0
  225. package/dist/esm/src/Templates/Stores/library/languages/it.js +484 -0
  226. package/dist/esm/src/Templates/Stores/library/languages/ja.d.ts +3 -0
  227. package/dist/esm/src/Templates/Stores/library/languages/ja.d.ts.map +1 -0
  228. package/dist/esm/src/Templates/Stores/library/languages/ja.js +484 -0
  229. package/dist/esm/src/Templates/Stores/library/languages/ko.d.ts +3 -0
  230. package/dist/esm/src/Templates/Stores/library/languages/ko.d.ts.map +1 -0
  231. package/dist/esm/src/Templates/Stores/library/languages/ko.js +484 -0
  232. package/dist/esm/src/Templates/Stores/library/languages/nl.d.ts +3 -0
  233. package/dist/esm/src/Templates/Stores/library/languages/nl.d.ts.map +1 -0
  234. package/dist/esm/src/Templates/Stores/library/languages/nl.js +484 -0
  235. package/dist/esm/src/Templates/Stores/library/languages/pt.d.ts +3 -0
  236. package/dist/esm/src/Templates/Stores/library/languages/pt.d.ts.map +1 -0
  237. package/dist/esm/src/Templates/Stores/library/languages/pt.js +484 -0
  238. package/dist/esm/src/Templates/Stores/library/languages/ru.d.ts +3 -0
  239. package/dist/esm/src/Templates/Stores/library/languages/ru.d.ts.map +1 -0
  240. package/dist/esm/src/Templates/Stores/library/languages/ru.js +484 -0
  241. package/dist/esm/src/Templates/Stores/library/languages/tr.d.ts +3 -0
  242. package/dist/esm/src/Templates/Stores/library/languages/tr.d.ts.map +1 -0
  243. package/dist/esm/src/Templates/Stores/library/languages/tr.js +484 -0
  244. package/dist/esm/src/Templates/Stores/library/languages/vi.d.ts +3 -0
  245. package/dist/esm/src/Templates/Stores/library/languages/vi.d.ts.map +1 -0
  246. package/dist/esm/src/Templates/Stores/library/languages/vi.js +484 -0
  247. package/dist/esm/src/Templates/Stores/library/languages/zh.d.ts +3 -0
  248. package/dist/esm/src/Templates/Stores/library/languages/zh.d.ts.map +1 -0
  249. package/dist/esm/src/Templates/Stores/library/languages/zh.js +484 -0
  250. package/dist/esm/src/Templates/index.d.ts +1 -1
  251. package/dist/esm/src/Templates/index.d.ts.map +1 -1
  252. package/dist/esm/src/Templates/index.js +1 -1
  253. package/dist/esm/src/create/createAutocompleteController.js +1 -0
  254. package/dist/esm/src/create/createRecommendationController.js +1 -0
  255. package/dist/esm/src/create/createSearchController.js +1 -0
  256. package/dist/esm/src/index.d.ts +1 -1
  257. package/dist/esm/src/index.d.ts.map +1 -1
  258. package/dist/esm/src/index.js +1 -1
  259. package/dist/esm/src/types.d.ts +2 -1
  260. package/dist/esm/src/types.d.ts.map +1 -1
  261. package/eslint/src/index.cjs +5 -0
  262. package/eslint/src/validate-config.cjs +473 -0
  263. package/package.json +16 -14
  264. package/dist/cjs/src/Templates/Stores/library/currencies/aud.js +0 -10
  265. package/dist/cjs/src/Templates/Stores/library/currencies/eur.js +0 -10
  266. package/dist/cjs/src/Templates/Stores/library/currencies/usd.js +0 -10
  267. package/dist/esm/src/Templates/Stores/library/currencies/aud.d.ts +0 -8
  268. package/dist/esm/src/Templates/Stores/library/currencies/aud.d.ts.map +0 -1
  269. package/dist/esm/src/Templates/Stores/library/currencies/aud.js +0 -7
  270. package/dist/esm/src/Templates/Stores/library/currencies/eur.d.ts +0 -8
  271. package/dist/esm/src/Templates/Stores/library/currencies/eur.d.ts.map +0 -1
  272. package/dist/esm/src/Templates/Stores/library/currencies/eur.js +0 -7
  273. package/dist/esm/src/Templates/Stores/library/currencies/usd.d.ts +0 -8
  274. package/dist/esm/src/Templates/Stores/library/currencies/usd.d.ts.map +0 -1
  275. package/dist/esm/src/Templates/Stores/library/currencies/usd.js +0 -7
@@ -0,0 +1,605 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from 'preact/hooks';
3
+ import { observer } from 'mobx-react-lite';
4
+ import { isObservableArray } from 'mobx';
5
+ import { css } from '@emotion/react';
6
+ import classnames from 'classnames';
7
+ import deepmerge from 'deepmerge';
8
+ import { useTheme, CacheProvider, useTreePath, useSnap } from '../../../providers';
9
+ import { useA11y, useComponent, useCreateController, useCustomComponentOverride, useLang, useTracking } from '../../../hooks';
10
+ import { defined, mergeProps, mergeStyles } from '../../../utilities';
11
+ import { fieldNameToComponentName } from '@athoscommerce/snap-toolbox';
12
+ import { VariantSelection } from '../../Molecules/VariantSelection';
13
+ import { Slideshow } from '../../Molecules/Slideshow';
14
+ import { Button } from '../../Atoms/Button';
15
+ import { ProductDetail } from '../../Atoms/ProductDetail';
16
+ import { ProductDetailTable } from '../../Molecules/ProductDetailTable';
17
+ import { OverlayBadge } from '../../Molecules/OverlayBadge';
18
+ import { CalloutBadge } from '../../Molecules/CalloutBadge';
19
+ import { Gallery } from '../../Molecules/Gallery';
20
+ import { QuantityPicker } from '../../Molecules/QuantityPicker';
21
+ const defaultStyles = ({ column1, column2, column3, column4 }) => {
22
+ return css({
23
+ '& .ss__quickview__content': {
24
+ // extra top padding keeps the close button clear of top content (e.g. overlay badges)
25
+ padding: '48px 20px 20px 20px',
26
+ minWidth: '320px',
27
+ maxWidth: '600px',
28
+ position: 'relative',
29
+ boxSizing: 'border-box',
30
+ },
31
+ // The module grid: a flex row of columns. Columns are full width below the desktop
32
+ // breakpoint (single column) and use their configured widths side-by-side above it.
33
+ '& .ss__quickview__row': {
34
+ display: 'flex',
35
+ flexDirection: 'row',
36
+ flexWrap: 'wrap',
37
+ alignItems: 'flex-start',
38
+ gap: '24px',
39
+ // Flex items default to `min-width: auto`, which prevents a child from shrinking below
40
+ // its content's intrinsic width. For a row whose child is the slideshow (an Image/Slideshow),
41
+ // that means the image renders at its natural width — overflowing a narrow container such
42
+ // as the Slideout's single-column layout. Allow row children to shrink to the row width so
43
+ // the image's `max-width: 100%` can take effect. Column children (c1/c2) keep their own
44
+ // width rules, which win on specificity.
45
+ '& > *': {
46
+ minWidth: 0,
47
+ maxWidth: '100%',
48
+ },
49
+ },
50
+ // Mobile-first: every column spans the full row width so a multi-column layout
51
+ // stacks into a single column. Configured column widths apply at the desktop
52
+ // breakpoint below.
53
+ '& .ss__quickview__column': {
54
+ display: 'flex',
55
+ flexDirection: 'column',
56
+ gap: '12px',
57
+ minWidth: 0,
58
+ flex: '1 1 100%',
59
+ maxWidth: '100%',
60
+ },
61
+ '& .ss__quickview__column.ss__quickview__column--c1': {
62
+ alignContent: column1?.alignContent,
63
+ },
64
+ '& .ss__quickview__column.ss__quickview__column--c2': {
65
+ alignContent: column2?.alignContent,
66
+ },
67
+ '& .ss__quickview__column.ss__quickview__column--c3': {
68
+ alignContent: column3?.alignContent,
69
+ },
70
+ '& .ss__quickview__column.ss__quickview__column--c4': {
71
+ alignContent: column4?.alignContent,
72
+ },
73
+ // Modules whose element renders nothing (e.g. a ProductDetail resolving an absent field)
74
+ // can leave an empty row/column in the DOM — hide it so the flex gap doesn't show.
75
+ '& .ss__quickview__column:empty, & .ss__quickview__row:empty': {
76
+ display: 'none',
77
+ },
78
+ // The `_` module: a flexible spacer that pushes its siblings apart.
79
+ '& .ss__quickview__separator': {
80
+ flexGrow: 1,
81
+ flexShrink: 1,
82
+ },
83
+ '& .ss__quickview__slideshow': {
84
+ marginBottom: 0,
85
+ },
86
+ '& .ss__quickview__title': {
87
+ fontSize: '1.4em',
88
+ paddingRight: '32px', // leave room for the close button
89
+ },
90
+ '& .ss__quickview__variant': {
91
+ marginBottom: '12px',
92
+ // Slideshow centers its track when there are fewer swatches than slidesPerView — left-align instead.
93
+ '& .ss__slideshow__track--centered': {
94
+ justifyContent: 'flex-start',
95
+ },
96
+ },
97
+ '& .ss__quickview__variant-title': {
98
+ marginBottom: '6px',
99
+ fontWeight: 600,
100
+ },
101
+ '& .ss__quickview__image': {
102
+ display: 'block',
103
+ maxWidth: '100%',
104
+ marginBottom: '12px',
105
+ cursor: 'zoom-in',
106
+ '& img': {
107
+ display: 'block',
108
+ maxWidth: '100%',
109
+ },
110
+ },
111
+ '& .ss__quickview__carousel': {
112
+ // Slideshow defaults its slide images to objectFit:cover; the quickview hero image should
113
+ // display uncropped at its natural aspect ratio instead.
114
+ '& .ss__slideshow__slide img': {
115
+ objectFit: 'contain',
116
+ height: 'auto',
117
+ },
118
+ // Match the single-image zoom-in affordance (the clickable slide opens the lightbox).
119
+ '& .ss__slideshow__slide--clickable': {
120
+ cursor: 'zoom-in',
121
+ },
122
+ // Slideshow pins its nav buttons to width:10px; under a border-box reset the padding
123
+ // collapses the content box and the arrow icon shrinks to nothing (a blank white box).
124
+ // Let the buttons size to their icon so the prev/next angles actually render.
125
+ '& .ss__slideshow__navigation .ss__button': {
126
+ boxSizing: 'content-box',
127
+ width: 'auto',
128
+ },
129
+ },
130
+ '& .ss__quickview__variants': {
131
+ display: 'flex',
132
+ flexDirection: 'column',
133
+ gap: '12px',
134
+ // Each layout entry is wrapped in a flex row whose children size to their content (no
135
+ // flex-grow). Span the full row so the variant selectors — notably the swatch Slideshow,
136
+ // whose track reserves `calc(100% - 60px)` for nav arrows and collapses to 0 width (hiding
137
+ // every swatch) when its container is narrow — have room to render.
138
+ width: '100%',
139
+ },
140
+ '& .ss__quickview__description': {
141
+ lineHeight: 1.4,
142
+ },
143
+ '& .ss__quickview__close': {
144
+ position: 'absolute',
145
+ top: '12px',
146
+ right: '12px',
147
+ background: 'transparent',
148
+ border: 'none',
149
+ fontSize: '1.4em',
150
+ cursor: 'pointer',
151
+ lineHeight: 1,
152
+ zIndex: 1,
153
+ },
154
+ '& .ss__quickview__loading': {
155
+ padding: '40px',
156
+ textAlign: 'center',
157
+ minWidth: '200px',
158
+ },
159
+ '& .ss__quickview__error': {
160
+ padding: '40px',
161
+ textAlign: 'center',
162
+ minWidth: '200px',
163
+ color: '#b00020',
164
+ },
165
+ '@media (min-width: 768px)': {
166
+ '& .ss__quickview__content': {
167
+ maxWidth: '880px',
168
+ },
169
+ '& .ss__quickview__column.ss__quickview__column--c1': {
170
+ flex: column1?.width == 'auto' ? '1 1 0' : `1 1 ${column1?.width}`,
171
+ maxWidth: column1?.width == 'auto' ? 'none' : column1?.width,
172
+ },
173
+ '& .ss__quickview__column.ss__quickview__column--c2': {
174
+ flex: column2?.width == 'auto' ? '1 1 0' : `1 1 ${column2?.width}`,
175
+ maxWidth: column2?.width == 'auto' ? 'none' : column2?.width,
176
+ },
177
+ '& .ss__quickview__column.ss__quickview__column--c3': {
178
+ flex: column3?.width == 'auto' ? '1 1 0' : `1 1 ${column3?.width}`,
179
+ maxWidth: column3?.width == 'auto' ? 'none' : column3?.width,
180
+ },
181
+ '& .ss__quickview__column.ss__quickview__column--c4': {
182
+ flex: column4?.width == 'auto' ? '1 1 0' : `1 1 ${column4?.width}`,
183
+ maxWidth: column4?.width == 'auto' ? 'none' : column4?.width,
184
+ },
185
+ },
186
+ });
187
+ };
188
+ // Coerce an image-list field value into an array of image URL strings.
189
+ // Handles real arrays and MobX observable arrays; anything else → [].
190
+ const toImageArray = (value) => {
191
+ if (Array.isArray(value) || isObservableArray(value)) {
192
+ return Array.from(value).filter((v) => typeof v === 'string' && v.length > 0);
193
+ }
194
+ return [];
195
+ };
196
+ // Collect every `recommendation.<profile>` profile the active `layout` will actually render. Walks
197
+ // the layout and, on a column token (`c1`..`c4`), descends into that column's layout — mirroring
198
+ // findModule, which only renders a column the layout references. Columns the layout never references
199
+ // are skipped so their profiles don't spawn phantom controllers/searches. Deduped + sorted so the
200
+ // per-profile hook calls below keep a stable count/order across renders.
201
+ const collectRecommendationProfiles = (layout, columns) => {
202
+ const profiles = new Set();
203
+ const visitedColumns = new Set();
204
+ const walk = (node) => {
205
+ if (typeof node === 'string') {
206
+ if (node.startsWith('recommendation.')) {
207
+ profiles.add(node.slice('recommendation.'.length));
208
+ }
209
+ else if (node in columns && !visitedColumns.has(node)) {
210
+ visitedColumns.add(node);
211
+ walk(columns[node]);
212
+ }
213
+ }
214
+ else if (Array.isArray(node)) {
215
+ node.forEach(walk);
216
+ }
217
+ };
218
+ walk(layout);
219
+ return Array.from(profiles).sort();
220
+ };
221
+ // Impression-tracking wrapper used by the quickview containers (QuickviewModal /
222
+ // QuickviewSlideout). Containers mount it keyed by response/product so each displayed
223
+ // product is observed and tracked once via the standard useTracking hook. Tracking goes through
224
+ // the manager, which delegates to the originating controller with `quickView: true` — that flag
225
+ // both marks the beacon event as a quickview view and gives it its own dedup slot, so the
226
+ // impression still sends for a product whose grid impression was already tracked on the same
227
+ // response. Click tracking is disabled — quickview interactions are not clickThroughs; only the
228
+ // "More info" button tracks one.
229
+ export const QuickviewTracker = ({ quickviewManager, product, children, }) => {
230
+ const { trackingRef } = useTracking({ controller: quickviewManager, result: product, track: { click: false, options: { threshold: 0 } } });
231
+ return (_jsx("div", { className: "ss__quickview__tracker", ref: trackingRef, children: children }));
232
+ };
233
+ export const QuickviewLayout = observer((properties) => {
234
+ const globalTheme = useTheme();
235
+ const snap = useSnap();
236
+ const globalTreePath = useTreePath();
237
+ // Fullscreen image gallery (lightbox) state. Declared before any conditional return so hook
238
+ // order stays stable.
239
+ const [galleryOpen, setGalleryOpen] = useState(false);
240
+ const [galleryIndex, setGalleryIndex] = useState(0);
241
+ // Mirrors galleryOpen for the useA11y escape callback, which binds once per content element
242
+ // and would otherwise capture a stale value.
243
+ const galleryOpenRef = useRef(false);
244
+ galleryOpenRef.current = galleryOpen;
245
+ const openGallery = (i) => {
246
+ setGalleryIndex(i);
247
+ setGalleryOpen(true);
248
+ };
249
+ const defaultProps = {
250
+ treePath: globalTreePath,
251
+ hideBadge: false,
252
+ };
253
+ const props = mergeProps('quickviewLayout', globalTheme, defaultProps, properties);
254
+ const { quickviewManager, className, internalClassName, disableStyles, treePath, hideBadge, column1, column2, column3, column4, recommendation } = props;
255
+ // NOTE: the `!shouldRenderDefault` return lives below the last hook call — every hook in this
256
+ // component must run unconditionally on every render (shouldRenderDefault can flip while
257
+ // mounted, e.g. when a pending customComponent import resolves or fails).
258
+ const { overrideElement, shouldRenderDefault } = useCustomComponentOverride('quickview', props);
259
+ //initialize lang
260
+ const defaultLang = {
261
+ quickview: {
262
+ attributes: {
263
+ 'aria-label': 'Quickview',
264
+ },
265
+ },
266
+ closeButton: {
267
+ attributes: {
268
+ 'aria-label': 'Close quickview',
269
+ },
270
+ },
271
+ addToCartButton: {
272
+ value: 'Add to Cart',
273
+ },
274
+ moreInfoButton: {
275
+ value: 'More info',
276
+ },
277
+ loadingText: {
278
+ value: 'Loading…',
279
+ },
280
+ };
281
+ //deep merge with props.lang
282
+ const lang = deepmerge(defaultLang, props.lang || {});
283
+ const mergedLang = useLang(lang, {
284
+ quickviewManager,
285
+ });
286
+ // Hoist the slide-sync inputs before any conditional return so the hooks below
287
+ // are unconditional. All reads use optional chaining and safely produce defaults when
288
+ // the manager/product are absent.
289
+ const product = quickviewManager?.store?.product;
290
+ const core = product?.display?.mappings?.core || product?.mappings?.core;
291
+ const image = core?.imageUrl || core?.thumbnailImageUrl;
292
+ // Resolve the image-list field. `config.imagesField` accepts a single field name or an
293
+ // array of candidate names; when omitted it defaults to trying 'images' then 'ss_images'.
294
+ // Each candidate is looked up on mappings.core first, then attributes; the first that
295
+ // resolves to MORE THAN ONE image wins and is rendered as a 1-per-view slideshow. If none
296
+ // qualify, the modal falls back to the single core image below.
297
+ const configuredImagesField = quickviewManager?.store?.resolvedConfig?.imagesField;
298
+ const imageFieldCandidates = configuredImagesField
299
+ ? Array.isArray(configuredImagesField)
300
+ ? configuredImagesField
301
+ : [configuredImagesField]
302
+ : ['images', 'ss_images'];
303
+ const coreRecord = core;
304
+ const allAttributes = product?.display?.attributes || product?.attributes || {};
305
+ const activeVariant = product?.variants?.active;
306
+ const variantCore = activeVariant?.mappings?.core;
307
+ const variantAttributes = activeVariant?.attributes || {};
308
+ const resolveImages = (coreData, attrs) => {
309
+ for (const field of imageFieldCandidates) {
310
+ const candidate = toImageArray(coreData?.[field] ?? attrs?.[field]);
311
+ if (candidate.length > 1)
312
+ return candidate;
313
+ }
314
+ return [];
315
+ };
316
+ // Variant-aware image resolution. When a variant is active, use its own image array
317
+ // for the slideshow. If the variant has no multi-image field, show just its single
318
+ // imageUrl (no slideshow) rather than falling back to the parent's array — the parent
319
+ // images may depict other variants and would be misleading.
320
+ const variantImageList = activeVariant ? resolveImages(variantCore, variantAttributes) : [];
321
+ const parentImageList = resolveImages(coreRecord, allAttributes);
322
+ const imageList = activeVariant ? (variantImageList.length > 1 ? variantImageList : []) : parentImageList;
323
+ const hasMultipleImages = imageList.length > 1;
324
+ // When a variant is active, find its image in the slideshow so we can navigate to the
325
+ // correct slide instead of always staying on slide 0.
326
+ let targetSlide = 0;
327
+ if (activeVariant && hasMultipleImages && image) {
328
+ const idx = imageList.indexOf(image);
329
+ if (idx >= 0)
330
+ targetSlide = idx;
331
+ }
332
+ // Escape closes the quickview — unless the fullscreen gallery is layered on top,
333
+ // in which case Gallery's own Escape handler closes the gallery first.
334
+ // This window listener is the fallback for when focus sits outside the content focus
335
+ // trap (useA11y on the content div handles Escape — with stopPropagation — when focus
336
+ // is within it).
337
+ useEffect(() => {
338
+ const isOpenNow = Boolean(quickviewManager?.store?.isOpen);
339
+ if (!shouldRenderDefault || !isOpenNow)
340
+ return;
341
+ const onKey = (e) => {
342
+ if (e.key === 'Escape' && !galleryOpen) {
343
+ quickviewManager.close();
344
+ }
345
+ };
346
+ window.addEventListener('keydown', onKey);
347
+ return () => window.removeEventListener('keydown', onKey);
348
+ }, [shouldRenderDefault, quickviewManager?.store?.isOpen, galleryOpen]);
349
+ // Recommendation modules. `findModule` runs inside .map()/recursion and must not call hooks, so
350
+ // resolve every referenced profile's controller + components here (stable order) and let
351
+ // findModule read from this map. Mirrors Organisms/NoResults.
352
+ // The profile list and template availability are frozen on mount: the per-profile hook calls
353
+ // below must keep a stable count/order for the lifetime of this instance, and a responsive
354
+ // theme override could otherwise change the list while mounted. Profiles added by such a
355
+ // change render only after a remount.
356
+ const recommendationProfiles = useRef(collectRecommendationProfiles(props.layout, {
357
+ c1: column1?.layout,
358
+ c2: column2?.layout,
359
+ c3: column3?.layout,
360
+ c4: column4?.layout,
361
+ })).current;
362
+ const recsByProfile = new Map();
363
+ const snapTemplates = snap;
364
+ const hasTemplates = useRef(Boolean(snapTemplates?.templates)).current;
365
+ // only resolve component names when the layout actually references a `recommendation.<profile>`
366
+ const hasRecommendationModules = recommendationProfiles.length > 0;
367
+ const componentName = hasTemplates && hasRecommendationModules ? recommendation?.component || 'Recommendation' : undefined;
368
+ const resultComponentName = hasTemplates && hasRecommendationModules ? (recommendation?.resultComponent || 'Result') : undefined;
369
+ const ResultComponent = useComponent(snapTemplates?.templates?.library.import.component.result || {}, resultComponentName).ComponentOverride;
370
+ const Component = useComponent(snapTemplates?.templates?.library.import.component.recommendation.default || {}, componentName).ComponentOverride;
371
+ for (const profile of recommendationProfiles) {
372
+ const mergedConfig = Object.assign({ id: '', tag: profile, branch: 'production' }, recommendation?.config);
373
+ mergedConfig.tag = profile; // the module name always wins for tag
374
+ mergedConfig.id = mergedConfig.id || `quickview-${profile}`;
375
+ const recsController = hasTemplates ? useCreateController(snapTemplates, 'recommendation', mergedConfig) : undefined;
376
+ recsByProfile.set(profile, {
377
+ Component: Component,
378
+ ResultComponent,
379
+ recsController,
380
+ });
381
+ }
382
+ // Seed each recommendation with the currently-viewed product and (re)search when it changes.
383
+ // The controllers are resolved once by id (useCreateController), so the seed is applied here.
384
+ const recommendationSeed = core?.parentId || product?.id;
385
+ // useCreateController resolves its controller asynchronously — on the render where this effect first
386
+ // runs the controllers are still undefined. Key the effect on which profiles have a resolved controller
387
+ // so it re-runs (and finally seeds + searches) once they resolve; otherwise the search is skipped and
388
+ // never retried because the seed/profile deps don't change after mount.
389
+ const resolvedRecsKey = recommendationProfiles.map((profile) => (recsByProfile.get(profile)?.recsController ? profile : '')).join(',');
390
+ // The seed each controller was last searched with. The effect re-runs whenever ANOTHER
391
+ // profile's controller resolves (resolvedRecsKey), so without this an already-seeded
392
+ // controller would get search() called again — re-firing middleware and re-sending the
393
+ // render beacon.
394
+ const seededRecsRef = useRef(new Map());
395
+ useEffect(() => {
396
+ if (!shouldRenderDefault || !recommendationSeed)
397
+ return;
398
+ recsByProfile.forEach(({ recsController }) => {
399
+ if (!recsController)
400
+ return;
401
+ if (seededRecsRef.current.get(recsController.config.id) === recommendationSeed)
402
+ return;
403
+ seededRecsRef.current.set(recsController.config.id, recommendationSeed);
404
+ recsController.config.globals = { ...recsController.config.globals, products: [recommendationSeed] };
405
+ recsController.search();
406
+ });
407
+ // recsByProfile is rebuilt each render but holds the same (memoized) controller instances;
408
+ // re-run when the seed, the set of profiles, or the set of resolved controllers changes.
409
+ }, [shouldRenderDefault, recommendationSeed, recommendationProfiles.join(','), resolvedRecsKey]);
410
+ if (!shouldRenderDefault) {
411
+ return overrideElement;
412
+ }
413
+ const styling = mergeStyles(props, defaultStyles);
414
+ if (!quickviewManager) {
415
+ console.warn(`[QuickviewLayout] No quickviewManager provided; quickview cannot function without a QuickviewManager instance.`);
416
+ return null;
417
+ }
418
+ const store = quickviewManager.store;
419
+ const loading = Boolean(store.loading);
420
+ const configuredDisplayFields = store.resolvedConfig?.displayFields;
421
+ const displayFields = typeof configuredDisplayFields === 'function' ? (product ? configuredDisplayFields(product) : undefined) : configuredDisplayFields;
422
+ const error = store.error;
423
+ // Look up the display label for a field name from meta.facets[field].label.
424
+ // Falls back to the raw field name when no meta entry exists.
425
+ const metaFacets = quickviewManager.sourceController?.store.meta?.data?.facets;
426
+ const labelFor = (field) => metaFacets?.[field]?.label || field;
427
+ // Close is delegated to the container (Modal/Slideout) via onClose; fall back to the
428
+ // manager directly so the layout still works when rendered standalone.
429
+ const onClose = () => {
430
+ quickviewManager.close();
431
+ props.onClose && props.onClose();
432
+ };
433
+ // Escape inside the focus trap: the gallery layers above the quickview, so close it
434
+ // first; otherwise close the quickview itself.
435
+ const handleEscape = () => {
436
+ if (galleryOpenRef.current) {
437
+ setGalleryOpen(false);
438
+ }
439
+ else {
440
+ onClose();
441
+ }
442
+ };
443
+ // Dialog semantics + focus trap for the quickview content, following the autocomplete
444
+ // containers (AutocompleteModal/AutocompleteSlideout): useA11y traps Tab within the
445
+ // content and wires Escape to the callback above.
446
+ const contentProps = {
447
+ className: 'ss__quickview__content',
448
+ role: 'dialog',
449
+ 'aria-modal': 'true',
450
+ ref: (e) => useA11y(e, 0, true, handleEscape),
451
+ ...mergedLang.quickview?.attributes,
452
+ };
453
+ // Prefer `product.display` so the displayed name/image/attributes reflect the
454
+ // currently active variant (Mask-merged), falling back to the base product data.
455
+ const name = core?.name;
456
+ const url = core?.url;
457
+ const selections = product?.variants?.selections;
458
+ // Images shown in the fullscreen gallery: the multi-image list when present, otherwise the
459
+ // single core image (so clicking a lone image still opens the zoomable gallery).
460
+ const galleryImages = hasMultipleImages ? imageList : image ? [image] : [];
461
+ // Prepare slides for the slideshow. Use imageList when available, otherwise use the single image.
462
+ const slidesData = hasMultipleImages ? imageList : image ? [image] : [];
463
+ const hasSingleImage = slidesData.length === 1;
464
+ // The slideshow region: always use Slideshow component. When there's only one image, hide navigation and pagination.
465
+ // Clicking a slide opens the fullscreen gallery at that index. When the active variant changes,
466
+ // `startIndex` navigates to the variant's image without remounting.
467
+ const slideshowContent = slidesData.length > 0 ? (_jsx(Slideshow, { className: "ss__quickview__carousel", startIndex: targetSlide, slidesToShow: 1, slidesToMove: 1, showNavigation: !hasSingleImage, overlayNavigation: true, showPagination: !hasSingleImage, loop: false, slides: slidesData.map((src, i) => ({
468
+ src,
469
+ alt: name || '',
470
+ onClick: () => openGallery(i),
471
+ })), theme: props.theme, treePath: treePath, ...defined({ disableStyles }) })) : null;
472
+ // Module renderers. Each returns the corresponding region, or null when it has nothing to
473
+ // show (so empty columns/rows collapse). Columns (c1/c2) recurse into their own layouts.
474
+ const findModule = (module) => {
475
+ // new row
476
+ if (typeof module !== 'string') {
477
+ const children = module.map((subModule) => findModule(subModule));
478
+ const hasContent = module.some((subModule, i) => subModule !== '_' && children[i]);
479
+ if (!hasContent)
480
+ return null;
481
+ return _jsx("div", { className: "ss__quickview__row", children: children });
482
+ }
483
+ if (module == 'c1' && column1?.layout?.length) {
484
+ const children = column1.layout.map((m) => findModule(m));
485
+ const hasContent = column1.layout.some((m, i) => (Array.isArray(m) ? Boolean(children[i]) : m !== '_' && Boolean(children[i])));
486
+ if (!hasContent)
487
+ return null;
488
+ return _jsx("div", { className: "ss__quickview__column ss__quickview__column--c1", children: children });
489
+ }
490
+ if (module == 'c2' && column2?.layout?.length) {
491
+ const children = column2.layout.map((m) => findModule(m));
492
+ const hasContent = column2.layout.some((m, i) => (Array.isArray(m) ? Boolean(children[i]) : m !== '_' && Boolean(children[i])));
493
+ if (!hasContent)
494
+ return null;
495
+ return _jsx("div", { className: "ss__quickview__column ss__quickview__column--c2", children: children });
496
+ }
497
+ if (module == 'c3' && column3?.layout?.length) {
498
+ const children = column3.layout.map((m) => findModule(m));
499
+ const hasContent = column3.layout.some((m, i) => (Array.isArray(m) ? Boolean(children[i]) : m !== '_' && Boolean(children[i])));
500
+ if (!hasContent)
501
+ return null;
502
+ return _jsx("div", { className: "ss__quickview__column ss__quickview__column--c3", children: children });
503
+ }
504
+ if (module == 'c4' && column4?.layout?.length) {
505
+ const children = column4.layout.map((m) => findModule(m));
506
+ const hasContent = column4.layout.some((m, i) => (Array.isArray(m) ? Boolean(children[i]) : m !== '_' && Boolean(children[i])));
507
+ if (!hasContent)
508
+ return null;
509
+ return _jsx("div", { className: "ss__quickview__column ss__quickview__column--c4", children: children });
510
+ }
511
+ if (module == 'slideshow') {
512
+ if (!slideshowContent || !product)
513
+ return null;
514
+ return (_jsx("div", { className: "ss__quickview__slideshow", children: hideBadge ? (slideshowContent) : (_jsx(OverlayBadge, { result: product, controller: quickviewManager.sourceController, theme: props.theme, treePath: treePath, ...defined({ disableStyles }), children: slideshowContent })) }));
515
+ }
516
+ // `calloutBadge` renders badges at the default tag; `calloutBadge.<tag>` renders badges
517
+ // at a custom tag location (e.g. `calloutBadge.callout-secondary`).
518
+ if (module == 'calloutBadge' || module.startsWith('calloutBadge.')) {
519
+ if (!product)
520
+ return null;
521
+ const tag = module.startsWith('calloutBadge.') ? module.slice('calloutBadge.'.length) : undefined;
522
+ return _jsx(CalloutBadge, { result: product, theme: props.theme, treePath: treePath, ...defined({ disableStyles, tag }) });
523
+ }
524
+ // `productDetail.<path>` renders a single product field resolved from an explicit dot-path
525
+ // (e.g. `productDetail.mappings.core.name` or `productDetail.attributes.brand`). The product
526
+ // name is the "title", the `description` field renders as rich HTML; any other field renders
527
+ // as text. ProductDetail resolves the path and returns null when empty.
528
+ if (module.startsWith('productDetail.')) {
529
+ const path = module.slice('productDetail.'.length);
530
+ const field = path.split('.').pop() || '';
531
+ if (!path || !product)
532
+ return null;
533
+ // Preserve the legacy quickview classnames so existing styles/themes/tests keep matching.
534
+ const legacyClass = field === 'name' ? 'ss__quickview__title' : field === 'description' ? 'ss__quickview__description' : `ss__quickview__${field}`;
535
+ return (_jsx(ProductDetail, { result: product, field: path, html: field === 'description', className: legacyClass, theme: props.theme, treePath: treePath, ...defined({ disableStyles }) }));
536
+ }
537
+ // `variantSelections` renders every variant selection; `variantSelection.<field>` renders only
538
+ // the selection whose field matches (e.g. `variantSelection.color`). The field also matches its
539
+ // component-name form (`color_family` → `color-family`). A bare `variantSelection` module is
540
+ // not supported.
541
+ if (module == 'variantSelections') {
542
+ if (!selections || selections.length === 0)
543
+ return null;
544
+ return (_jsx("div", { className: "ss__quickview__variants", children: selections.map((selection) => (_jsxs("div", { className: "ss__quickview__variant", children: [_jsx("div", { className: "ss__quickview__variant-title", children: selection.label || selection.field }), _jsx(VariantSelection, { selection: selection, type: selection.type, theme: props.theme, treePath: treePath, ...defined({ disableStyles }) })] }, selection.field))) }));
545
+ }
546
+ if (module.startsWith('variantSelection.')) {
547
+ const name = module.slice('variantSelection.'.length);
548
+ const selection = selections?.find((selection) => selection.field === name || fieldNameToComponentName(selection.field) === name);
549
+ if (!name || !selection)
550
+ return null;
551
+ return (_jsxs("div", { className: "ss__quickview__variant", children: [_jsx("div", { className: "ss__quickview__variant-title", children: selection.label || selection.field }), _jsx(VariantSelection, { selection: selection, type: selection.type, theme: props.theme, treePath: treePath, ...defined({ disableStyles }) })] }));
552
+ }
553
+ if (module == 'button.add-to-cart') {
554
+ if (!product)
555
+ return null;
556
+ return (_jsx(Button, { name: "add-to-cart", internalClassName: "ss__quickview__add-to-cart", lang: { button: lang.addToCartButton }, onClick: () => product && quickviewManager.addToCart([product]), theme: props.theme, treePath: treePath, ...defined({ disableStyles }) }));
557
+ }
558
+ if (module == 'button.more-info') {
559
+ if (!url)
560
+ return null;
561
+ return (_jsx(Button, { name: "more-info", internalClassName: "ss__quickview__go-to-product", lang: { button: lang.moreInfoButton }, onClick: (e) => {
562
+ // track the redirect to the product page as a quickview clickThrough
563
+ // before navigating away (delegated with `quickView: true`)
564
+ if (product) {
565
+ quickviewManager.track.product.clickThrough(e, product);
566
+ }
567
+ window.location.href = url;
568
+ }, theme: props.theme, treePath: treePath, ...defined({ disableStyles }) }));
569
+ }
570
+ // `quantityPicker` binds to the observable `product.quantity`, which `button.add-to-cart`
571
+ // (via the cart store) picks up when the product is added.
572
+ if (module == 'quantityPicker') {
573
+ if (!product)
574
+ return null;
575
+ return (_jsx(QuantityPicker, { internalClassName: "ss__quickview__quantity-picker", value: product.quantity, onChange: (e, value) => (product.quantity = value), theme: props.theme, treePath: treePath, ...defined({ disableStyles }) }));
576
+ }
577
+ if (module == 'productDetailTable') {
578
+ if (!product)
579
+ return null;
580
+ // Label precedence: explicit config label, then the meta facet label, then the raw field key.
581
+ const labeledFields = (displayFields || []).map((detail) => ({ ...detail, label: detail.label ?? labelFor(detail.field) }));
582
+ return (_jsx(ProductDetailTable, { result: product, displayFields: labeledFields, className: "ss__quickview__attributes", theme: props.theme, treePath: treePath, ...defined({ disableStyles }) }));
583
+ }
584
+ if (module.startsWith('recommendation.')) {
585
+ const profile = module.slice('recommendation.'.length);
586
+ const entry = recsByProfile.get(profile);
587
+ const RecComponent = entry?.Component;
588
+ const recsController = entry?.recsController;
589
+ if (!RecComponent || !recsController?.store?.loaded)
590
+ return null;
591
+ return (_jsx("div", { className: "ss__quickview__recommendations", children: _jsx(RecComponent, { controller: recsController, title: recsController.store?.profile?.display?.templateParameters?.title, resultComponent: entry?.ResultComponent, name: profile }) }));
592
+ }
593
+ if (module == '_') {
594
+ return _jsx("div", { className: "ss__quickview__separator" });
595
+ }
596
+ return null;
597
+ };
598
+ let layout = props.layout;
599
+ if (typeof layout === 'string') {
600
+ quickviewManager.sourceController?.log.warn(`unsupported layout found. ${props.layout}`);
601
+ layout = [];
602
+ }
603
+ const closeButton = (_jsx(Button, { name: "close", internalClassName: "ss__quickview__close", icon: "close-thin", lang: { button: lang.closeButton }, onClick: () => onClose(), theme: props.theme, treePath: treePath, ...defined({ disableStyles }) }));
604
+ return (_jsx(CacheProvider, { children: _jsx("div", { ...styling, className: classnames('ss__quickview', className, internalClassName), children: error || loading || product ? (_jsxs("div", { ...contentProps, children: [closeButton, error ? (_jsx("div", { className: "ss__quickview__error", role: "alert", children: error.message })) : loading ? (_jsx("div", { className: "ss__quickview__loading", ...mergedLang.loadingText?.all })) : (_jsxs(_Fragment, { children: [layout?.map((module) => findModule(module)), _jsx(Gallery, { images: galleryImages, open: galleryOpen, startIndex: galleryIndex, onClose: () => setGalleryOpen(false), alt: name, theme: props.theme, treePath: treePath, ...defined({ disableStyles }) })] }))] })) : null }) }));
605
+ });
@@ -0,0 +1,2 @@
1
+ export * from './QuickviewLayout';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../components/src/components/Organisms/QuickviewLayout/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './QuickviewLayout';
@@ -114,7 +114,7 @@ export const AutocompleteFixed = observer((properties) => {
114
114
  },
115
115
  modal: {
116
116
  // default props
117
- internalClassName: 'autocomplete-fixed__modal',
117
+ internalClassName: 'ss__autocomplete-fixed__modal',
118
118
  buttonSelector: buttonSelector,
119
119
  lockScroll: false,
120
120
  onOverlayClick: reset,
@@ -130,8 +130,8 @@ export const AutocompleteFixed = observer((properties) => {
130
130
  },
131
131
  searchInput: {
132
132
  // default props
133
- // autocomplete__search-input is required for useAcRenderedInput hook.
134
- internalClassName: 'autocomplete-fixed__search-input autocomplete__search-input',
133
+ // ss__autocomplete__search-input is required for useAcRenderedInput hook.
134
+ internalClassName: 'ss__autocomplete-fixed__search-input ss__autocomplete__search-input',
135
135
  placeholderText: inputPlaceholderText || undefined,
136
136
  submitSearchButton: {
137
137
  onClick: () => {
@@ -126,7 +126,7 @@ export const AutocompleteModal = observer((properties) => {
126
126
  },
127
127
  modal: {
128
128
  // default props
129
- internalClassName: 'autocomplete-modal__modal',
129
+ internalClassName: 'ss__autocomplete-modal__modal',
130
130
  buttonSelector: buttonSelector,
131
131
  onOverlayClick: reset,
132
132
  overlayColor: overlayColor,
@@ -141,8 +141,8 @@ export const AutocompleteModal = observer((properties) => {
141
141
  },
142
142
  searchInput: {
143
143
  // default props
144
- // autocomplete__search-input is required for useAcRenderedInput hook.
145
- internalClassName: 'autocomplete-modal__search-input autocomplete__search-input',
144
+ // ss__autocomplete__search-input is required for useAcRenderedInput hook.
145
+ internalClassName: 'ss__autocomplete-modal__search-input ss__autocomplete__search-input',
146
146
  submitSearchButton: {
147
147
  onClick: () => {
148
148
  () => reset();