medusa-storefront-data 2.5.1 → 2.5.3

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 (293) hide show
  1. package/HOMEPAGE_CONFIG.md +83 -10
  2. package/package.json +160 -115
  3. package/src/server/cart.ts +1 -1
  4. package/src/server/dynamic-config.ts +132 -12
  5. package/src/server/help-faq-section-defaults.json +92 -0
  6. package/src/server/help-sections/help-faq.ts +25 -0
  7. package/src/server/help-sections/index.ts +8 -0
  8. package/src/server/homepage-config.types.ts +24 -0
  9. package/src/server/homepage-section-defaults.ts +3 -0
  10. package/src/server/normalize-homepage-config.ts +39 -0
  11. package/dist/segment-data/default-page-input.json +0 -191
  12. package/dist/src/config.d.ts +0 -3
  13. package/dist/src/config.d.ts.map +0 -1
  14. package/dist/src/config.js +0 -31
  15. package/dist/src/cookies.d.ts +0 -23
  16. package/dist/src/cookies.d.ts.map +0 -1
  17. package/dist/src/cookies.js +0 -140
  18. package/dist/src/dynamic-config-schema/index.d.ts +0 -103
  19. package/dist/src/dynamic-config-schema/index.d.ts.map +0 -1
  20. package/dist/src/dynamic-config-schema/index.js +0 -172
  21. package/dist/src/dynamic-config-schema/sections/about-brand.d.ts +0 -5
  22. package/dist/src/dynamic-config-schema/sections/about-brand.d.ts.map +0 -1
  23. package/dist/src/dynamic-config-schema/sections/about-brand.js +0 -30
  24. package/dist/src/dynamic-config-schema/sections/baptism-picks.d.ts +0 -5
  25. package/dist/src/dynamic-config-schema/sections/baptism-picks.d.ts.map +0 -1
  26. package/dist/src/dynamic-config-schema/sections/baptism-picks.js +0 -17
  27. package/dist/src/dynamic-config-schema/sections/baptism.d.ts +0 -5
  28. package/dist/src/dynamic-config-schema/sections/baptism.d.ts.map +0 -1
  29. package/dist/src/dynamic-config-schema/sections/baptism.js +0 -4
  30. package/dist/src/dynamic-config-schema/sections/blog-posts.d.ts +0 -5
  31. package/dist/src/dynamic-config-schema/sections/blog-posts.d.ts.map +0 -1
  32. package/dist/src/dynamic-config-schema/sections/blog-posts.js +0 -31
  33. package/dist/src/dynamic-config-schema/sections/brand-marquee.d.ts +0 -5
  34. package/dist/src/dynamic-config-schema/sections/brand-marquee.d.ts.map +0 -1
  35. package/dist/src/dynamic-config-schema/sections/brand-marquee.js +0 -9
  36. package/dist/src/dynamic-config-schema/sections/brand-pillars.d.ts +0 -5
  37. package/dist/src/dynamic-config-schema/sections/brand-pillars.d.ts.map +0 -1
  38. package/dist/src/dynamic-config-schema/sections/brand-pillars.js +0 -29
  39. package/dist/src/dynamic-config-schema/sections/category-pills.d.ts +0 -5
  40. package/dist/src/dynamic-config-schema/sections/category-pills.d.ts.map +0 -1
  41. package/dist/src/dynamic-config-schema/sections/category-pills.js +0 -4
  42. package/dist/src/dynamic-config-schema/sections/celebrity-trust.d.ts +0 -5
  43. package/dist/src/dynamic-config-schema/sections/celebrity-trust.d.ts.map +0 -1
  44. package/dist/src/dynamic-config-schema/sections/celebrity-trust.js +0 -4
  45. package/dist/src/dynamic-config-schema/sections/features.d.ts +0 -5
  46. package/dist/src/dynamic-config-schema/sections/features.d.ts.map +0 -1
  47. package/dist/src/dynamic-config-schema/sections/features.js +0 -12
  48. package/dist/src/dynamic-config-schema/sections/hero.d.ts +0 -6
  49. package/dist/src/dynamic-config-schema/sections/hero.d.ts.map +0 -1
  50. package/dist/src/dynamic-config-schema/sections/hero.js +0 -9
  51. package/dist/src/dynamic-config-schema/sections/index.d.ts +0 -24
  52. package/dist/src/dynamic-config-schema/sections/index.d.ts.map +0 -1
  53. package/dist/src/dynamic-config-schema/sections/index.js +0 -23
  54. package/dist/src/dynamic-config-schema/sections/instagram-posts.d.ts +0 -5
  55. package/dist/src/dynamic-config-schema/sections/instagram-posts.d.ts.map +0 -1
  56. package/dist/src/dynamic-config-schema/sections/instagram-posts.js +0 -30
  57. package/dist/src/dynamic-config-schema/sections/loved-by-moms.d.ts +0 -5
  58. package/dist/src/dynamic-config-schema/sections/loved-by-moms.d.ts.map +0 -1
  59. package/dist/src/dynamic-config-schema/sections/loved-by-moms.js +0 -4
  60. package/dist/src/dynamic-config-schema/sections/luxe-favourites.d.ts +0 -5
  61. package/dist/src/dynamic-config-schema/sections/luxe-favourites.d.ts.map +0 -1
  62. package/dist/src/dynamic-config-schema/sections/luxe-favourites.js +0 -4
  63. package/dist/src/dynamic-config-schema/sections/new-arrivals-classic.d.ts +0 -5
  64. package/dist/src/dynamic-config-schema/sections/new-arrivals-classic.d.ts.map +0 -1
  65. package/dist/src/dynamic-config-schema/sections/new-arrivals-classic.js +0 -12
  66. package/dist/src/dynamic-config-schema/sections/new-arrivals.d.ts +0 -5
  67. package/dist/src/dynamic-config-schema/sections/new-arrivals.d.ts.map +0 -1
  68. package/dist/src/dynamic-config-schema/sections/new-arrivals.js +0 -12
  69. package/dist/src/dynamic-config-schema/sections/promo-announcements.d.ts +0 -5
  70. package/dist/src/dynamic-config-schema/sections/promo-announcements.d.ts.map +0 -1
  71. package/dist/src/dynamic-config-schema/sections/promo-announcements.js +0 -16
  72. package/dist/src/dynamic-config-schema/sections/promo-countdown.d.ts +0 -5
  73. package/dist/src/dynamic-config-schema/sections/promo-countdown.d.ts.map +0 -1
  74. package/dist/src/dynamic-config-schema/sections/promo-countdown.js +0 -16
  75. package/dist/src/dynamic-config-schema/sections/shop-by-age.d.ts +0 -5
  76. package/dist/src/dynamic-config-schema/sections/shop-by-age.d.ts.map +0 -1
  77. package/dist/src/dynamic-config-schema/sections/shop-by-age.js +0 -4
  78. package/dist/src/dynamic-config-schema/sections/shop-by-category.d.ts +0 -5
  79. package/dist/src/dynamic-config-schema/sections/shop-by-category.d.ts.map +0 -1
  80. package/dist/src/dynamic-config-schema/sections/shop-by-category.js +0 -4
  81. package/dist/src/dynamic-config-schema/sections/testimonials.d.ts +0 -5
  82. package/dist/src/dynamic-config-schema/sections/testimonials.d.ts.map +0 -1
  83. package/dist/src/dynamic-config-schema/sections/testimonials.js +0 -9
  84. package/dist/src/dynamic-config-schema/sections/theme-dresses.d.ts +0 -5
  85. package/dist/src/dynamic-config-schema/sections/theme-dresses.d.ts.map +0 -1
  86. package/dist/src/dynamic-config-schema/sections/theme-dresses.js +0 -4
  87. package/dist/src/dynamic-config-schema/sections/video-stories.d.ts +0 -5
  88. package/dist/src/dynamic-config-schema/sections/video-stories.d.ts.map +0 -1
  89. package/dist/src/dynamic-config-schema/sections/video-stories.js +0 -24
  90. package/dist/src/dynamic-config-schema/sections/why-choose-us.d.ts +0 -5
  91. package/dist/src/dynamic-config-schema/sections/why-choose-us.d.ts.map +0 -1
  92. package/dist/src/dynamic-config-schema/sections/why-choose-us.js +0 -9
  93. package/dist/src/dynamic-config-schema/shared.d.ts +0 -35
  94. package/dist/src/dynamic-config-schema/shared.d.ts.map +0 -1
  95. package/dist/src/dynamic-config-schema/shared.js +0 -99
  96. package/dist/src/dynamic-config-schema/site-configs.d.ts +0 -11
  97. package/dist/src/dynamic-config-schema/site-configs.d.ts.map +0 -1
  98. package/dist/src/dynamic-config-schema/site-configs.js +0 -70
  99. package/dist/src/edge.d.ts +0 -3
  100. package/dist/src/edge.d.ts.map +0 -1
  101. package/dist/src/edge.js +0 -1
  102. package/dist/src/middleware.d.ts +0 -3
  103. package/dist/src/middleware.d.ts.map +0 -1
  104. package/dist/src/middleware.js +0 -1
  105. package/dist/src/server/brand-pillars-from-categories.d.ts +0 -8
  106. package/dist/src/server/brand-pillars-from-categories.d.ts.map +0 -1
  107. package/dist/src/server/brand-pillars-from-categories.js +0 -92
  108. package/dist/src/server/cart.d.ts +0 -96
  109. package/dist/src/server/cart.d.ts.map +0 -1
  110. package/dist/src/server/cart.js +0 -797
  111. package/dist/src/server/categories.d.ts +0 -4
  112. package/dist/src/server/categories.d.ts.map +0 -1
  113. package/dist/src/server/categories.js +0 -34
  114. package/dist/src/server/collections.d.ts +0 -8
  115. package/dist/src/server/collections.d.ts.map +0 -1
  116. package/dist/src/server/collections.js +0 -39
  117. package/dist/src/server/config-merge.d.ts +0 -3
  118. package/dist/src/server/config-merge.d.ts.map +0 -1
  119. package/dist/src/server/config-merge.js +0 -31
  120. package/dist/src/server/contact.d.ts +0 -34
  121. package/dist/src/server/contact.d.ts.map +0 -1
  122. package/dist/src/server/contact.js +0 -57
  123. package/dist/src/server/customer-registration.d.ts +0 -142
  124. package/dist/src/server/customer-registration.d.ts.map +0 -1
  125. package/dist/src/server/customer-registration.js +0 -295
  126. package/dist/src/server/customer.d.ts +0 -48
  127. package/dist/src/server/customer.d.ts.map +0 -1
  128. package/dist/src/server/customer.js +0 -413
  129. package/dist/src/server/dynamic-config-api.d.ts +0 -11
  130. package/dist/src/server/dynamic-config-api.d.ts.map +0 -1
  131. package/dist/src/server/dynamic-config-api.js +0 -46
  132. package/dist/src/server/dynamic-config.d.ts +0 -157
  133. package/dist/src/server/dynamic-config.d.ts.map +0 -1
  134. package/dist/src/server/dynamic-config.js +0 -573
  135. package/dist/src/server/fulfillment.d.ts +0 -5
  136. package/dist/src/server/fulfillment.d.ts.map +0 -1
  137. package/dist/src/server/fulfillment.js +0 -47
  138. package/dist/src/server/guest.d.ts +0 -81
  139. package/dist/src/server/guest.d.ts.map +0 -1
  140. package/dist/src/server/guest.js +0 -183
  141. package/dist/src/server/home-sections/about-brand.d.ts +0 -9
  142. package/dist/src/server/home-sections/about-brand.d.ts.map +0 -1
  143. package/dist/src/server/home-sections/about-brand.js +0 -9
  144. package/dist/src/server/home-sections/baptism-picks.d.ts +0 -10
  145. package/dist/src/server/home-sections/baptism-picks.d.ts.map +0 -1
  146. package/dist/src/server/home-sections/baptism-picks.js +0 -27
  147. package/dist/src/server/home-sections/baptism.d.ts +0 -13
  148. package/dist/src/server/home-sections/baptism.d.ts.map +0 -1
  149. package/dist/src/server/home-sections/baptism.js +0 -43
  150. package/dist/src/server/home-sections/blog-posts.d.ts +0 -9
  151. package/dist/src/server/home-sections/blog-posts.d.ts.map +0 -1
  152. package/dist/src/server/home-sections/blog-posts.js +0 -9
  153. package/dist/src/server/home-sections/brand-marquee.d.ts +0 -8
  154. package/dist/src/server/home-sections/brand-marquee.d.ts.map +0 -1
  155. package/dist/src/server/home-sections/brand-marquee.js +0 -7
  156. package/dist/src/server/home-sections/brand-pillars.d.ts +0 -9
  157. package/dist/src/server/home-sections/brand-pillars.d.ts.map +0 -1
  158. package/dist/src/server/home-sections/brand-pillars.js +0 -9
  159. package/dist/src/server/home-sections/category-pills.d.ts +0 -9
  160. package/dist/src/server/home-sections/category-pills.d.ts.map +0 -1
  161. package/dist/src/server/home-sections/category-pills.js +0 -19
  162. package/dist/src/server/home-sections/celebrity-trust.d.ts +0 -12
  163. package/dist/src/server/home-sections/celebrity-trust.d.ts.map +0 -1
  164. package/dist/src/server/home-sections/celebrity-trust.js +0 -27
  165. package/dist/src/server/home-sections/features.d.ts +0 -9
  166. package/dist/src/server/home-sections/features.d.ts.map +0 -1
  167. package/dist/src/server/home-sections/features.js +0 -9
  168. package/dist/src/server/home-sections/hero.d.ts +0 -9
  169. package/dist/src/server/home-sections/hero.d.ts.map +0 -1
  170. package/dist/src/server/home-sections/hero.js +0 -9
  171. package/dist/src/server/home-sections/instagram-posts.d.ts +0 -9
  172. package/dist/src/server/home-sections/instagram-posts.d.ts.map +0 -1
  173. package/dist/src/server/home-sections/instagram-posts.js +0 -9
  174. package/dist/src/server/home-sections/loved-by-moms.d.ts +0 -12
  175. package/dist/src/server/home-sections/loved-by-moms.d.ts.map +0 -1
  176. package/dist/src/server/home-sections/loved-by-moms.js +0 -20
  177. package/dist/src/server/home-sections/luxe-favourites.d.ts +0 -11
  178. package/dist/src/server/home-sections/luxe-favourites.d.ts.map +0 -1
  179. package/dist/src/server/home-sections/luxe-favourites.js +0 -19
  180. package/dist/src/server/home-sections/new-arrivals-classic.d.ts +0 -8
  181. package/dist/src/server/home-sections/new-arrivals-classic.d.ts.map +0 -1
  182. package/dist/src/server/home-sections/new-arrivals-classic.js +0 -10
  183. package/dist/src/server/home-sections/new-arrivals.d.ts +0 -12
  184. package/dist/src/server/home-sections/new-arrivals.d.ts.map +0 -1
  185. package/dist/src/server/home-sections/new-arrivals.js +0 -28
  186. package/dist/src/server/home-sections/promo-announcements.d.ts +0 -7
  187. package/dist/src/server/home-sections/promo-announcements.d.ts.map +0 -1
  188. package/dist/src/server/home-sections/promo-announcements.js +0 -7
  189. package/dist/src/server/home-sections/promo-countdown.d.ts +0 -6
  190. package/dist/src/server/home-sections/promo-countdown.d.ts.map +0 -1
  191. package/dist/src/server/home-sections/promo-countdown.js +0 -5
  192. package/dist/src/server/home-sections/shared.d.ts +0 -10
  193. package/dist/src/server/home-sections/shared.d.ts.map +0 -1
  194. package/dist/src/server/home-sections/shared.js +0 -29
  195. package/dist/src/server/home-sections/shop-by-age.d.ts +0 -9
  196. package/dist/src/server/home-sections/shop-by-age.d.ts.map +0 -1
  197. package/dist/src/server/home-sections/shop-by-age.js +0 -17
  198. package/dist/src/server/home-sections/shop-by-category.d.ts +0 -10
  199. package/dist/src/server/home-sections/shop-by-category.d.ts.map +0 -1
  200. package/dist/src/server/home-sections/shop-by-category.js +0 -17
  201. package/dist/src/server/home-sections/testimonials.d.ts +0 -9
  202. package/dist/src/server/home-sections/testimonials.d.ts.map +0 -1
  203. package/dist/src/server/home-sections/testimonials.js +0 -9
  204. package/dist/src/server/home-sections/theme-dresses.d.ts +0 -12
  205. package/dist/src/server/home-sections/theme-dresses.d.ts.map +0 -1
  206. package/dist/src/server/home-sections/theme-dresses.js +0 -27
  207. package/dist/src/server/home-sections/video-stories.d.ts +0 -9
  208. package/dist/src/server/home-sections/video-stories.d.ts.map +0 -1
  209. package/dist/src/server/home-sections/video-stories.js +0 -9
  210. package/dist/src/server/home-sections/why-choose-us.d.ts +0 -9
  211. package/dist/src/server/home-sections/why-choose-us.d.ts.map +0 -1
  212. package/dist/src/server/home-sections/why-choose-us.js +0 -9
  213. package/dist/src/server/home.d.ts +0 -51
  214. package/dist/src/server/home.d.ts.map +0 -1
  215. package/dist/src/server/home.js +0 -1
  216. package/dist/src/server/homepage-config.types.d.ts +0 -274
  217. package/dist/src/server/homepage-config.types.d.ts.map +0 -1
  218. package/dist/src/server/homepage-config.types.js +0 -33
  219. package/dist/src/server/homepage-section-defaults.d.ts +0 -188
  220. package/dist/src/server/homepage-section-defaults.d.ts.map +0 -1
  221. package/dist/src/server/homepage-section-defaults.js +0 -188
  222. package/dist/src/server/index.d.ts +0 -25
  223. package/dist/src/server/index.d.ts.map +0 -1
  224. package/dist/src/server/index.js +0 -24
  225. package/dist/src/server/locale-actions.d.ts +0 -14
  226. package/dist/src/server/locale-actions.d.ts.map +0 -1
  227. package/dist/src/server/locale-actions.js +0 -58
  228. package/dist/src/server/locales.d.ts +0 -8
  229. package/dist/src/server/locales.d.ts.map +0 -1
  230. package/dist/src/server/locales.js +0 -12
  231. package/dist/src/server/normalize-homepage-config.d.ts +0 -7
  232. package/dist/src/server/normalize-homepage-config.d.ts.map +0 -1
  233. package/dist/src/server/normalize-homepage-config.js +0 -213
  234. package/dist/src/server/notifications.d.ts +0 -2
  235. package/dist/src/server/notifications.d.ts.map +0 -1
  236. package/dist/src/server/notifications.js +0 -20
  237. package/dist/src/server/onboarding.d.ts +0 -2
  238. package/dist/src/server/onboarding.d.ts.map +0 -1
  239. package/dist/src/server/onboarding.js +0 -8
  240. package/dist/src/server/orders.d.ts +0 -63
  241. package/dist/src/server/orders.d.ts.map +0 -1
  242. package/dist/src/server/orders.js +0 -230
  243. package/dist/src/server/page-input.d.ts +0 -19
  244. package/dist/src/server/page-input.d.ts.map +0 -1
  245. package/dist/src/server/page-input.js +0 -42
  246. package/dist/src/server/payment-details.d.ts +0 -5
  247. package/dist/src/server/payment-details.d.ts.map +0 -1
  248. package/dist/src/server/payment-details.js +0 -28
  249. package/dist/src/server/payment.d.ts +0 -3
  250. package/dist/src/server/payment.d.ts.map +0 -1
  251. package/dist/src/server/payment.js +0 -13
  252. package/dist/src/server/pincode.d.ts +0 -7
  253. package/dist/src/server/pincode.d.ts.map +0 -1
  254. package/dist/src/server/pincode.js +0 -30
  255. package/dist/src/server/products.d.ts +0 -54
  256. package/dist/src/server/products.d.ts.map +0 -1
  257. package/dist/src/server/products.js +0 -154
  258. package/dist/src/server/regions.d.ts +0 -5
  259. package/dist/src/server/regions.d.ts.map +0 -1
  260. package/dist/src/server/regions.js +0 -57
  261. package/dist/src/server/resolve-home-segment-data.d.ts +0 -25
  262. package/dist/src/server/resolve-home-segment-data.d.ts.map +0 -1
  263. package/dist/src/server/resolve-home-segment-data.js +0 -20
  264. package/dist/src/server/returns.d.ts +0 -29
  265. package/dist/src/server/returns.d.ts.map +0 -1
  266. package/dist/src/server/returns.js +0 -132
  267. package/dist/src/server/shoppable-looks.d.ts +0 -17
  268. package/dist/src/server/shoppable-looks.d.ts.map +0 -1
  269. package/dist/src/server/shoppable-looks.js +0 -136
  270. package/dist/src/server/swaps.d.ts +0 -15
  271. package/dist/src/server/swaps.d.ts.map +0 -1
  272. package/dist/src/server/swaps.js +0 -89
  273. package/dist/src/server/variants.d.ts +0 -3
  274. package/dist/src/server/variants.d.ts.map +0 -1
  275. package/dist/src/server/variants.js +0 -15
  276. package/dist/src/server/wishlist.d.ts +0 -11
  277. package/dist/src/server/wishlist.d.ts.map +0 -1
  278. package/dist/src/server/wishlist.js +0 -49
  279. package/dist/src/util/get-locale-header.d.ts +0 -4
  280. package/dist/src/util/get-locale-header.d.ts.map +0 -1
  281. package/dist/src/util/get-locale-header.js +0 -7
  282. package/dist/src/util/medusa-error.d.ts +0 -2
  283. package/dist/src/util/medusa-error.d.ts.map +0 -1
  284. package/dist/src/util/medusa-error.js +0 -18
  285. package/dist/src/util/revalidate-cart.d.ts +0 -2
  286. package/dist/src/util/revalidate-cart.d.ts.map +0 -1
  287. package/dist/src/util/revalidate-cart.js +0 -8
  288. package/dist/src/util/sort-products.d.ts +0 -3
  289. package/dist/src/util/sort-products.d.ts.map +0 -1
  290. package/dist/src/util/sort-products.js +0 -1
  291. package/dist/src/util/store-client.d.ts +0 -11
  292. package/dist/src/util/store-client.d.ts.map +0 -1
  293. package/dist/src/util/store-client.js +0 -75
