@akinon/projectzero 2.0.0-beta.2 → 2.0.0-beta.20

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 (377) hide show
  1. package/CHANGELOG.md +147 -6
  2. package/app-template/.env.example +8 -0
  3. package/app-template/.github/instructions/account.instructions.md +749 -0
  4. package/app-template/.github/instructions/checkout.instructions.md +678 -0
  5. package/app-template/.github/instructions/default.instructions.md +279 -0
  6. package/app-template/.github/instructions/edge-cases.instructions.md +73 -0
  7. package/app-template/.github/instructions/routing.instructions.md +603 -0
  8. package/app-template/.github/instructions/settings.instructions.md +338 -0
  9. package/app-template/.gitignore +5 -0
  10. package/app-template/AGENTS.md +7 -0
  11. package/app-template/CHANGELOG.md +1645 -61
  12. package/app-template/Procfile +1 -1
  13. package/app-template/README.md +6 -0
  14. package/app-template/akinon.json +1 -4
  15. package/app-template/build.sh +10 -0
  16. package/app-template/config/prebuild-tests.json +5 -0
  17. package/app-template/docs/advanced-usage.md +111 -0
  18. package/app-template/docs/plugins.md +60 -25
  19. package/app-template/docs/sentry-usage.md +35 -0
  20. package/app-template/jest.config.ts +2 -2
  21. package/app-template/next-env.d.ts +1 -0
  22. package/app-template/next.config.mjs +8 -5
  23. package/app-template/package.json +60 -50
  24. package/app-template/postcss.config.mjs +5 -0
  25. package/app-template/public/amex.svg +12 -0
  26. package/app-template/public/apple-pay.svg +16 -0
  27. package/app-template/public/assets/images/product-placeholder-1.jpg +0 -0
  28. package/app-template/public/assets/images/product-placeholder-2.jpg +0 -0
  29. package/app-template/public/assets/images/product-placeholder-3.jpg +0 -0
  30. package/app-template/public/assets/images/product-placeholder-4.jpg +0 -0
  31. package/app-template/public/google-pay.svg +16 -0
  32. package/app-template/public/locales/en/account.json +13 -4
  33. package/app-template/public/locales/en/auth.json +6 -7
  34. package/app-template/public/locales/en/basket.json +6 -6
  35. package/app-template/public/locales/en/blog.json +7 -0
  36. package/app-template/public/locales/en/category.json +3 -1
  37. package/app-template/public/locales/en/checkout.json +17 -4
  38. package/app-template/public/locales/en/common.json +71 -3
  39. package/app-template/public/locales/en/forgot_password.json +6 -7
  40. package/app-template/public/locales/en/product.json +84 -4
  41. package/app-template/public/locales/tr/account.json +13 -4
  42. package/app-template/public/locales/tr/auth.json +16 -17
  43. package/app-template/public/locales/tr/basket.json +4 -4
  44. package/app-template/public/locales/tr/blog.json +7 -0
  45. package/app-template/public/locales/tr/category.json +3 -1
  46. package/app-template/public/locales/tr/checkout.json +48 -36
  47. package/app-template/public/locales/tr/common.json +70 -2
  48. package/app-template/public/locales/tr/forgot_password.json +12 -13
  49. package/app-template/public/locales/tr/product.json +82 -0
  50. package/app-template/public/logo.svg +3 -27
  51. package/app-template/public/mastercard.svg +14 -0
  52. package/app-template/public/masterpass-javascript-sdk-web.min.js +1 -0
  53. package/app-template/public/promotion-banner.jpg +0 -0
  54. package/app-template/public/shop-pay.svg +12 -0
  55. package/app-template/public/visa.svg +12 -0
  56. package/app-template/src/__tests__/middleware-matcher.test.ts +135 -0
  57. package/app-template/src/app/[commerce]/[locale]/[currency]/blog/[slug]/page.tsx +118 -0
  58. package/app-template/src/app/[commerce]/[locale]/[currency]/pages/[slug]/page.tsx +15 -0
  59. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/[...prettyurl]/page.tsx +9 -9
  60. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/layout.tsx +2 -2
  61. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/cancellation/page.tsx +105 -13
  62. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/page.tsx +136 -52
  63. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/profile/page.tsx +2 -2
  64. package/app-template/src/app/[pz]/category/[pk]/page.tsx +27 -0
  65. package/app-template/src/app/[pz]/error.tsx +17 -0
  66. package/app-template/src/app/[pz]/flat-page/[pk]/page.tsx +23 -0
  67. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/forms/[pk]/generate/page.tsx +1 -2
  68. package/app-template/src/app/[pz]/group-product/[pk]/page.tsx +93 -0
  69. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/page.tsx +2 -4
  70. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/layout.tsx +3 -10
  71. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/list/page.tsx +2 -4
  72. package/app-template/src/app/{[commerce]/[locale]/[currency]/pz-not-found/page.tsx → [pz]/not-found.tsx} +5 -7
  73. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/checkout/page.tsx +7 -4
  74. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/page.tsx +6 -4
  75. package/app-template/src/app/[pz]/product/[pk]/page.tsx +102 -0
  76. package/app-template/src/app/[pz]/special-page/[pk]/page.tsx +35 -0
  77. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/email-set-primary/[[...id]]/page.tsx +3 -4
  78. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/registration/account-confirm-email/[[...id]]/page.tsx +3 -3
  79. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/reset/[[...id]]/page.tsx +41 -5
  80. package/app-template/src/app/[pz]/xml-sitemap/[node]/route.ts +73 -0
  81. package/app-template/src/app/api/auth/[...nextauth]/route.ts +3 -0
  82. package/app-template/src/app/api/barcode-search/route.ts +1 -0
  83. package/app-template/src/app/api/form/[...id]/route.ts +1 -7
  84. package/app-template/src/app/api/image-proxy/route.ts +1 -0
  85. package/app-template/src/app/api/product-categories/route.ts +1 -0
  86. package/app-template/src/app/api/similar-product-list/route.ts +1 -0
  87. package/app-template/src/app/api/similar-products/route.ts +1 -0
  88. package/app-template/src/app/api/theme-settings/route.ts +12 -0
  89. package/app-template/src/app/api/virtual-try-on/limited-categories/route.ts +1 -0
  90. package/app-template/src/app/api/virtual-try-on/route.ts +1 -0
  91. package/app-template/src/assets/fonts/pz-icon.css +211 -49
  92. package/app-template/src/assets/fonts/pz-icon.eot +0 -0
  93. package/app-template/src/assets/fonts/pz-icon.html +486 -0
  94. package/app-template/src/assets/fonts/pz-icon.scss +373 -49
  95. package/app-template/src/assets/fonts/pz-icon.svg +215 -53
  96. package/app-template/src/assets/fonts/pz-icon.ttf +0 -0
  97. package/app-template/src/assets/fonts/pz-icon.woff +0 -0
  98. package/app-template/src/assets/fonts/pz-icon.woff2 +0 -0
  99. package/app-template/src/assets/globals.scss +37 -34
  100. package/app-template/src/assets/icons/arrow-right.svg +3 -0
  101. package/app-template/src/assets/icons/cart.svg +4 -12
  102. package/app-template/src/assets/icons/check.svg +2 -18
  103. package/app-template/src/assets/icons/chevron-down.svg +2 -7
  104. package/app-template/src/assets/icons/delete.svg +3 -0
  105. package/app-template/src/assets/icons/facebook.svg +2 -8
  106. package/app-template/src/assets/icons/fav-off.svg +5 -0
  107. package/app-template/src/assets/icons/fav-on.svg +5 -0
  108. package/app-template/src/assets/icons/filter-and-sort.svg +3 -0
  109. package/app-template/src/assets/icons/heart.svg +3 -0
  110. package/app-template/src/assets/icons/instagram.svg +2 -13
  111. package/app-template/src/assets/icons/materials.svg +3 -0
  112. package/app-template/src/assets/icons/person.svg +4 -0
  113. package/app-template/src/assets/icons/pinterest.svg +5 -11
  114. package/app-template/src/assets/icons/ruler.svg +3 -0
  115. package/app-template/src/assets/icons/search.svg +8 -11
  116. package/app-template/src/assets/icons/share.svg +2 -9
  117. package/app-template/src/assets/icons/snapchat.svg +3 -0
  118. package/app-template/src/assets/icons/tiktok.svg +3 -0
  119. package/app-template/src/assets/icons/tumblr.svg +6 -0
  120. package/app-template/src/assets/icons/twitter.svg +2 -10
  121. package/app-template/src/assets/icons/vimeo.svg +3 -0
  122. package/app-template/src/assets/icons/youtube.svg +3 -0
  123. package/app-template/src/assets/icons/zoom.svg +8 -0
  124. package/app-template/src/auth.ts +3 -0
  125. package/app-template/src/components/__tests__/link.test.tsx +2 -0
  126. package/app-template/src/components/accordion.tsx +48 -23
  127. package/app-template/src/components/action-tooltip.tsx +160 -0
  128. package/app-template/src/components/button.tsx +50 -35
  129. package/app-template/src/components/carousel-core.tsx +4 -11
  130. package/app-template/src/components/checkbox.tsx +2 -1
  131. package/app-template/src/components/currency-select.tsx +150 -4
  132. package/app-template/src/components/file-input.tsx +64 -2
  133. package/app-template/src/components/generate-form-fields.tsx +49 -10
  134. package/app-template/src/components/icon.tsx +5 -6
  135. package/app-template/src/components/index.ts +4 -1
  136. package/app-template/src/components/input.tsx +8 -2
  137. package/app-template/src/components/language-select.tsx +88 -2
  138. package/app-template/src/components/modal.tsx +34 -16
  139. package/app-template/src/components/pagination.tsx +133 -20
  140. package/app-template/src/components/price.tsx +1 -1
  141. package/app-template/src/components/pwa-tags.tsx +1 -0
  142. package/app-template/src/components/quantity-input.tsx +63 -0
  143. package/app-template/src/components/quantity-selector.tsx +203 -0
  144. package/app-template/src/components/route-handler.tsx +50 -0
  145. package/app-template/src/components/select.tsx +86 -54
  146. package/app-template/src/components/tabs.tsx +2 -2
  147. package/app-template/src/components/types/index.ts +55 -2
  148. package/app-template/src/components/widget-content.tsx +323 -0
  149. package/app-template/src/data/server/theme.ts +70 -0
  150. package/app-template/src/hooks/use-fav-button.tsx +9 -10
  151. package/app-template/src/hooks/use-product-cart.ts +80 -0
  152. package/app-template/src/hooks/use-stock-alert.ts +74 -0
  153. package/app-template/src/hooks/use-theme-settings.ts +42 -0
  154. package/app-template/src/lib/fonts.ts +149 -0
  155. package/app-template/src/middleware.ts +1 -0
  156. package/app-template/src/plugins.js +13 -2
  157. package/app-template/src/redux/middlewares/category.ts +6 -5
  158. package/app-template/src/redux/reducers/category.ts +1 -1
  159. package/app-template/src/redux/store.ts +21 -1
  160. package/app-template/src/routes/index.ts +2 -1
  161. package/app-template/src/settings.js +5 -3
  162. package/app-template/src/types/hookform-resolvers-yup.d.ts +28 -0
  163. package/app-template/src/types/index.ts +74 -3
  164. package/app-template/src/types/next-auth.d.ts +2 -2
  165. package/app-template/src/types/widget.ts +169 -0
  166. package/app-template/src/utils/convert-facet-search-params.ts +1 -1
  167. package/app-template/src/utils/formatDate.ts +48 -0
  168. package/app-template/src/utils/styles.ts +71 -0
  169. package/app-template/src/utils/variant-validation.ts +41 -0
  170. package/app-template/src/views/account/address-form.tsx +8 -4
  171. package/app-template/src/views/account/contact-form.tsx +148 -136
  172. package/app-template/src/views/account/content-header.tsx +2 -2
  173. package/app-template/src/views/account/faq/faq-tabs.tsx +8 -2
  174. package/app-template/src/views/account/favorite-item.tsx +1 -1
  175. package/app-template/src/views/account/order.tsx +10 -8
  176. package/app-template/src/views/account/orders/order-cancellation-item.tsx +4 -3
  177. package/app-template/src/views/account/orders/order-detail-header.tsx +1 -1
  178. package/app-template/src/views/anonymous-tracking/order-detail/index.tsx +44 -37
  179. package/app-template/src/views/basket/basket-item.tsx +697 -107
  180. package/app-template/src/views/basket/basket-summary-context.tsx +560 -0
  181. package/app-template/src/views/basket/designer-context.tsx +617 -0
  182. package/app-template/src/views/basket/index.ts +2 -0
  183. package/app-template/src/views/basket/summary.tsx +497 -60
  184. package/app-template/src/views/breadcrumb/breadcrumb-client.tsx +190 -0
  185. package/app-template/src/views/breadcrumb/breadcrumb-registrar.tsx +286 -0
  186. package/app-template/src/views/breadcrumb/constants.ts +15 -0
  187. package/app-template/src/views/breadcrumb/index.tsx +127 -0
  188. package/app-template/src/views/breadcrumb.tsx +13 -38
  189. package/app-template/src/views/category/category-active-filters.tsx +1 -1
  190. package/app-template/src/views/category/category-banner.tsx +4 -23
  191. package/app-template/src/views/category/category-header.tsx +289 -60
  192. package/app-template/src/views/category/category-info.tsx +177 -27
  193. package/app-template/src/views/category/filters/filter-item.tsx +138 -42
  194. package/app-template/src/views/category/filters/index.tsx +209 -49
  195. package/app-template/src/views/category/layout.tsx +7 -4
  196. package/app-template/src/views/category/native-widget-context.tsx +257 -0
  197. package/app-template/src/views/category/product-list-registrar.tsx +665 -0
  198. package/app-template/src/views/checkout/auth.tsx +64 -40
  199. package/app-template/src/views/checkout/checkout-address-registrar.tsx +254 -0
  200. package/app-template/src/views/checkout/checkout-buttons-registrar.tsx +183 -0
  201. package/app-template/src/views/checkout/checkout-delivery-method-registrar.tsx +259 -0
  202. package/app-template/src/views/checkout/checkout-payment-options-registrar.tsx +253 -0
  203. package/app-template/src/views/checkout/checkout-summary-registrar.tsx +183 -0
  204. package/app-template/src/views/checkout/constants.ts +5 -0
  205. package/app-template/src/views/checkout/index.tsx +5 -0
  206. package/app-template/src/views/checkout/layout/header.tsx +9 -5
  207. package/app-template/src/views/checkout/steps/payment/index.tsx +5 -2
  208. package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +93 -6
  209. package/app-template/src/views/checkout/steps/payment/options/funds-transfer.tsx +25 -5
  210. package/app-template/src/views/checkout/steps/payment/options/loyalty.tsx +21 -2
  211. package/app-template/src/views/checkout/steps/payment/options/masterpass-rest.tsx +15 -0
  212. package/app-template/src/views/checkout/steps/payment/options/redirection.tsx +27 -5
  213. package/app-template/src/views/checkout/steps/payment/options/saved-card.tsx +18 -0
  214. package/app-template/src/views/checkout/steps/payment/options/store-credit.tsx +464 -0
  215. package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +171 -40
  216. package/app-template/src/views/checkout/steps/shipping/address-box.tsx +104 -29
  217. package/app-template/src/views/checkout/steps/shipping/addresses.tsx +129 -46
  218. package/app-template/src/views/checkout/steps/shipping/shipping-options.tsx +232 -27
  219. package/app-template/src/views/checkout/summary.tsx +310 -26
  220. package/app-template/src/views/find-in-store/index.tsx +2 -2
  221. package/app-template/src/views/footer/footer-app-banner-context.tsx +326 -0
  222. package/app-template/src/views/footer/footer-bottom-context.tsx +215 -0
  223. package/app-template/src/views/footer/footer-bottom-wrapper.tsx +74 -0
  224. package/app-template/src/views/footer/footer-layout-constants.ts +35 -0
  225. package/app-template/src/views/footer/footer-layout-registrar.tsx +342 -0
  226. package/app-template/src/views/footer/footer-layout-switcher.tsx +110 -0
  227. package/app-template/src/views/footer/footer-menu-context.tsx +211 -0
  228. package/app-template/src/views/footer/footer-native-widgets.tsx +60 -0
  229. package/app-template/src/views/footer/footer-social-context.tsx +254 -0
  230. package/app-template/src/views/footer/footer-subscription-context.tsx +210 -0
  231. package/app-template/src/views/footer/footer-utils.ts +43 -0
  232. package/app-template/src/views/footer/footer-value-props-context.tsx +326 -0
  233. package/app-template/src/views/footer/logo-settings.ts +183 -0
  234. package/app-template/src/views/footer/native-widget-config.ts +262 -0
  235. package/app-template/src/views/footer/subscription-settings.ts +122 -0
  236. package/app-template/src/views/footer/use-footer-logo.ts +162 -0
  237. package/app-template/src/views/footer.tsx +415 -13
  238. package/app-template/src/views/guest-login/index.tsx +62 -58
  239. package/app-template/src/views/header/action-menu.tsx +284 -49
  240. package/app-template/src/views/header/band.tsx +6 -21
  241. package/app-template/src/views/header/designer-context.tsx +261 -0
  242. package/app-template/src/views/header/header-announcement-registrar.tsx +267 -0
  243. package/app-template/src/views/header/header-client-wrapper.tsx +496 -0
  244. package/app-template/src/views/header/header-content.tsx +1026 -0
  245. package/app-template/src/views/header/header-currency-registrar.tsx +348 -0
  246. package/app-template/src/views/header/header-icons-context.tsx +262 -0
  247. package/app-template/src/views/header/header-language-registrar.tsx +348 -0
  248. package/app-template/src/views/header/header-layout-context.tsx +143 -0
  249. package/app-template/src/views/header/header-layout-registrar.tsx +658 -0
  250. package/app-template/src/views/header/header-logo-context.tsx +228 -0
  251. package/app-template/src/views/header/header-logo.tsx +118 -0
  252. package/app-template/src/views/header/header-mini-basket-context.tsx +524 -0
  253. package/app-template/src/views/header/header-search-registrar.tsx +511 -0
  254. package/app-template/src/views/header/header-text-slider-registrar.tsx +382 -0
  255. package/app-template/src/views/header/index.tsx +110 -48
  256. package/app-template/src/views/header/inline-search.tsx +262 -0
  257. package/app-template/src/views/header/mini-basket.tsx +832 -46
  258. package/app-template/src/views/header/mobile-hamburger-button.tsx +5 -8
  259. package/app-template/src/views/header/mobile-menu.tsx +12 -0
  260. package/app-template/src/views/header/navbar-menu-context.tsx +219 -0
  261. package/app-template/src/views/header/navbar.tsx +178 -111
  262. package/app-template/src/views/header/search/index.tsx +85 -24
  263. package/app-template/src/views/header/search/results.tsx +127 -65
  264. package/app-template/src/views/header/search/search-input.tsx +61 -0
  265. package/app-template/src/views/header/server-settings-parser.ts +1105 -0
  266. package/app-template/src/views/header/use-header-icons.ts +241 -0
  267. package/app-template/src/views/header/use-header-logo.ts +213 -0
  268. package/app-template/src/views/header/use-navbar-menu.ts +179 -0
  269. package/app-template/src/views/installment-options/index.tsx +1 -1
  270. package/app-template/src/views/login/index.tsx +89 -56
  271. package/app-template/src/views/otp-login/index.tsx +23 -20
  272. package/app-template/src/views/product/accordion-section.tsx +61 -0
  273. package/app-template/src/views/product/accordion-wrapper.tsx +135 -43
  274. package/app-template/src/views/product/custom-button-group.tsx +69 -0
  275. package/app-template/src/views/product/favorites-button-section.tsx +69 -0
  276. package/app-template/src/views/product/find-in-store-section.tsx +60 -0
  277. package/app-template/src/views/product/index.ts +1 -0
  278. package/app-template/src/views/product/layout.tsx +21 -6
  279. package/app-template/src/views/product/misc-buttons.tsx +339 -25
  280. package/app-template/src/views/product/price-wrapper.tsx +3 -24
  281. package/app-template/src/views/product/product-actions.tsx +294 -0
  282. package/app-template/src/views/product/product-info-section.tsx +140 -0
  283. package/app-template/src/views/product/product-info.tsx +130 -254
  284. package/app-template/src/views/product/product-share.tsx +61 -0
  285. package/app-template/src/views/product/product-variants.tsx +26 -0
  286. package/app-template/src/views/product/quantity-section.tsx +73 -0
  287. package/app-template/src/views/product/sale-tag.tsx +10 -0
  288. package/app-template/src/views/product/share-section.tsx +357 -0
  289. package/app-template/src/views/product/slider.tsx +135 -76
  290. package/app-template/src/views/product/variant.tsx +69 -41
  291. package/app-template/src/views/product/variants-section.tsx +126 -0
  292. package/app-template/src/views/product-detail/constants.ts +272 -0
  293. package/app-template/src/views/product-detail/index.ts +10 -0
  294. package/app-template/src/views/product-detail/product-detail-registrar.tsx +616 -0
  295. package/app-template/src/views/product-item/index.tsx +119 -46
  296. package/app-template/src/views/register/index.tsx +54 -44
  297. package/app-template/src/views/share/index.tsx +9 -6
  298. package/app-template/src/views/widgets/home-hero-slider-content.tsx +41 -39
  299. package/app-template/src/widgets/flatpages/about-us/index.tsx +78 -0
  300. package/app-template/src/widgets/flatpages/blog-list/index.tsx +129 -0
  301. package/app-template/src/widgets/footer-app-banner.tsx +444 -0
  302. package/app-template/src/widgets/footer-bottom.tsx +127 -0
  303. package/app-template/src/widgets/footer-menu-compact.tsx +238 -0
  304. package/app-template/src/widgets/footer-menu-two.tsx +298 -0
  305. package/app-template/src/widgets/footer-menu.tsx +6 -2
  306. package/app-template/src/widgets/footer-social-client.tsx +251 -0
  307. package/app-template/src/widgets/footer-social.tsx +47 -16
  308. package/app-template/src/widgets/footer-subscription/footer-subscription-form.tsx +17 -14
  309. package/app-template/src/widgets/footer-subscription/index.tsx +183 -17
  310. package/app-template/src/widgets/footer-value-props.tsx +201 -0
  311. package/app-template/src/widgets/home-stories-eng.tsx +42 -34
  312. package/app-template/src/widgets/index.ts +7 -0
  313. package/app-template/src/widgets/schemas/about-us.json +46 -0
  314. package/app-template/src/widgets/schemas/blog-list.json +37 -0
  315. package/app-template/src/widgets/schemas/blog.json +29 -0
  316. package/app-template/tailwind.config.js +19 -7
  317. package/app-template/tsconfig.json +29 -11
  318. package/codemods/migrate-segments/index.js +591 -0
  319. package/codemods/sentry-9/index.js +30 -0
  320. package/codemods/sentry-9/remove-sentry-configs.js +14 -0
  321. package/codemods/sentry-9/remove-sentry-dependency.js +25 -0
  322. package/codemods/sentry-9/replace-error-page.js +32 -0
  323. package/codemods/update-tailwind-config/index.js +30 -0
  324. package/codemods/update-tailwind-config/transform.js +102 -0
  325. package/commands/codemod.ts +17 -0
  326. package/commands/index.ts +3 -1
  327. package/commands/plugins.ts +115 -46
  328. package/dist/codemods/sentry-9/templates/error.js +14 -0
  329. package/dist/commands/codemod.js +15 -0
  330. package/dist/commands/index.js +3 -1
  331. package/dist/commands/plugins.js +85 -34
  332. package/package.json +3 -2
  333. package/app-template/postcss.config.js +0 -6
  334. package/app-template/sentry.client.config.ts +0 -16
  335. package/app-template/sentry.edge.config.ts +0 -3
  336. package/app-template/sentry.properties +0 -4
  337. package/app-template/sentry.server.config.ts +0 -3
  338. package/app-template/src/app/[commerce]/[locale]/[currency]/category/[pk]/page.tsx +0 -22
  339. package/app-template/src/app/[commerce]/[locale]/[currency]/error.tsx +0 -20
  340. package/app-template/src/app/[commerce]/[locale]/[currency]/flat-page/[pk]/page.tsx +0 -20
  341. package/app-template/src/app/[commerce]/[locale]/[currency]/group-product/[pk]/page.tsx +0 -74
  342. package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/loading.tsx +0 -67
  343. package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/page.tsx +0 -84
  344. package/app-template/src/app/[commerce]/[locale]/[currency]/special-page/[pk]/page.tsx +0 -27
  345. package/app-template/src/app/[commerce]/[locale]/[currency]/xml-sitemap/[node]/route.ts +0 -25
  346. package/app-template/src/pages/api/auth/[...nextauth].ts +0 -3
  347. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/address/page.tsx +0 -0
  348. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-email/page.tsx +0 -0
  349. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-password/page.tsx +0 -0
  350. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/contact/page.tsx +0 -0
  351. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/coupons/page.tsx +0 -0
  352. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/email-verification/page.tsx +0 -0
  353. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/faq/page.tsx +0 -0
  354. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/favourite-products/page.tsx +0 -0
  355. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/my-quotations/page.tsx +0 -0
  356. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/layout.tsx +0 -0
  357. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/page.tsx +0 -0
  358. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/page.tsx +0 -0
  359. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/address/stores/page.tsx +0 -0
  360. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/anonymous-tracking/page.tsx +0 -0
  361. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/oauth-login/page.tsx +0 -0
  362. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/page.tsx +0 -0
  363. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket/page.tsx +0 -0
  364. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket-b2b/page.tsx +0 -0
  365. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/category/[pk]/loading.tsx +0 -0
  366. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/client-root.tsx +0 -0
  367. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/contact-us/page.tsx +0 -0
  368. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/flat-page/[pk]/loading.tsx +0 -0
  369. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/group-product/[pk]/loading.tsx +0 -0
  370. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/loading.tsx +0 -0
  371. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/list/loading.tsx +0 -0
  372. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/layout.tsx +0 -0
  373. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/page.tsx +0 -0
  374. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/special-page/[pk]/loading.tsx +0 -0
  375. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/template.tsx +0 -0
  376. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/password/reset/page.tsx +0 -0
  377. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/xml-sitemap/route.ts +0 -0