@@ -1,6 +1,44 @@
1
1
  # Homepage config and page input
2
2
 
3
- Storefront **packages do not call** `GET /store/dynamic-config`. Segment copy uses **hardcoded JSON defaults** (`segment-data/default-page-input.json`). The **main project** fetches dynamic config once and passes optional `pageInput` overrides.
3
+ Storefront **packages do not call** `GET /store/dynamic-config`. Each homepage section in `medusa-ui-home` keeps its **default copy in `data.json`** beside the UI. The **main project** fetches dynamic config once and passes optional `pageInput` overrides.
4
+
5
+ ## `medusa-ui-home` section layout
6
+
7
+ Each section id is a folder under `src/home/sections/<id>/`:
8
+
9
+ | File | Role |
10
+ |------|------|
11
+ | `data.json` | Default segment fields for dynamic-config schema |
12
+ | `theme.ts` | Default class names for slots this section uses + `ThemeOverrides` + `mergeSectionTheme()` |
13
+ | `dynamic-config.ts` | `*HomepageSectionField`, `*DynamicConfigStructure`, section id exports |
14
+ | `component/` | Presentational UI (or `component/index.tsx` re-export for shared widgets) |
15
+ | `section.tsx` | Section React wrapper only; optional `theme` prop |
16
+ | `index.ts` | Package export (`medusa-ui-home/sections/<id>`) |
17
+
18
+ Shared widgets used by multiple sections live in `src/home/components/` (`dynamic-banner`, `shoppable-gallery`, `shared/product-grid-section`, etc.).
19
+
20
+ Cross-section slots (e.g. `section`, `sectionPad`, `cardSurface`) live in `src/home/theme/shared.ts` and are composed into `medusa-ui-home/theme` via `defaultHomeThemeClassNames`.
21
+
22
+ ### Per-section theme overrides
23
+
24
+ ```tsx
25
+ import AboutBrandSection, {
26
+ mergeSectionTheme,
27
+ type ThemeOverrides,
28
+ } from "medusa-ui-home/sections/aboutBrand"
29
+
30
+ const aboutBrandTheme: ThemeOverrides = {
31
+ bannerTitle: "text-3xl font-black text-[var(--sf-color-secondary)]",
32
+ }
33
+
34
+ // Page / section instance
35
+ <AboutBrandSection {...data} theme={aboutBrandTheme} />
36
+
37
+ // Or merge into site home theme (Medusa theme-base)
38
+ const homeTheme = mergeThemeSlots(defaultHomeThemeClassNames, {
39
+ ...mergeSectionTheme({ bannerTitle: "..." }),
40
+ })
41
+ ```
4
42
 
5
43
  ## Tree-shakeable imports (one section)
6
44
 
@@ -33,7 +71,7 @@ export default async function Page({
33
71
  | `medusa-ui-home/sections/promoAnnouncements` | `medusa-storefront-data/home/sections/promoAnnouncements` |
34
72
  | … | … (all `HomeSectionId` values) |
35
73
 
36
- Run `node scripts/generate-home-section-exports.mjs` after adding a section.
74
+ Run `node scripts/generate-home-section-exports.mjs` after adding a section (creates `sections/<id>/` export entries in `medusa-ui-home` and loader paths in `medusa-storefront-data`).
37
75
 
38
76
  ## Themed pages (tree-shakeable)
39
77
 
@@ -108,25 +146,60 @@ const pageInput = homepageConfigFromDynamicResponse(await getDynamicConfig())
108
146
 
109
147
  Pass `pageInput` only where you need CMS overrides; omit it to use package JSON defaults.
110
148
 
111
- ## Medusa backend admin schemas (`medusa-ui-home`)
149
+ ## Medusa backend admin schemas (`medusa-ui-home-config`)
112
150
 
113
- UI and dynamic-config schema live in the same section file import only what you register:
151
+ Use **`medusa-ui-home-config`** in the Medusa server (CommonJS `require` + ESM `import`). Do not import `medusa-ui-home` in `medusa-config` — that package is ESM-only (React UI).
152
+
153
+ ```js
154
+ const { homepageSectionFields } = require("medusa-ui-home-config")
155
+ const { aboutBrandHomepageSectionField } = require(
156
+ "medusa-ui-home-config/sections/aboutBrand",
157
+ )
158
+ ```
114
159
 
115
160
  ```ts
116
- import HeroSection, {
117
- heroHomepageSectionField,
118
- bannerSlide,
119
- } from "medusa-ui-home/sections/hero"
120
- import { whyChooseUsHomepageSectionField } from "medusa-ui-home/sections/whyChooseUs"
161
+ import { homepageSectionFields } from "medusa-ui-home-config"
162
+ import { heroHomepageSectionField, bannerSlide } from "medusa-ui-home-config/sections/hero"
121
163
  ```
122
164
 
123
- Compose `options.configs` in your Medusa project from each section’s `*HomepageSectionField` (and site-level structures you define locally). Merge API responses with `homepageConfigFromDynamicResponse` from `medusa-storefront-data/dynamic-config`.
165
+ Compose `options.configs` from `homepageSectionFields` or individual `*HomepageSectionField` exports. Merge API responses with `homepageConfigFromDynamicResponse` from `medusa-storefront-data/dynamic-config`.
166
+
167
+ Help page FAQs use **`helpFaqHomepageSectionField`** from `medusa-ui-home-config/sections/helpFaq` (also included in `homepageSectionFields`). Store in `homepage-config.sections.helpFaq`:
168
+
169
+ ```json
170
+ {
171
+ "sections": {
172
+ "helpFaq": {
173
+ "eyebrow": "Knowledge Base",
174
+ "title": "Frequently Asked",
175
+ "titleHighlight": "Questions",
176
+ "subtitle": "Browse FAQs by topic.",
177
+ "categories": [
178
+ {
179
+ "category": "Order & Delivery",
180
+ "icon": "🚚",
181
+ "color": "from-blue-500 to-cyan-400",
182
+ "items": [
183
+ { "question": "When will I receive my order?", "answer": "…" }
184
+ ]
185
+ }
186
+ ]
187
+ }
188
+ }
189
+ }
190
+ ```
191
+
192
+ Legacy flat `faq-array` entries are still supported and are grouped by `faq-category`.
193
+
194
+ Storefront UI still imports from `medusa-ui-home/sections/<id>`.
124
195
 
125
196
  ## API reference
126
197
 
127
198
  | Export | Use |
128
199
  |--------|-----|
129
200
  | `loadHeroSectionData`, `loadNewArrivalsSectionData`, … | **One section** catalog + copy |
201
+ | `loadHelpFaqSectionData` | Help page FAQ (`sections.helpFaq`) |
202
+ | `getHelpFaqFromPageInput(pageInput)` | FAQ categories + section header copy |
130
203
  | `getDynamicConfig()` | **Main project only** |
131
204
  | `get*FromPageInput(pageInput)` | Read CMS copy/banners without fetching |
132
205
  | `homepageConfigFromDynamicResponse(raw)` | Merge API → `pageInput` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "medusa-storefront-data",
3
- "version": "2.5.1",
3
+ "version": "2.5.3",
4
4
  "type": "module",
5
5
  "description": "Medusa storefront server data layer extracted from Next.js storefront",
6
6
  "license": "MIT",
@@ -53,120 +53,165 @@
53
53
  "import": "./src/server/index.ts",
54
54
  "default": "./src/server/index.ts"
55
55
  },
56
- "./home/sections/promoAnnouncements": {
57
- "types": "./dist/server/home-sections/promo-announcements.d.ts",
58
- "import": "./src/server/home-sections/promo-announcements.ts",
59
- "default": "./src/server/home-sections/promo-announcements.ts"
60
- },
61
- "./home/sections/hero": {
62
- "types": "./dist/server/home-sections/hero.d.ts",
63
- "import": "./src/server/home-sections/hero.ts",
64
- "default": "./src/server/home-sections/hero.ts"
65
- },
66
- "./home/sections/categoryPills": {
67
- "types": "./dist/server/home-sections/category-pills.d.ts",
68
- "import": "./src/server/home-sections/category-pills.ts",
69
- "default": "./src/server/home-sections/category-pills.ts"
70
- },
71
- "./home/sections/newArrivals": {
72
- "types": "./dist/server/home-sections/new-arrivals.d.ts",
73
- "import": "./src/server/home-sections/new-arrivals.ts",
74
- "default": "./src/server/home-sections/new-arrivals.ts"
75
- },
76
- "./home/sections/newArrivalsClassic": {
77
- "types": "./dist/server/home-sections/new-arrivals-classic.d.ts",
78
- "import": "./src/server/home-sections/new-arrivals-classic.ts",
79
- "default": "./src/server/home-sections/new-arrivals-classic.ts"
80
- },
81
- "./home/sections/promoCountdown": {
82
- "types": "./dist/server/home-sections/promo-countdown.d.ts",
83
- "import": "./src/server/home-sections/promo-countdown.ts",
84
- "default": "./src/server/home-sections/promo-countdown.ts"
85
- },
86
- "./home/sections/celebrityTrust": {
87
- "types": "./dist/server/home-sections/celebrity-trust.d.ts",
88
- "import": "./src/server/home-sections/celebrity-trust.ts",
89
- "default": "./src/server/home-sections/celebrity-trust.ts"
90
- },
91
- "./home/sections/luxeFavourites": {
92
- "types": "./dist/server/home-sections/luxe-favourites.d.ts",
93
- "import": "./src/server/home-sections/luxe-favourites.ts",
94
- "default": "./src/server/home-sections/luxe-favourites.ts"
95
- },
96
- "./home/sections/shopByCategory": {
97
- "types": "./dist/server/home-sections/shop-by-category.d.ts",
98
- "import": "./src/server/home-sections/shop-by-category.ts",
99
- "default": "./src/server/home-sections/shop-by-category.ts"
100
- },
101
- "./home/sections/baptism": {
102
- "types": "./dist/server/home-sections/baptism.d.ts",
103
- "import": "./src/server/home-sections/baptism.ts",
104
- "default": "./src/server/home-sections/baptism.ts"
105
- },
106
- "./home/sections/baptismPicks": {
107
- "types": "./dist/server/home-sections/baptism-picks.d.ts",
108
- "import": "./src/server/home-sections/baptism-picks.ts",
109
- "default": "./src/server/home-sections/baptism-picks.ts"
110
- },
111
- "./home/sections/themeDresses": {
112
- "types": "./dist/server/home-sections/theme-dresses.d.ts",
113
- "import": "./src/server/home-sections/theme-dresses.ts",
114
- "default": "./src/server/home-sections/theme-dresses.ts"
115
- },
116
- "./home/sections/brandMarquee": {
117
- "types": "./dist/server/home-sections/brand-marquee.d.ts",
118
- "import": "./src/server/home-sections/brand-marquee.ts",
119
- "default": "./src/server/home-sections/brand-marquee.ts"
120
- },
121
- "./home/sections/aboutBrand": {
122
- "types": "./dist/server/home-sections/about-brand.d.ts",
123
- "import": "./src/server/home-sections/about-brand.ts",
124
- "default": "./src/server/home-sections/about-brand.ts"
125
- },
126
- "./home/sections/testimonials": {
127
- "types": "./dist/server/home-sections/testimonials.d.ts",
128
- "import": "./src/server/home-sections/testimonials.ts",
129
- "default": "./src/server/home-sections/testimonials.ts"
130
- },
131
- "./home/sections/brandPillars": {
132
- "types": "./dist/server/home-sections/brand-pillars.d.ts",
133
- "import": "./src/server/home-sections/brand-pillars.ts",
134
- "default": "./src/server/home-sections/brand-pillars.ts"
135
- },
136
- "./home/sections/instagramPosts": {
137
- "types": "./dist/server/home-sections/instagram-posts.d.ts",
138
- "import": "./src/server/home-sections/instagram-posts.ts",
139
- "default": "./src/server/home-sections/instagram-posts.ts"
140
- },
141
- "./home/sections/features": {
142
- "types": "./dist/server/home-sections/features.d.ts",
143
- "import": "./src/server/home-sections/features.ts",
144
- "default": "./src/server/home-sections/features.ts"
145
- },
146
- "./home/sections/shopByAge": {
147
- "types": "./dist/server/home-sections/shop-by-age.d.ts",
148
- "import": "./src/server/home-sections/shop-by-age.ts",
149
- "default": "./src/server/home-sections/shop-by-age.ts"
150
- },
151
- "./home/sections/whyChooseUs": {
152
- "types": "./dist/server/home-sections/why-choose-us.d.ts",
153
- "import": "./src/server/home-sections/why-choose-us.ts",
154
- "default": "./src/server/home-sections/why-choose-us.ts"
155
- },
156
- "./home/sections/lovedByMoms": {
157
- "types": "./dist/server/home-sections/loved-by-moms.d.ts",
158
- "import": "./src/server/home-sections/loved-by-moms.ts",
159
- "default": "./src/server/home-sections/loved-by-moms.ts"
160
- },
161
- "./home/sections/videoStories": {
162
- "types": "./dist/server/home-sections/video-stories.d.ts",
163
- "import": "./src/server/home-sections/video-stories.ts",
164
- "default": "./src/server/home-sections/video-stories.ts"
165
- },
166
- "./home/sections/blogPosts": {
167
- "types": "./dist/server/home-sections/blog-posts.d.ts",
168
- "import": "./src/server/home-sections/blog-posts.ts",
169
- "default": "./src/server/home-sections/blog-posts.ts"
56
+ "./cookies": {
57
+ "types": "./dist/cookies.d.ts",
58
+ "import": "./src/cookies.ts",
59
+ "default": "./src/cookies.ts"
60
+ },
61
+ "./config": {
62
+ "types": "./dist/config.d.ts",
63
+ "import": "./src/config.ts",
64
+ "default": "./src/config.ts"
65
+ },
66
+ "./locale-header": {
67
+ "types": "./dist/util/get-locale-header.d.ts",
68
+ "import": "./src/util/get-locale-header.ts",
69
+ "default": "./src/util/get-locale-header.ts"
70
+ },
71
+ "./medusa-error": {
72
+ "types": "./dist/util/medusa-error.d.ts",
73
+ "import": "./src/util/medusa-error.ts",
74
+ "default": "./src/util/medusa-error.ts"
75
+ },
76
+ "./sort-products": {
77
+ "types": "./dist/util/sort-products.d.ts",
78
+ "import": "./src/util/sort-products.ts",
79
+ "default": "./src/util/sort-products.ts"
80
+ },
81
+ "./middleware": {
82
+ "types": "./dist/middleware.d.ts",
83
+ "import": "./src/middleware.ts",
84
+ "default": "./src/middleware.ts"
85
+ },
86
+ "./edge": {
87
+ "types": "./dist/edge.d.ts",
88
+ "import": "./src/edge.ts",
89
+ "default": "./src/edge.ts"
90
+ },
91
+ "./cart": {
92
+ "types": "./dist/server/cart.d.ts",
93
+ "import": "./src/server/cart.ts",
94
+ "default": "./src/server/cart.ts"
95
+ },
96
+ "./categories": {
97
+ "types": "./dist/server/categories.d.ts",
98
+ "import": "./src/server/categories.ts",
99
+ "default": "./src/server/categories.ts"
100
+ },
101
+ "./collections": {
102
+ "types": "./dist/server/collections.d.ts",
103
+ "import": "./src/server/collections.ts",
104
+ "default": "./src/server/collections.ts"
105
+ },
106
+ "./contact": {
107
+ "types": "./dist/server/contact.d.ts",
108
+ "import": "./src/server/contact.ts",
109
+ "default": "./src/server/contact.ts"
110
+ },
111
+ "./customer": {
112
+ "types": "./dist/server/customer.d.ts",
113
+ "import": "./src/server/customer.ts",
114
+ "default": "./src/server/customer.ts"
115
+ },
116
+ "./customer-registration": {
117
+ "types": "./dist/server/customer-registration.d.ts",
118
+ "import": "./src/server/customer-registration.ts",
119
+ "default": "./src/server/customer-registration.ts"
120
+ },
121
+ "./dynamic-config": {
122
+ "types": "./dist/server/dynamic-config.d.ts",
123
+ "import": "./src/server/dynamic-config.ts",
124
+ "default": "./src/server/dynamic-config.ts"
125
+ },
126
+ "./help/sections/helpFaq": {
127
+ "types": "./dist/server/help-sections/help-faq.d.ts",
128
+ "import": "./src/server/help-sections/help-faq.ts",
129
+ "default": "./src/server/help-sections/help-faq.ts"
130
+ },
131
+ "./fulfillment": {
132
+ "types": "./dist/server/fulfillment.d.ts",
133
+ "import": "./src/server/fulfillment.ts",
134
+ "default": "./src/server/fulfillment.ts"
135
+ },
136
+ "./guest": {
137
+ "types": "./dist/server/guest.d.ts",
138
+ "import": "./src/server/guest.ts",
139
+ "default": "./src/server/guest.ts"
140
+ },
141
+ "./home": {
142
+ "types": "./dist/server/home.d.ts",
143
+ "import": "./src/server/home.ts",
144
+ "default": "./src/server/home.ts"
145
+ },
146
+ "./locale-actions": {
147
+ "types": "./dist/server/locale-actions.d.ts",
148
+ "import": "./src/server/locale-actions.ts",
149
+ "default": "./src/server/locale-actions.ts"
150
+ },
151
+ "./locales": {
152
+ "types": "./dist/server/locales.d.ts",
153
+ "import": "./src/server/locales.ts",
154
+ "default": "./src/server/locales.ts"
155
+ },
156
+ "./notifications": {
157
+ "types": "./dist/server/notifications.d.ts",
158
+ "import": "./src/server/notifications.ts",
159
+ "default": "./src/server/notifications.ts"
160
+ },
161
+ "./onboarding": {
162
+ "types": "./dist/server/onboarding.d.ts",
163
+ "import": "./src/server/onboarding.ts",
164
+ "default": "./src/server/onboarding.ts"
165
+ },
166
+ "./orders": {
167
+ "types": "./dist/server/orders.d.ts",
168
+ "import": "./src/server/orders.ts",
169
+ "default": "./src/server/orders.ts"
170
+ },
171
+ "./payment": {
172
+ "types": "./dist/server/payment.d.ts",
173
+ "import": "./src/server/payment.ts",
174
+ "default": "./src/server/payment.ts"
175
+ },
176
+ "./payment-details": {
177
+ "types": "./dist/server/payment-details.d.ts",
178
+ "import": "./src/server/payment-details.ts",
179
+ "default": "./src/server/payment-details.ts"
180
+ },
181
+ "./pincode": {
182
+ "types": "./dist/server/pincode.d.ts",
183
+ "import": "./src/server/pincode.ts",
184
+ "default": "./src/server/pincode.ts"
185
+ },
186
+ "./products": {
187
+ "types": "./dist/server/products.d.ts",
188
+ "import": "./src/server/products.ts",
189
+ "default": "./src/server/products.ts"
190
+ },
191
+ "./regions": {
192
+ "types": "./dist/server/regions.d.ts",
193
+ "import": "./src/server/regions.ts",
194
+ "default": "./src/server/regions.ts"
195
+ },
196
+ "./returns": {
197
+ "types": "./dist/server/returns.d.ts",
198
+ "import": "./src/server/returns.ts",
199
+ "default": "./src/server/returns.ts"
200
+ },
201
+ "./swaps": {
202
+ "types": "./dist/server/swaps.d.ts",
203
+ "import": "./src/server/swaps.ts",
204
+ "default": "./src/server/swaps.ts"
205
+ },
206
+ "./variants": {
207
+ "types": "./dist/server/variants.d.ts",
208
+ "import": "./src/server/variants.ts",
209
+ "default": "./src/server/variants.ts"
210
+ },
211
+ "./wishlist": {
212
+ "types": "./dist/server/wishlist.d.ts",
213
+ "import": "./src/server/wishlist.ts",
214
+ "default": "./src/server/wishlist.ts"
170
215
  }
171
216
  },
172
217
  "main": "./dist/server/index.js",
@@ -740,7 +740,7 @@ export async function placeOrder(cartId?: string) {
740
740
  }
741
741
 
742
742
  if (cartRes?.type === "order") {
743
- const order = cartRes.order as HttpTypes.StoreOrder
743
+ const order = cartRes.order as unknown as HttpTypes.StoreOrder
744
744
  const countryCode = order.shipping_address?.country_code?.toLowerCase()
745
745
 
746
746
  const orderCacheTag = await getCacheTag("orders")
@@ -523,22 +523,100 @@ export function getSocialLinksFromPageInput(
523
523
  }
524
524
 
525
525
 
526
- export function getFaqsFromPageInput(
526
+ export type HelpFaqItem = { q: string; a: string }
527
+
528
+ export type HelpFaqCategory = {
529
+ category: string
530
+ icon?: string
531
+ color?: string
532
+ items: HelpFaqItem[]
533
+ }
534
+
535
+ export type HelpFaqSectionCopy = {
536
+ eyebrow?: string
537
+ title?: string
538
+ titleHighlight?: string
539
+ subtitle?: string
540
+ }
541
+
542
+ export type HelpFaqConfig = {
543
+ sectionCopy: HelpFaqSectionCopy
544
+ categories: HelpFaqCategory[]
545
+ }
546
+
547
+ function asConfigObject(value: unknown): Record<string, unknown> | null {
548
+ if (value && typeof value === "object" && !Array.isArray(value)) {
549
+ return value as Record<string, unknown>
550
+ }
551
+ return null
552
+ }
553
+
554
+ function asConfigArray(value: unknown): unknown[] {
555
+ return Array.isArray(value) ? value : []
556
+ }
557
+
558
+ function parseHelpFaqItems(itemsRaw: unknown): HelpFaqItem[] {
559
+ const items: HelpFaqItem[] = []
560
+ for (const item of asConfigArray(itemsRaw)) {
561
+ const faq =
562
+ asConfigObject((item as Record<string, unknown>)?.faq) ?? asConfigObject(item)
563
+ if (!faq) continue
564
+ const q = String(
565
+ faq.question ?? faq["faq-question"] ?? faq.q ?? ""
566
+ ).trim()
567
+ const a = String(faq.answer ?? faq["faq-answer"] ?? faq.a ?? "").trim()
568
+ if (q && a) items.push({ q, a })
569
+ }
570
+ return items
571
+ }
572
+
573
+ function parseHelpFaqCategoriesFromBlock(
574
+ block: Record<string, unknown>
575
+ ): HelpFaqCategory[] {
576
+ const raw = block.categories
577
+ if (!Array.isArray(raw)) return []
578
+
579
+ const categories: HelpFaqCategory[] = []
580
+ for (const row of raw) {
581
+ const cat =
582
+ asConfigObject((row as Record<string, unknown>)?.category) ??
583
+ asConfigObject(row)
584
+ if (!cat) continue
585
+ const category = String(cat.category ?? cat.name ?? "").trim()
586
+ const items = parseHelpFaqItems(cat.items)
587
+ if (!category || items.length === 0) continue
588
+ categories.push({
589
+ category,
590
+ icon: String(cat.icon ?? "❓").trim() || "❓",
591
+ color:
592
+ String(cat.color ?? "from-violet-500 to-purple-400").trim() ||
593
+ "from-violet-500 to-purple-400",
594
+ items,
595
+ })
596
+ }
597
+ return categories
598
+ }
599
+
600
+ function parseHelpFaqCategoriesFromLegacyArray(
527
601
  pageInput?: HomepageConfig | null
528
- ): Array<{ category: string; items: Array<{ q: string; a: string }> }> | null {
602
+ ): HelpFaqCategory[] {
529
603
  const config = resolvePageInput(pageInput)
530
604
  const faqsRaw = config["faq-array"] || []
531
- if (!Array.isArray(faqsRaw) || faqsRaw.length === 0) return null
605
+ if (!Array.isArray(faqsRaw) || faqsRaw.length === 0) return []
606
+
532
607
  const categoriesMap: Record<
533
608
  string,
534
- { displayCategory: string; items: Array<{ q: string; a: string }> }
609
+ { displayCategory: string; items: HelpFaqItem[] }
535
610
  > = {}
611
+
536
612
  faqsRaw.forEach((item: Record<string, unknown>) => {
537
- const faq = (item?.["faq"] || item) as Record<string, unknown>
538
- const displayCategory = String(faq?.["faq-category"] || "General Questions").trim()
613
+ const faq = (item?.faq || item) as Record<string, unknown>
614
+ const displayCategory = String(
615
+ faq?.["faq-category"] || faq?.category || "General Questions"
616
+ ).trim()
539
617
  const categoryKey = displayCategory.toLowerCase()
540
- const q = String(faq?.["faq-question"] || "").trim()
541
- const a = String(faq?.["faq-answer"] || "").trim()
618
+ const q = String(faq?.["faq-question"] || faq?.question || "").trim()
619
+ const a = String(faq?.["faq-answer"] || faq?.answer || "").trim()
542
620
  if (q && a) {
543
621
  if (!categoriesMap[categoryKey]) {
544
622
  categoriesMap[categoryKey] = { displayCategory, items: [] }
@@ -546,11 +624,53 @@ export function getFaqsFromPageInput(
546
624
  categoriesMap[categoryKey].items.push({ q, a })
547
625
  }
548
626
  })
549
- const faqs = Object.values(categoriesMap).map((catData) => ({
550
- category: catData.displayCategory,
551
- items: catData.items,
627
+
628
+ return Object.values(categoriesMap).map((cat) => ({
629
+ category: cat.displayCategory,
630
+ icon: "❓",
631
+ color: "from-violet-500 to-purple-400",
632
+ items: cat.items,
552
633
  }))
553
- return faqs.length > 0 ? faqs : null
634
+ }
635
+
636
+ function helpFaqBlockToSectionCopy(
637
+ block: Record<string, unknown>
638
+ ): HelpFaqSectionCopy {
639
+ const copy = parseSectionCopy(block)
640
+ return {
641
+ eyebrow: copy.eyebrow ?? undefined,
642
+ title: copy.title ?? copy.name ?? undefined,
643
+ titleHighlight:
644
+ typeof block.titleHighlight === "string"
645
+ ? block.titleHighlight
646
+ : undefined,
647
+ subtitle: copy.subtitle ?? copy.description ?? copy.text ?? undefined,
648
+ }
649
+ }
650
+
651
+ /**
652
+ * Help page FAQ — `sections.helpFaq` (preferred) with legacy `faq-array` fallback.
653
+ */
654
+ export function getHelpFaqFromPageInput(
655
+ pageInput?: HomepageConfig | null
656
+ ): HelpFaqConfig {
657
+ const block = getMergedSectionBlock("helpFaq", pageInput)
658
+ const sectionCopy = helpFaqBlockToSectionCopy(block)
659
+
660
+ let categories = parseHelpFaqCategoriesFromBlock(block)
661
+ if (categories.length === 0) {
662
+ categories = parseHelpFaqCategoriesFromLegacyArray(pageInput)
663
+ }
664
+
665
+ return { sectionCopy, categories }
666
+ }
667
+
668
+ /** FAQ categories for the help template (null when empty). */
669
+ export function getFaqsFromPageInput(
670
+ pageInput?: HomepageConfig | null
671
+ ): HelpFaqCategory[] | null {
672
+ const { categories } = getHelpFaqFromPageInput(pageInput)
673
+ return categories.length > 0 ? categories : null
554
674
  }
555
675
 
556
676