@@ -7,6 +7,7 @@ import { useForm } from 'react-hook-form';
7
7
  import { yupResolver } from '@hookform/resolvers/yup';
8
8
  import * as yup from 'yup';
9
9
  import DynamicForm from './dynamic-form';
10
+
10
11
  import {
11
12
  AllFieldClassesType,
12
13
  FieldPropertiesType,
@@ -14,6 +15,7 @@ import {
14
15
  FormPropertiesType,
15
16
  Schema
16
17
  } from '@akinon/next/types';
18
+ import { useLocalization } from '@akinon/next/hooks';
17
19
 
18
20
  export function GenerateFormFields({
19
21
  schema,
@@ -28,8 +30,14 @@ export function GenerateFormFields({
28
30
  formProperties: FormPropertiesType;
29
31
  submitButtonText: string;
30
32
  }) {
33
+ const { t } = useLocalization();
31
34
  const [fields, setFields] = useState([]);
32
35
  const [loading, setIsLoading] = useState(true);
36
+ const [isSubmitting, setIsSubmitting] = useState(false);
37
+ const [submitStatus, setSubmitStatus] = useState<
38
+ 'idle' | 'success' | 'error'
39
+ >('idle');
40
+ const [submitMessage, setSubmitMessage] = useState('');
33
41
 
34
42
  const generateValidationSchema = () => {
35
43
  const schemaObject = {};
@@ -80,6 +88,7 @@ export function GenerateFormFields({
80
88
  const {
81
89
  handleSubmit,
82
90
  register,
91
+ reset,
83
92
  formState: { errors }
84
93
  } = useForm<FormField>({
85
94
  resolver: yupResolver(generateValidationSchema())
@@ -108,6 +117,10 @@ export function GenerateFormFields({
108
117
  }, [schema, fieldProperties]);
109
118
 
110
119
  const onSubmit = async (data) => {
120
+ setIsSubmitting(true);
121
+ setSubmitStatus('idle');
122
+ setSubmitMessage('');
123
+
111
124
  try {
112
125
  const formData = new FormData();
113
126
 
@@ -115,12 +128,25 @@ export function GenerateFormFields({
115
128
  formData.append(key, data[key]);
116
129
  });
117
130
 
118
- fetch(formProperties.actionUrl, {
131
+ const response = await fetch(formProperties.actionUrl, {
119
132
  method: 'POST',
120
133
  body: formData
121
134
  });
135
+
136
+ if (response.ok) {
137
+ setSubmitStatus('success');
138
+ setSubmitMessage(t('common.forms.success'));
139
+ reset();
140
+ } else {
141
+ setSubmitStatus('error');
142
+ setSubmitMessage(t('common.forms.error'));
143
+ }
122
144
  } catch (error) {
123
- console.error('Form submit error:', error);
145
+ console.error(t('common.forms.submit_error'), error);
146
+ setSubmitStatus('error');
147
+ setSubmitMessage(t('common.forms.error'));
148
+ } finally {
149
+ setIsSubmitting(false);
124
150
  }
125
151
  };
126
152
 
@@ -157,7 +183,7 @@ export function GenerateFormFields({
157
183
  className={twMerge(allFieldClasses?.className, field.class)}
158
184
  name={field.key}
159
185
  {...field.attributes}
160
- error={errors[field.key]}
186
+ error={errors[field.key] as any}
161
187
  {...register(field.key)}
162
188
  />
163
189
  </div>
@@ -187,7 +213,7 @@ export function GenerateFormFields({
187
213
  className={twMerge(allFieldClasses?.className, field?.class)}
188
214
  name={field.key}
189
215
  {...field.attributes}
190
- error={errors[field.key]}
216
+ error={errors[field.key] as any}
191
217
  {...register(field.key, { valueAsNumber: true })}
192
218
  />
193
219
  </div>
@@ -220,7 +246,7 @@ export function GenerateFormFields({
220
246
  />
221
247
  {errors[field.key] && (
222
248
  <span className="mt-1 text-sm text-error">
223
- {errors[field.key].message}
249
+ {String(errors[field.key].message)}
224
250
  </span>
225
251
  )}
226
252
  </div>
@@ -251,7 +277,7 @@ export function GenerateFormFields({
251
277
  className={twMerge(allFieldClasses?.className, field?.class)}
252
278
  name={field.key}
253
279
  {...field.attributes}
254
- error={errors[field.key]}
280
+ error={errors[field.key] as any}
255
281
  {...register(field.key)}
256
282
  />
257
283
  </div>
@@ -285,7 +311,7 @@ export function GenerateFormFields({
285
311
  label: choice
286
312
  }))}
287
313
  {...field.attributes}
288
- error={errors[field.key]}
314
+ error={errors[field.key] as any}
289
315
  {...register(field.key)}
290
316
  />
291
317
  </div>
@@ -316,7 +342,7 @@ export function GenerateFormFields({
316
342
  className={twMerge(allFieldClasses?.className, field?.class)}
317
343
  name={field.key}
318
344
  {...field.attributes}
319
- error={errors[field.key]}
345
+ error={errors[field.key] as any}
320
346
  {...register(field.key)}
321
347
  />
322
348
  </div>
@@ -337,9 +363,22 @@ export function GenerateFormFields({
337
363
  <LoaderSpinner />
338
364
  ) : (
339
365
  <>
366
+ {submitStatus === 'success' && (
367
+ <div className="mb-4 p-3 bg-green-100 border border-green-400 text-green-700 rounded">
368
+ {submitMessage}
369
+ </div>
370
+ )}
371
+
372
+ {submitStatus === 'error' && (
373
+ <div className="mb-4 p-3 bg-red-100 border border-red-400 text-red-700 rounded">
374
+ {submitMessage}
375
+ </div>
376
+ )}
377
+
340
378
  {fields.map((field: FormField) => generateField(field))}
341
- <Button type="submit" className="w-full">
342
- {submitButtonText}
379
+
380
+ <Button type="submit" className="w-full" disabled={isSubmitting}>
381
+ {isSubmitting ? t('common.forms.sending') : submitButtonText}
343
382
  </Button>
344
383
  </>
345
384
  )}
@@ -2,17 +2,16 @@ import { IconProps } from '@theme/components/types';
2
2
  import clsx from 'clsx';
3
3
 
4
4
  export const Icon = (props: IconProps) => {
5
- const { name, size, className, ...rest } = props;
5
+ const { name, size, className, style, ...rest } = props;
6
6
 
7
7
  return (
8
8
  <i
9
9
  className={clsx(`flex pz-icon-${name}`, className)}
10
10
  {...rest}
11
- style={
12
- size && {
13
- fontSize: `${size}px`
14
- }
15
- }
11
+ style={{
12
+ ...style,
13
+ ...(size && { fontSize: `${size}px` })
14
+ }}
16
15
  />
17
16
  );
18
17
  };
@@ -18,7 +18,8 @@ export * from './select';
18
18
  export * from './radio';
19
19
  export * from './checkbox';
20
20
  export * from './file-input';
21
-
21
+ export * from './widget-content';
22
+ export * from './action-tooltip';
22
23
  // Loaders
23
24
  export * from './loader-spinner';
24
25
  export * from './custom-loader';
@@ -39,3 +40,5 @@ export * from './skeleton-wrapper';
39
40
  // Head
40
41
  export * from './canonical-url';
41
42
  export * from './pwa-tags';
43
+ export * from './quantity-input';
44
+ export * from './quantity-selector';
@@ -48,7 +48,13 @@ export const Input = forwardRef<
48
48
  props.className
49
49
  );
50
50
 
51
- const inputProps: any = {
51
+ const inputProps: {
52
+ id?: string;
53
+ ref?: Ref<HTMLInputElement>;
54
+ className?: string;
55
+ onFocus?: () => void;
56
+ onBlur?: (event: FocusEvent<HTMLInputElement>) => void;
57
+ } = {
52
58
  id,
53
59
  ref,
54
60
  className: inputClass,
@@ -112,7 +118,7 @@ export const Input = forwardRef<
112
118
  )}
113
119
  </div>
114
120
  {error && (
115
- <span className="mt-1 text-sm text-error">{error.message}</span>
121
+ <span className="mt-1 text-sm text-error">{String(error.message)}</span>
116
122
  )}
117
123
  </div>
118
124
  );
@@ -1,30 +1,116 @@
1
1
  'use client';
2
2
 
3
3
  import { useLocalization } from '@akinon/next/hooks';
4
+ import { useEffect, useRef } from 'react';
4
5
  import { Select } from './select';
5
6
 
6
7
  interface LanguageSelectProps {
7
8
  className?: string;
9
+ showIcon?: boolean;
10
+ iconClassName?: string;
11
+ /** Custom SVG icon content */
12
+ customIcon?: string;
13
+ /** Label format: 'full' (English), 'short' (EN), 'code' (en) */
14
+ labelFormat?: 'full' | 'short' | 'code';
8
15
  }
9
16
 
10
17
  export const LanguageSelect = (props: LanguageSelectProps) => {
11
18
  const { locale, locales, setLocale } = useLocalization();
19
+ const isUpdatingFromParent = useRef(false);
20
+
21
+ useEffect(() => {
22
+ if (window.parent !== window && !isUpdatingFromParent.current) {
23
+ window.parent.postMessage(
24
+ {
25
+ type: 'LOCALE_UPDATE',
26
+ data: {
27
+ locale,
28
+ locales: locales.map((lang) => ({
29
+ value: lang.value,
30
+ label: lang.label
31
+ }))
32
+ }
33
+ },
34
+ '*'
35
+ );
36
+ }
37
+ }, [locale, locales]);
38
+
39
+ useEffect(() => {
40
+ const handleMessage = (event: MessageEvent) => {
41
+ if (event.data?.type === 'LOCALE_UPDATE') {
42
+ const { locale: newLocale } = event.data.data;
43
+
44
+ if (newLocale && newLocale !== locale) {
45
+ isUpdatingFromParent.current = true;
46
+ setLocale(newLocale);
47
+ setTimeout(() => {
48
+ isUpdatingFromParent.current = false;
49
+ }, 100);
50
+ }
51
+ }
52
+ };
53
+
54
+ window.addEventListener('message', handleMessage);
55
+ return () => window.removeEventListener('message', handleMessage);
56
+ }, [locale, setLocale]);
12
57
 
13
58
  const handleChange = async (e) => {
14
59
  const selectedLanguage = e.currentTarget.value;
15
60
 
16
61
  setLocale(selectedLanguage);
62
+
63
+ if (window.parent !== window) {
64
+ window.parent.postMessage(
65
+ {
66
+ type: 'LOCALE_UPDATE',
67
+ data: {
68
+ locale: selectedLanguage,
69
+ locales: locales.map((lang) => ({
70
+ value: lang.value,
71
+ label: lang.label
72
+ }))
73
+ }
74
+ },
75
+ '*'
76
+ );
77
+ }
78
+ };
79
+
80
+ // Format label based on labelFormat prop
81
+ const formatLabel = (lang: { value: string; label: string }) => {
82
+ switch (props.labelFormat) {
83
+ case 'short':
84
+ // Get first 2 characters uppercase (EN, TR, etc.)
85
+ return lang.value.slice(0, 2).toUpperCase();
86
+ case 'code':
87
+ // Return locale code as-is (en, tr, etc.)
88
+ return lang.value;
89
+ case 'full':
90
+ default:
91
+ // Return full label (English, Türkçe, etc.)
92
+ return lang.label;
93
+ }
17
94
  };
18
95
 
96
+ // Check if customIcon has actual SVG content
97
+ const hasValidCustomIcon =
98
+ props.customIcon &&
99
+ typeof props.customIcon === 'string' &&
100
+ props.customIcon.includes('<svg');
101
+
19
102
  return (
20
103
  <Select
21
104
  onChange={handleChange}
22
105
  options={locales.map((lang) => ({
23
106
  value: lang.value,
24
- label: lang.label
107
+ label: formatLabel(lang)
25
108
  }))}
26
109
  value={locale}
27
- icon="globe"
110
+ icon={
111
+ props.showIcon !== false && !hasValidCustomIcon ? 'globe' : undefined
112
+ }
113
+ customIcon={props.showIcon !== false ? props.customIcon : undefined}
28
114
  data-testid="language"
29
115
  borderless
30
116
  className={props.className}
@@ -4,16 +4,7 @@ import ReactPortal from './react-portal';
4
4
  import { Icon } from './icon';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { useEffect } from 'react';
7
-
8
- export interface ModalProps {
9
- portalId: string;
10
- children?: React.ReactNode;
11
- open?: boolean;
12
- setOpen?: (open: boolean) => void;
13
- title?: React.ReactNode;
14
- showCloseButton?: React.ReactNode;
15
- className?: string;
16
- }
7
+ import { ModalProps } from '@theme/types';
17
8
 
18
9
  export const Modal = (props: ModalProps) => {
19
10
  const {
@@ -23,7 +14,14 @@ export const Modal = (props: ModalProps) => {
23
14
  setOpen,
24
15
  title = '',
25
16
  showCloseButton = true,
26
- className
17
+ className,
18
+ overlayClassName,
19
+ headerWrapperClassName,
20
+ titleClassName,
21
+ closeButtonClassName,
22
+ iconName = 'close',
23
+ iconSize = 16,
24
+ iconClassName
27
25
  } = props;
28
26
 
29
27
  useEffect(() => {
@@ -38,23 +36,43 @@ export const Modal = (props: ModalProps) => {
38
36
 
39
37
  return (
40
38
  <ReactPortal wrapperId={portalId}>
41
- <div className="fixed top-0 left-0 w-screen h-screen bg-primary bg-opacity-60 z-50" />
39
+ <div
40
+ className={twMerge(
41
+ 'fixed top-0 left-0 w-screen h-screen bg-primary bg-opacity-60 z-50',
42
+ overlayClassName
43
+ )}
44
+ onClick={(e) => e.stopPropagation()}
45
+ />
42
46
  <section
43
47
  className={twMerge(
44
48
  'fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 z-50 bg-white',
45
49
  className
46
50
  )}
51
+ onClick={(e) => e.stopPropagation()}
47
52
  >
48
53
  {(showCloseButton || title) && (
49
- <div className="flex px-6 py-4 border-b border-gray-400">
50
- {title && <h3 className="text-lg font-light">{title}</h3>}
54
+ <div
55
+ className={twMerge(
56
+ 'flex px-6 py-4 border-b border-gray-400',
57
+ headerWrapperClassName
58
+ )}
59
+ >
60
+ {title && (
61
+ <h3 className={twMerge('text-lg font-light', titleClassName)}>
62
+ {title}
63
+ </h3>
64
+ )}
51
65
  {showCloseButton && (
52
66
  <button
53
67
  type="button"
54
68
  onClick={() => setOpen(false)}
55
- className="ml-auto"
69
+ className={twMerge('ml-auto', closeButtonClassName)}
56
70
  >
57
- <Icon name="close" size={16} />
71
+ <Icon
72
+ name={iconName}
73
+ size={iconSize}
74
+ className={iconClassName}
75
+ />
58
76
  </button>
59
77
  )}
60
78
  </div>
@@ -8,6 +8,14 @@ import { useLocalization } from '@akinon/next/hooks';
8
8
  import { useRouter } from '@akinon/next/hooks';
9
9
  import { useInView } from 'react-intersection-observer';
10
10
 
11
+ const parseSafeUrl = (url: string) => {
12
+ try {
13
+ return new URL(url, window.location.origin);
14
+ } catch {
15
+ return null;
16
+ }
17
+ };
18
+
11
19
  export const Pagination = (props: PaginationProps) => {
12
20
  const { t } = useLocalization();
13
21
  const router = useRouter();
@@ -26,7 +34,8 @@ export const Pagination = (props: PaginationProps) => {
26
34
  onPageChange,
27
35
  direction,
28
36
  render,
29
- isLoading
37
+ isLoading,
38
+ customStyles
30
39
  } = props;
31
40
 
32
41
  const pagination = usePagination(total, limit, currentPage, numberOfPages);
@@ -96,7 +105,11 @@ export const Pagination = (props: PaginationProps) => {
96
105
  const handleClick = (e: MouseEvent<HTMLAnchorElement>, url: string) => {
97
106
  e.preventDefault();
98
107
 
99
- const newUrl = new URL(url, window.location.origin);
108
+ const newUrl = parseSafeUrl(url);
109
+ if (!newUrl) {
110
+ return;
111
+ }
112
+
100
113
  const page = newUrl.searchParams.get('page');
101
114
 
102
115
  if (page === '1') {
@@ -117,7 +130,21 @@ export const Pagination = (props: PaginationProps) => {
117
130
  setNextPage(changingPage);
118
131
  }
119
132
 
120
- onPageChange(changingPage);
133
+ // Navigate to new page using router if onPageChange is not provided
134
+ if (onPageChange) {
135
+ onPageChange(changingPage);
136
+ } else {
137
+ const currentUrl = parseSafeUrl(window.location.href);
138
+ if (!currentUrl) {
139
+ return;
140
+ }
141
+
142
+ currentUrl.searchParams.set('page', String(changingPage));
143
+ if (changingPage === 1) {
144
+ currentUrl.searchParams.delete('page');
145
+ }
146
+ router.push(currentUrl.pathname + currentUrl.search, undefined);
147
+ }
121
148
  };
122
149
 
123
150
  useEffect(() => {
@@ -125,6 +152,7 @@ export const Pagination = (props: PaginationProps) => {
125
152
  setPrevPage(1);
126
153
  setNextPage(1);
127
154
  }
155
+ // eslint-disable-next-line react-hooks/exhaustive-deps
128
156
  }, [page]);
129
157
 
130
158
  useEffect(() => {
@@ -155,11 +183,77 @@ export const Pagination = (props: PaginationProps) => {
155
183
  return <>{render(pagination)}</>;
156
184
  }
157
185
 
186
+ // Custom styles for pagination container
187
+ const containerStyles: React.CSSProperties = {
188
+ marginTop: customStyles?.marginTop || '32px',
189
+ marginBottom: customStyles?.marginBottom || '16px',
190
+ gap: customStyles?.pageGap || '8px'
191
+ };
192
+
193
+ // Custom styles for page links (button-like)
194
+ const pageStyles: React.CSSProperties = {
195
+ fontSize: customStyles?.pageFontSize || '14px',
196
+ color: customStyles?.pageColor || '#9ca3af',
197
+ backgroundColor: customStyles?.pageBgColor || 'transparent',
198
+ paddingLeft: customStyles?.pagePaddingX || '8px',
199
+ paddingRight: customStyles?.pagePaddingX || '8px',
200
+ paddingTop: customStyles?.pagePaddingY || '4px',
201
+ paddingBottom: customStyles?.pagePaddingY || '4px',
202
+ borderRadius: customStyles?.pageBorderRadius || '0px',
203
+ borderWidth: customStyles?.pageBorderWidth || '0px',
204
+ borderStyle: 'solid',
205
+ borderColor: customStyles?.pageBorderColor || '#e5e7eb',
206
+ display: 'flex',
207
+ alignItems: 'center',
208
+ justifyContent: 'center'
209
+ };
210
+
211
+ const activePageStyles: React.CSSProperties = {
212
+ fontSize: customStyles?.pageFontSize || '14px',
213
+ color: customStyles?.pageActiveColor || '#1a1a1a',
214
+ fontWeight: customStyles?.pageActiveFontWeight || '600',
215
+ backgroundColor: customStyles?.pageActiveBgColor || 'transparent',
216
+ paddingLeft: customStyles?.pagePaddingX || '8px',
217
+ paddingRight: customStyles?.pagePaddingX || '8px',
218
+ paddingTop: customStyles?.pagePaddingY || '4px',
219
+ paddingBottom: customStyles?.pagePaddingY || '4px',
220
+ borderRadius: customStyles?.pageBorderRadius || '0px',
221
+ borderWidth: customStyles?.pageBorderWidth || '0px',
222
+ borderStyle: 'solid',
223
+ borderColor: customStyles?.pageActiveBorderColor || '#1a1a1a',
224
+ display: 'flex',
225
+ alignItems: 'center',
226
+ justifyContent: 'center'
227
+ };
228
+
229
+ const arrowStyles: React.CSSProperties = {
230
+ color: customStyles?.arrowColor || '#1a1a1a'
231
+ };
232
+
233
+ // Custom styles for more button
234
+ const buttonStyles: React.CSSProperties = {
235
+ backgroundColor: customStyles?.buttonBgColor || '#000000',
236
+ color: customStyles?.buttonTextColor || '#ffffff',
237
+ borderRadius: customStyles?.buttonBorderRadius || '4px',
238
+ paddingLeft: customStyles?.buttonPaddingX || '20px',
239
+ paddingRight: customStyles?.buttonPaddingX || '20px',
240
+ paddingTop: customStyles?.buttonPaddingY || '12px',
241
+ paddingBottom: customStyles?.buttonPaddingY || '12px'
242
+ };
243
+
158
244
  return direction === 'prev' && type !== 'list' ? (
159
245
  <>
160
- <div className="flex items-center justify-center">
246
+ <div
247
+ className="flex items-center justify-center"
248
+ style={{
249
+ marginTop: customStyles?.marginTop,
250
+ marginBottom: customStyles?.marginBottom
251
+ }}
252
+ data-section-id="pagination-section"
253
+ >
161
254
  <Button
162
255
  className={twMerge('px-5', moreButtonClassName)}
256
+ style={buttonStyles}
163
257
  onClick={() => handlePageChange()}
164
258
  >
165
259
  {isLoading ? (
@@ -173,15 +267,26 @@ export const Pagination = (props: PaginationProps) => {
173
267
  ) : (
174
268
  <>
175
269
  {type === 'more' && (
176
- <div className="flex items-center justify-center">
270
+ <div
271
+ className="flex items-center justify-center"
272
+ style={{
273
+ marginTop: customStyles?.marginTop,
274
+ marginBottom: customStyles?.marginBottom
275
+ }}
276
+ data-section-id="pagination-section"
277
+ >
177
278
  <Button
178
279
  className={twMerge(
179
- 'px-5',
180
- Number(nextPage) === Number(last)
181
- ? 'bg-gray-600 border-gray-600 pointer-events-none'
182
- : 'bg-black',
280
+ Number(nextPage) === Number(last) ? 'pointer-events-none' : '',
183
281
  moreButtonClassName
184
282
  )}
283
+ style={{
284
+ ...buttonStyles,
285
+ backgroundColor:
286
+ Number(nextPage) === Number(last)
287
+ ? '#6b7280'
288
+ : customStyles?.buttonBgColor || '#000000'
289
+ }}
185
290
  onClick={() => handlePageChange()}
186
291
  disabled={Number(nextPage) === Number(last)}
187
292
  >
@@ -209,9 +314,11 @@ export const Pagination = (props: PaginationProps) => {
209
314
  {type === 'list' && (
210
315
  <ul
211
316
  className={twMerge(
212
- 'mb-4 mt-8 flex items-center justify-center',
317
+ 'flex items-center justify-center',
213
318
  containerClassName
214
319
  )}
320
+ style={containerStyles}
321
+ data-section-id="pagination-section"
215
322
  >
216
323
  {prev && currentPage !== 1 && (
217
324
  <li>
@@ -219,9 +326,10 @@ export const Pagination = (props: PaginationProps) => {
219
326
  onClick={(e) => handleClick(e, prev)}
220
327
  href={prev}
221
328
  className={twMerge(
222
- 'flex cursor-pointer px-2 text-sm items-center',
329
+ 'flex cursor-pointer px-2 items-center',
223
330
  prevClassName
224
331
  )}
332
+ style={arrowStyles}
225
333
  >
226
334
  <span>&lt;</span>
227
335
  <span className="ms-4 hidden lg:inline-block">
@@ -238,20 +346,24 @@ export const Pagination = (props: PaginationProps) => {
238
346
  onClick={(e) => handleClick(e, item.url)}
239
347
  href={item.url}
240
348
  className={twMerge(
241
- clsx(
242
- 'cursor-pointer px-2 text-xs items-center',
243
- { 'pointer-events-none': item.url === null },
244
- Number(page) === Number(item?.page)
245
- ? 'font-semibold text-black-800'
246
- : 'text-gray-400'
247
- ),
349
+ clsx('cursor-pointer px-2 items-center', {
350
+ 'pointer-events-none': item.url === null
351
+ }),
248
352
  pageClassName
249
353
  )}
354
+ style={
355
+ Number(page) === Number(item?.page)
356
+ ? activePageStyles
357
+ : pageStyles
358
+ }
250
359
  >
251
360
  {item?.page}
252
361
  </Link>
253
362
  ) : (
254
- <span className="flex cursor-default items-center justify-center text-xs">
363
+ <span
364
+ className="flex cursor-default items-center justify-center"
365
+ style={pageStyles}
366
+ >
255
367
  {item?.page}
256
368
  </span>
257
369
  )}
@@ -264,9 +376,10 @@ export const Pagination = (props: PaginationProps) => {
264
376
  onClick={(e) => handleClick(e, next)}
265
377
  href={next}
266
378
  className={twMerge(
267
- 'flex cursor-pointer px-2 text-xs items-center',
379
+ 'flex cursor-pointer px-2 items-center',
268
380
  nextClassName
269
381
  )}
382
+ style={arrowStyles}
270
383
  >
271
384
  <span className="me-4 hidden lg:inline-block">
272
385
  {t('category.pagination.next')}
@@ -56,7 +56,7 @@ export const Price = (props: NumericFormatProps & PriceProps) => {
56
56
 
57
57
  const currentCurrencyDecimalScale = Settings.localization.currencies.find(
58
58
  (currency) => currency.code === currencyCode_
59
- ).decimalScale;
59
+ )?.decimalScale;
60
60
 
61
61
  return (
62
62
  <NumericFormat
@@ -2,6 +2,7 @@ import { Metadata } from '@akinon/next/types';
2
2
 
3
3
  const pwaTags: Metadata = {
4
4
  manifest: '/manifest.json',
5
+ themeColor: '#FFFFFF',
5
6
  formatDetection: {
6
7
  telephone: false
7
8
  },