@akinon/projectzero 2.0.0-beta.9 → 2.0.1

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 (290) hide show
  1. package/CHANGELOG.md +191 -17
  2. package/app-template/.env.example +3 -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 +3 -0
  10. package/app-template/AGENTS.md +7 -0
  11. package/app-template/CHANGELOG.md +2065 -232
  12. package/app-template/Procfile +1 -1
  13. package/app-template/akinon.json +1 -4
  14. package/app-template/build.sh +10 -0
  15. package/app-template/docs/advanced-usage.md +111 -0
  16. package/app-template/docs/plugins.md +60 -25
  17. package/app-template/docs/sentry-usage.md +35 -0
  18. package/app-template/jest.config.ts +2 -2
  19. package/app-template/next-env.d.ts +1 -0
  20. package/app-template/{next.config.ts → next.config.mjs} +6 -7
  21. package/app-template/package.json +58 -50
  22. package/app-template/postcss.config.mjs +1 -4
  23. package/app-template/public/amex.svg +12 -0
  24. package/app-template/public/apple-pay.svg +16 -0
  25. package/app-template/public/assets/images/product-placeholder-1.jpg +0 -0
  26. package/app-template/public/assets/images/product-placeholder-2.jpg +0 -0
  27. package/app-template/public/assets/images/product-placeholder-3.jpg +0 -0
  28. package/app-template/public/assets/images/product-placeholder-4.jpg +0 -0
  29. package/app-template/public/google-pay.svg +16 -0
  30. package/app-template/public/locales/en/account.json +9 -4
  31. package/app-template/public/locales/en/auth.json +6 -7
  32. package/app-template/public/locales/en/basket.json +6 -6
  33. package/app-template/public/locales/en/blog.json +7 -0
  34. package/app-template/public/locales/en/category.json +3 -1
  35. package/app-template/public/locales/en/checkout.json +17 -4
  36. package/app-template/public/locales/en/common.json +61 -3
  37. package/app-template/public/locales/en/forgot_password.json +6 -7
  38. package/app-template/public/locales/en/product.json +84 -4
  39. package/app-template/public/locales/tr/account.json +9 -4
  40. package/app-template/public/locales/tr/auth.json +16 -17
  41. package/app-template/public/locales/tr/basket.json +4 -4
  42. package/app-template/public/locales/tr/blog.json +7 -0
  43. package/app-template/public/locales/tr/category.json +3 -1
  44. package/app-template/public/locales/tr/checkout.json +48 -36
  45. package/app-template/public/locales/tr/common.json +60 -2
  46. package/app-template/public/locales/tr/forgot_password.json +12 -13
  47. package/app-template/public/locales/tr/product.json +82 -0
  48. package/app-template/public/logo.svg +3 -27
  49. package/app-template/public/mastercard.svg +14 -0
  50. package/app-template/public/masterpass-javascript-sdk-web.min.js +1 -0
  51. package/app-template/public/promotion-banner.jpg +0 -0
  52. package/app-template/public/shop-pay.svg +12 -0
  53. package/app-template/public/visa.svg +12 -0
  54. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/[...prettyurl]/page.tsx +11 -11
  55. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/layout.tsx +4 -3
  56. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/cancellation/page.tsx +13 -10
  57. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/page.tsx +73 -51
  58. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/page.tsx +1 -1
  59. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/profile/page.tsx +2 -2
  60. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/address/stores/page.tsx +2 -2
  61. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/page.tsx +1 -1
  62. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket/page.tsx +2 -2
  63. package/app-template/src/app/[pz]/blog/[slug]/page.tsx +120 -0
  64. package/app-template/src/app/[pz]/category/[pk]/page.tsx +37 -0
  65. package/app-template/src/app/[pz]/flat-page/[pk]/page.tsx +23 -0
  66. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/forms/[pk]/generate/page.tsx +2 -3
  67. package/app-template/src/app/[pz]/group-product/[pk]/page.tsx +93 -0
  68. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/page.tsx +2 -4
  69. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/layout.tsx +6 -11
  70. package/app-template/src/app/[pz]/list/page.tsx +26 -0
  71. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/not-found.tsx +5 -7
  72. package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/page.tsx +6 -4
  73. package/app-template/src/app/[pz]/page.tsx +28 -0
  74. package/app-template/src/app/[pz]/pages/[slug]/page.tsx +19 -0
  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/{[commerce]/[locale]/[currency] → [pz]}/xml-sitemap/[node]/route.ts +8 -6
  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/cache/route.ts +1 -1
  84. package/app-template/src/app/api/form/[...id]/route.ts +1 -7
  85. package/app-template/src/app/api/image-proxy/route.ts +1 -0
  86. package/app-template/src/app/api/logout/route.ts +1 -1
  87. package/app-template/src/app/api/product-categories/route.ts +1 -0
  88. package/app-template/src/app/api/similar-product-list/route.ts +1 -0
  89. package/app-template/src/app/api/similar-products/route.ts +1 -0
  90. package/app-template/src/app/api/theme-settings/route.ts +12 -0
  91. package/app-template/src/app/api/virtual-try-on/limited-categories/route.ts +1 -0
  92. package/app-template/src/app/api/virtual-try-on/route.ts +1 -0
  93. package/app-template/src/app/api/web-vitals/route.ts +1 -1
  94. package/app-template/src/assets/fonts/pz-icon.css +211 -49
  95. package/app-template/src/assets/fonts/pz-icon.eot +0 -0
  96. package/app-template/src/assets/fonts/pz-icon.html +486 -0
  97. package/app-template/src/assets/fonts/pz-icon.scss +373 -49
  98. package/app-template/src/assets/fonts/pz-icon.svg +215 -53
  99. package/app-template/src/assets/fonts/pz-icon.ttf +0 -0
  100. package/app-template/src/assets/fonts/pz-icon.woff +0 -0
  101. package/app-template/src/assets/fonts/pz-icon.woff2 +0 -0
  102. package/app-template/src/assets/globals.scss +8 -133
  103. package/app-template/src/assets/icons/arrow-right.svg +3 -0
  104. package/app-template/src/assets/icons/cart.svg +4 -12
  105. package/app-template/src/assets/icons/check.svg +2 -18
  106. package/app-template/src/assets/icons/chevron-down.svg +2 -7
  107. package/app-template/src/assets/icons/delete.svg +3 -0
  108. package/app-template/src/assets/icons/facebook.svg +2 -8
  109. package/app-template/src/assets/icons/fav-off.svg +5 -0
  110. package/app-template/src/assets/icons/fav-on.svg +5 -0
  111. package/app-template/src/assets/icons/filter-and-sort.svg +3 -0
  112. package/app-template/src/assets/icons/heart.svg +3 -0
  113. package/app-template/src/assets/icons/instagram.svg +2 -13
  114. package/app-template/src/assets/icons/materials.svg +3 -0
  115. package/app-template/src/assets/icons/person.svg +4 -0
  116. package/app-template/src/assets/icons/pinterest.svg +5 -11
  117. package/app-template/src/assets/icons/ruler.svg +3 -0
  118. package/app-template/src/assets/icons/search.svg +8 -11
  119. package/app-template/src/assets/icons/share.svg +2 -9
  120. package/app-template/src/assets/icons/snapchat.svg +3 -0
  121. package/app-template/src/assets/icons/tiktok.svg +3 -0
  122. package/app-template/src/assets/icons/tumblr.svg +6 -0
  123. package/app-template/src/assets/icons/twitter.svg +2 -10
  124. package/app-template/src/assets/icons/vimeo.svg +3 -0
  125. package/app-template/src/assets/icons/youtube.svg +3 -0
  126. package/app-template/src/assets/icons/zoom.svg +8 -0
  127. package/app-template/src/auth.ts +3 -0
  128. package/app-template/src/components/__tests__/badge.test.tsx +2 -2
  129. package/app-template/src/components/__tests__/link.test.tsx +2 -0
  130. package/app-template/src/components/accordion.tsx +48 -23
  131. package/app-template/src/components/action-tooltip.tsx +160 -0
  132. package/app-template/src/components/button.tsx +1 -1
  133. package/app-template/src/components/carousel-core.tsx +4 -11
  134. package/app-template/src/components/checkbox.tsx +2 -1
  135. package/app-template/src/components/currency-select.tsx +150 -4
  136. package/app-template/src/components/file-input.tsx +27 -7
  137. package/app-template/src/components/generate-form-fields.tsx +49 -10
  138. package/app-template/src/components/icon.tsx +5 -6
  139. package/app-template/src/components/index.ts +4 -1
  140. package/app-template/src/components/input.tsx +11 -5
  141. package/app-template/src/components/language-select.tsx +88 -2
  142. package/app-template/src/components/modal.tsx +34 -16
  143. package/app-template/src/components/pagination.tsx +133 -20
  144. package/app-template/src/components/price.tsx +1 -1
  145. package/app-template/src/components/pwa-tags.tsx +1 -0
  146. package/app-template/src/components/quantity-input.tsx +63 -0
  147. package/app-template/src/components/quantity-selector.tsx +215 -0
  148. package/app-template/src/components/route-handler.tsx +50 -0
  149. package/app-template/src/components/select.tsx +86 -54
  150. package/app-template/src/components/shimmer.tsx +1 -1
  151. package/app-template/src/components/types/index.ts +51 -1
  152. package/app-template/src/components/widget-content.tsx +323 -0
  153. package/app-template/src/data/server/theme.ts +70 -0
  154. package/app-template/src/hooks/use-fav-button.tsx +9 -10
  155. package/app-template/src/hooks/use-product-cart.ts +80 -0
  156. package/app-template/src/hooks/use-stock-alert.ts +74 -0
  157. package/app-template/src/hooks/use-theme-settings.ts +42 -0
  158. package/app-template/src/lib/fonts.ts +149 -0
  159. package/app-template/src/plugins.js +12 -2
  160. package/app-template/src/{middleware.ts → proxy.ts} +3 -3
  161. package/app-template/src/redux/middlewares/category.ts +5 -4
  162. package/app-template/src/redux/store.ts +21 -1
  163. package/app-template/src/routes/index.ts +8 -7
  164. package/app-template/src/settings.js +6 -3
  165. package/app-template/src/types/hookform-resolvers-yup.d.ts +28 -0
  166. package/app-template/src/types/index.ts +74 -3
  167. package/app-template/src/types/next-auth.d.ts +2 -2
  168. package/app-template/src/types/widget.ts +169 -0
  169. package/app-template/src/utils/__tests__/theme-page-context.test.ts +145 -0
  170. package/app-template/src/utils/formatDate.ts +48 -0
  171. package/app-template/src/utils/styles.ts +71 -0
  172. package/app-template/src/utils/theme-page-context.ts +309 -0
  173. package/app-template/src/utils/variant-validation.ts +41 -0
  174. package/app-template/src/views/account/address-form.tsx +8 -4
  175. package/app-template/src/views/account/contact-form.tsx +148 -131
  176. package/app-template/src/views/account/content-header.tsx +4 -3
  177. package/app-template/src/views/account/faq/faq-tabs.tsx +8 -2
  178. package/app-template/src/views/account/favorite-item.tsx +1 -1
  179. package/app-template/src/views/account/order.tsx +11 -9
  180. package/app-template/src/views/account/orders/order-cancellation-item.tsx +1 -1
  181. package/app-template/src/views/account/orders/order-detail-header.tsx +1 -1
  182. package/app-template/src/views/anonymous-tracking/order-detail/index.tsx +45 -38
  183. package/app-template/src/views/basket/basket-item.tsx +6 -1
  184. package/app-template/src/views/basket/summary.tsx +16 -0
  185. package/app-template/src/views/breadcrumb.tsx +2 -2
  186. package/app-template/src/views/category/category-banner.tsx +4 -23
  187. package/app-template/src/views/category/category-info.tsx +2 -1
  188. package/app-template/src/views/category/filters/filter-item.tsx +138 -42
  189. package/app-template/src/views/category/filters/index.tsx +1 -1
  190. package/app-template/src/views/category/layout.tsx +1 -0
  191. package/app-template/src/views/checkout/auth.tsx +64 -40
  192. package/app-template/src/views/checkout/layout/header.tsx +10 -6
  193. package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +22 -6
  194. package/app-template/src/views/checkout/steps/payment/options/funds-transfer.tsx +25 -5
  195. package/app-template/src/views/checkout/steps/payment/options/loyalty.tsx +21 -2
  196. package/app-template/src/views/checkout/steps/payment/options/redirection.tsx +27 -5
  197. package/app-template/src/views/checkout/steps/payment/options/store-credit.tsx +464 -0
  198. package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +4 -4
  199. package/app-template/src/views/checkout/steps/shipping/address-box.tsx +33 -20
  200. package/app-template/src/views/checkout/steps/shipping/addresses.tsx +2 -2
  201. package/app-template/src/views/checkout/summary.tsx +12 -2
  202. package/app-template/src/views/find-in-store/index.tsx +2 -2
  203. package/app-template/src/views/guest-login/index.tsx +62 -58
  204. package/app-template/src/views/header/action-menu.tsx +1 -1
  205. package/app-template/src/views/header/band.tsx +2 -2
  206. package/app-template/src/views/header/index.tsx +1 -1
  207. package/app-template/src/views/header/mini-basket.tsx +3 -3
  208. package/app-template/src/views/header/mobile-hamburger-button.tsx +5 -8
  209. package/app-template/src/views/header/mobile-menu.tsx +18 -6
  210. package/app-template/src/views/header/navbar.tsx +1 -1
  211. package/app-template/src/views/header/pwa-back-button.tsx +1 -1
  212. package/app-template/src/views/header/search/index.tsx +13 -3
  213. package/app-template/src/views/header/search/results.tsx +1 -1
  214. package/app-template/src/views/header/user-menu.tsx +1 -3
  215. package/app-template/src/views/login/index.tsx +66 -57
  216. package/app-template/src/views/otp-login/index.tsx +11 -6
  217. package/app-template/src/views/product/index.ts +1 -0
  218. package/app-template/src/views/product/layout.tsx +26 -6
  219. package/app-template/src/views/product/price-wrapper.tsx +3 -24
  220. package/app-template/src/views/product/product-actions.tsx +165 -0
  221. package/app-template/src/views/product/product-info.tsx +76 -238
  222. package/app-template/src/views/product/product-share.tsx +58 -0
  223. package/app-template/src/views/product/product-variants.tsx +26 -0
  224. package/app-template/src/views/product/slider.tsx +22 -1
  225. package/app-template/src/views/product/variant.tsx +69 -41
  226. package/app-template/src/views/product-pointer-banner-item.tsx +1 -1
  227. package/app-template/src/views/register/index.tsx +31 -46
  228. package/app-template/src/views/sales-contract-modal/index.tsx +17 -17
  229. package/app-template/src/views/share/index.tsx +9 -6
  230. package/app-template/src/views/widgets/home-hero-slider-content.tsx +41 -39
  231. package/app-template/src/widgets/flatpages/about-us/index.tsx +78 -0
  232. package/app-template/src/widgets/flatpages/blog-list/index.tsx +129 -0
  233. package/app-template/src/widgets/footer-info.tsx +1 -1
  234. package/app-template/src/widgets/footer-menu.tsx +7 -3
  235. package/app-template/src/widgets/footer-subscription/footer-subscription-form.tsx +17 -14
  236. package/app-template/src/widgets/footer-subscription/index.tsx +1 -1
  237. package/app-template/src/widgets/home-stories-eng.tsx +43 -35
  238. package/app-template/src/widgets/index.ts +7 -0
  239. package/app-template/src/widgets/schemas/about-us.json +46 -0
  240. package/app-template/src/widgets/schemas/blog-list.json +37 -0
  241. package/app-template/src/widgets/schemas/blog.json +29 -0
  242. package/app-template/tailwind.config.js +155 -7
  243. package/app-template/tsconfig.json +29 -11
  244. package/codemods/migrate-auth-v5/index.js +339 -0
  245. package/codemods/migrate-auth-v5/transform.js +86 -0
  246. package/codemods/migrate-segments/index.js +591 -0
  247. package/codemods/update-tailwind-config/index.js +30 -0
  248. package/codemods/update-tailwind-config/transform.js +102 -0
  249. package/codemods/upgrade-to-2/index.js +549 -0
  250. package/commands/codemod.ts +0 -1
  251. package/commands/plugins.ts +111 -46
  252. package/dist/commands/codemod.js +0 -1
  253. package/dist/commands/plugins.js +104 -36
  254. package/package.json +3 -2
  255. package/app-template/src/app/[commerce]/[locale]/[currency]/category/[pk]/page.tsx +0 -22
  256. package/app-template/src/app/[commerce]/[locale]/[currency]/flat-page/[pk]/page.tsx +0 -20
  257. package/app-template/src/app/[commerce]/[locale]/[currency]/group-product/[pk]/page.tsx +0 -74
  258. package/app-template/src/app/[commerce]/[locale]/[currency]/list/page.tsx +0 -18
  259. package/app-template/src/app/[commerce]/[locale]/[currency]/page.tsx +0 -50
  260. package/app-template/src/app/[commerce]/[locale]/[currency]/product/[pk]/page.tsx +0 -84
  261. package/app-template/src/app/[commerce]/[locale]/[currency]/special-page/[pk]/page.tsx +0 -27
  262. package/app-template/src/pages/api/auth/[...nextauth].ts +0 -3
  263. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/address/page.tsx +0 -0
  264. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-email/page.tsx +0 -0
  265. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/change-password/page.tsx +0 -0
  266. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/contact/page.tsx +0 -0
  267. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/coupons/page.tsx +0 -0
  268. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/email-verification/page.tsx +0 -0
  269. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/faq/page.tsx +0 -0
  270. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/favourite-products/page.tsx +0 -0
  271. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/my-quotations/page.tsx +0 -0
  272. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/[id]/layout.tsx +0 -0
  273. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/account/orders/page.tsx +0 -0
  274. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/anonymous-tracking/page.tsx +0 -0
  275. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/auth/oauth-login/page.tsx +0 -0
  276. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/basket-b2b/page.tsx +0 -0
  277. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/category/[pk]/loading.tsx +0 -0
  278. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/client-root.tsx +0 -0
  279. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/contact-us/page.tsx +0 -0
  280. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/error.tsx +0 -0
  281. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/flat-page/[pk]/loading.tsx +0 -0
  282. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/group-product/[pk]/loading.tsx +0 -0
  283. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/landing-page/[pk]/loading.tsx +0 -0
  284. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/list/loading.tsx +0 -0
  285. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/checkout/page.tsx +0 -0
  286. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/orders/completed/[token]/layout.tsx +0 -0
  287. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/special-page/[pk]/loading.tsx +0 -0
  288. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/template.tsx +0 -0
  289. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/users/password/reset/page.tsx +0 -0
  290. /package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/xml-sitemap/route.ts +0 -0
@@ -0,0 +1,160 @@
1
+ 'use client';
2
+
3
+ import clsx from 'clsx';
4
+
5
+ interface ActionTooltipProps {
6
+ widgetData: {
7
+ attributes: Record<string, any>;
8
+ name: string;
9
+ template: string;
10
+ slug: string;
11
+ };
12
+ selectedWidget: any;
13
+ designMode: boolean;
14
+ onDelete?: () => void;
15
+ onMoveUp?: () => void;
16
+ onMoveDown?: () => void;
17
+ onCopy?: () => void;
18
+ }
19
+
20
+ export function ActionTooltip({
21
+ widgetData,
22
+ selectedWidget,
23
+ designMode,
24
+ onDelete,
25
+ onMoveUp,
26
+ onMoveDown,
27
+ onCopy
28
+ }: ActionTooltipProps) {
29
+ if (!widgetData?.attributes) {
30
+ return null;
31
+ }
32
+
33
+ const componentId = Object.keys(widgetData.attributes)[0];
34
+ const attributes = widgetData.attributes[componentId];
35
+
36
+ if (!attributes) {
37
+ return null;
38
+ }
39
+
40
+ const isRootContainer = !attributes.parentId;
41
+
42
+ if (isRootContainer) {
43
+ return null;
44
+ }
45
+
46
+ const isContainer = ['container'].includes(attributes.type);
47
+ const isCollectionItem = selectedWidget?.id?.includes('-');
48
+
49
+ const isSelected = isCollectionItem
50
+ ? selectedWidget?.id === componentId
51
+ : selectedWidget?.id?.split('-')[0] === componentId?.split('-')[0];
52
+
53
+ if (!designMode || !selectedWidget || !isSelected) {
54
+ return null;
55
+ }
56
+
57
+ return (
58
+ <section className="flex absolute justify-center right-[29px] mr-[4px] bottom-[-1px] z-[51] w-[73px] h-[21px] bg-[#292b2c] overflow-hidden gap-[9px]">
59
+ <button
60
+ className={clsx('bg-[#292b2c] text-white hover:opacity-80')}
61
+ onClick={onMoveUp}
62
+ >
63
+ <svg
64
+ width="9"
65
+ height="9"
66
+ viewBox="0 0 9 9"
67
+ xmlns="http://www.w3.org/2000/svg"
68
+ >
69
+ <path
70
+ d="M3.94 2.33 2.557 3.715a.546.546 0 0 1-.771-.772L4.1.628a.546.546 0 0 1 .771 0l2.315 2.314a.546.546 0 0 1-.772.772L5.031 2.33v5.626a.546.546 0 0 1-1.09 0V2.33z"
71
+ fill="#FFF"
72
+ fillRule="evenodd"
73
+ />
74
+ </svg>
75
+ </button>
76
+
77
+ <button
78
+ className={clsx(
79
+ 'bg-[#292b2c] text-white hover:opacity-80',
80
+ isContainer && 'disabled'
81
+ )}
82
+ onClick={onMoveDown}
83
+ >
84
+ <svg
85
+ width="9"
86
+ height="9"
87
+ viewBox="0 0 9 9"
88
+ xmlns="http://www.w3.org/2000/svg"
89
+ >
90
+ <path
91
+ d="M3.697 6.64 2.314 5.257a.546.546 0 0 0-.771.771l2.314 2.315a.546.546 0 0 0 .772 0l2.314-2.315a.546.546 0 0 0-.772-.771L4.788 6.64V1.014a.546.546 0 0 0-1.09 0V6.64z"
92
+ fill="#FFF"
93
+ fillRule="evenodd"
94
+ />
95
+ </svg>
96
+ </button>
97
+
98
+ <button
99
+ className="bg-[#292b2c] text-white hover:opacity-80"
100
+ onClick={onDelete}
101
+ >
102
+ <svg
103
+ width="8"
104
+ height="8"
105
+ viewBox="0 0 8 8"
106
+ xmlns="http://www.w3.org/2000/svg"
107
+ >
108
+ <path
109
+ d="M6.8986356,1.49777209 L5.4463047,1.49777209 L5.4463047,1.089312 C5.4463047,0.499342458 4.94696224,0 4.3569927,0 L2.9046618,0 C2.31469226,0 1.8153498,0.499342458 1.8153498,1.089312 L1.8153498,1.49777209 L0.363018903,1.49777209 C0.181509452,1.49777209 0,1.63384035 0,1.86079099 C0,2.08774162 0.181509452,2.17836871 0.363018903,2.17836871 L0.771478991,2.17836871 L0.771478991,6.9438215 C0.771478991,7.53379103 1.27082145,7.98769231 1.86079099,7.98769231 L5.4914906,7.98769231 C6.08146013,7.98769231 6.53536141,7.48834985 6.53536141,6.9438215 L6.53536141,2.17836871 L6.9438215,2.17836871 C7.12533095,2.17836871 7.3068404,2.04230044 7.3068404,1.8153498 C7.3068404,1.58839917 7.07988976,1.49777209 6.89838031,1.49777209 L6.8986356,1.49777209 Z M2.5416429,1.089312 C2.5416429,0.862361361 2.72315235,0.680851909 2.95010299,0.680851909 L4.40243389,0.680851909 C4.62938452,0.680851909 4.81089397,0.862361361 4.81089397,1.089312 L4.81089397,1.49777209 L2.5416429,1.49777209 L2.5416429,1.089312 L2.5416429,1.089312 Z M5.8093236,6.8986356 C5.8093236,7.12558623 5.62781415,7.2616545 5.4463047,7.2616545 L1.81560509,7.2616545 C1.58865445,7.2616545 1.407145,7.08014505 1.407145,6.8986356 L1.407145,2.17862399 L5.8093236,2.17862399 L5.8093236,6.8986356 Z M2.9046618,3.31312189 C2.72315235,3.31312189 2.5416429,3.44919016 2.5416429,3.67614079 L2.5416429,5.8093236 C2.5416429,5.99083305 2.67771116,6.1723425 2.9046618,6.1723425 C3.13161244,6.1723425 3.2676807,6.03627424 3.2676807,5.8093236 L3.2676807,3.63095489 C3.2676807,3.44944544 3.08617125,3.31337718 2.9046618,3.31337718 L2.9046618,3.31312189 Z M4.3569927,3.31312189 C4.17548325,3.31312189 3.9939738,3.44919016 3.9939738,3.63069961 L3.9939738,5.80906831 C3.9939738,5.99057777 4.13004206,6.17208722 4.3569927,6.17208722 C4.58394334,6.17208722 4.7200116,6.03601895 4.7200116,5.80906831 L4.7200116,3.63069961 C4.67457042,3.44919016 4.53850215,3.31312189 4.3569927,3.31312189 Z"
110
+ fill="#FFF"
111
+ fillRule="evenodd"
112
+ />
113
+ </svg>
114
+ </button>
115
+
116
+ <button
117
+ className="bg-[#292b2c] text-white hover:opacity-80"
118
+ onClick={onCopy}
119
+ >
120
+ <svg
121
+ width="8px"
122
+ height="10px"
123
+ viewBox="0 0 8 10"
124
+ version="1.1"
125
+ xmlns="http://www.w3.org/2000/svg"
126
+ >
127
+ <g
128
+ id="dynamic-widget"
129
+ stroke="none"
130
+ strokeWidth="1"
131
+ fill="none"
132
+ fillRule="evenodd"
133
+ >
134
+ <g
135
+ id="dynamic-widget---02"
136
+ transform="translate(-543, -615)"
137
+ fill="#FFFFFF"
138
+ fillRule="nonzero"
139
+ stroke="#FFFFFF"
140
+ strokeWidth="0.307692308"
141
+ >
142
+ <g id="Grou5" transform="translate(484, 610)">
143
+ <g id="Group-5" transform="translate(59.6154, 6)">
144
+ <path
145
+ d="M4.35136402,1.39920627 L0.632480235,1.39920627 C0.283491141,1.39920627 0,1.68269742 0,2.03168651 L0,7.36751977 C0,7.71650886 0.283491141,8 0.632480235,8 L4.35136402,8 C4.70035311,8 4.98384425,7.71650886 4.98384425,7.36751977 L4.98384425,2.03168651 C4.98209431,1.68269742 4.69885316,1.39920627 4.35136402,1.39920627 Z M4.53985813,7.36576982 C4.53985813,7.47051655 4.45461079,7.55576388 4.34986407,7.55576388 L0.630980282,7.55576388 C0.526233555,7.55576388 0.440986219,7.47051655 0.440986219,7.36576982 L0.440986219,2.03143652 C0.440986219,1.92668979 0.526233555,1.84144245 0.630980282,1.84144245 L4.34986407,1.84144245 C4.45461079,1.84144245 4.53985813,1.92668979 4.53985813,2.03143652 L4.53985813,7.36576982 Z"
146
+ id="Shape"
147
+ ></path>
148
+ <path
149
+ d="M5.77331958,0 L2.0544358,0 C1.7054467,0 1.42195556,0.283491141 1.42195556,0.632480235 C1.42195556,0.755226399 1.52020249,0.853723321 1.64319865,0.853723321 C1.76619481,0.853723321 1.86444174,0.755476391 1.86444174,0.632480235 C1.86444174,0.527733508 1.94968907,0.442486172 2.0544358,0.442486172 L5.77331958,0.442486172 C5.87806631,0.442486172 5.96331365,0.527733508 5.96331365,0.632480235 L5.96331365,5.96831349 C5.96331365,6.07306022 5.87806631,6.15830755 5.77331958,6.15830755 C5.65057342,6.15830755 5.5520765,6.25655448 5.5520765,6.37955064 C5.5520765,6.5025468 5.65032343,6.60079373 5.77331958,6.60079373 C6.12230868,6.60079373 6.40579982,6.31730258 6.40579982,5.96831349 L6.40579982,0.632480235 C6.40579982,0.283491141 6.12230868,0 5.77331958,0 Z"
150
+ id="Path"
151
+ ></path>
152
+ </g>
153
+ </g>
154
+ </g>
155
+ </g>
156
+ </svg>
157
+ </button>
158
+ </section>
159
+ );
160
+ }
@@ -54,7 +54,7 @@ export const Button = (props: ButtonProps) => {
54
54
  {children}
55
55
  </Link>
56
56
  ) : (
57
- <button {...rest} className={buttonClasses}>
57
+ <button data-testid="button" {...rest} className={buttonClasses}>
58
58
  {children}
59
59
  </button>
60
60
  );
@@ -1,11 +1,10 @@
1
1
  'use client';
2
2
 
3
- import { useEffect, useState } from 'react';
3
+ import { forwardRef } from 'react';
4
4
  import 'react-multi-carousel/lib/styles.css';
5
5
  import Carousel, {
6
6
  CarouselProps as BaseCarouselProps
7
7
  } from 'react-multi-carousel';
8
- import { forwardRef } from 'react';
9
8
  import { useMediaQuery } from '@akinon/next/hooks';
10
9
 
11
10
  type ContainerAspectRatioType = {
@@ -20,15 +19,9 @@ interface CarouselProps extends BaseCarouselProps {
20
19
  const CarouselCore = forwardRef<Carousel, CarouselProps>((props, ref) => {
21
20
  const { containerAspectRatio } = props;
22
21
  const matches = useMediaQuery('(min-width: 768px)');
23
- const [aspectRatio, setAspectRatio] = useState(containerAspectRatio.mobile);
24
-
25
- useEffect(() => {
26
- if (matches) {
27
- setAspectRatio(containerAspectRatio.desktop);
28
- } else {
29
- setAspectRatio(containerAspectRatio.mobile);
30
- }
31
- }, [matches, containerAspectRatio]);
22
+ const aspectRatio = matches
23
+ ? containerAspectRatio.desktop
24
+ : containerAspectRatio.mobile;
32
25
 
33
26
  return (
34
27
  <div className="w-full" style={{ aspectRatio }}>
@@ -9,6 +9,7 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
9
9
  <label className={twMerge('flex flex-col text-xs', props.className)}>
10
10
  <div className="flex items-center">
11
11
  <input
12
+ data-testid="checkbox"
12
13
  type="checkbox"
13
14
  {...rest}
14
15
  ref={ref}
@@ -18,7 +19,7 @@ const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>((props, ref) => {
18
19
  {children && <span className="ml-2">{children}</span>}
19
20
  </div>
20
21
  {error && (
21
- <span className="mt-1 text-sm text-error">{error.message}</span>
22
+ <span className="mt-1 text-sm text-error">{String(error.message)}</span>
22
23
  )}
23
24
  </label>
24
25
  );
@@ -9,6 +9,11 @@ import { Select } from './select';
9
9
 
10
10
  interface CurrencySelectProps {
11
11
  className?: string;
12
+ showIcon?: boolean;
13
+ /** Custom SVG icon content */
14
+ customIcon?: string;
15
+ /** Label format: 'full' (US Dollar), 'symbol' ($), 'code' (USD) */
16
+ labelFormat?: 'full' | 'symbol' | 'code';
12
17
  }
13
18
 
14
19
  export const CurrencySelect = (props: CurrencySelectProps) => {
@@ -17,6 +22,98 @@ export const CurrencySelect = (props: CurrencySelectProps) => {
17
22
  const { t, currency, setCurrency } = useLocalization();
18
23
  const { currencies } = settings.localization;
19
24
 
25
+ // Currency symbol map for common currencies
26
+ const currencySymbolMap: Record<string, string> = {
27
+ usd: '$',
28
+ eur: '€',
29
+ gbp: '£',
30
+ try: '₺',
31
+ jpy: '¥',
32
+ cny: '¥',
33
+ krw: '₩',
34
+ inr: '₹',
35
+ rub: '₽',
36
+ brl: 'R$',
37
+ aud: 'A$',
38
+ cad: 'C$',
39
+ chf: 'CHF',
40
+ sek: 'kr',
41
+ nok: 'kr',
42
+ dkk: 'kr',
43
+ pln: 'zł',
44
+ mxn: '$',
45
+ sgd: 'S$',
46
+ hkd: 'HK$',
47
+ nzd: 'NZ$',
48
+ zar: 'R',
49
+ aed: 'د.إ',
50
+ sar: '﷼',
51
+ thb: '฿',
52
+ myr: 'RM',
53
+ php: '₱',
54
+ idr: 'Rp',
55
+ vnd: '₫',
56
+ egp: 'E£',
57
+ ngn: '₦',
58
+ pkr: '₨',
59
+ bdt: '৳',
60
+ cop: '$',
61
+ ars: '$',
62
+ clp: '$',
63
+ pen: 'S/',
64
+ ils: '₪',
65
+ kwd: 'د.ك',
66
+ qar: '﷼',
67
+ bhd: '.د.ب',
68
+ omr: '﷼'
69
+ };
70
+
71
+ // Currency full name map for common currencies
72
+ const currencyNameMap: Record<string, string> = {
73
+ usd: 'US Dollar',
74
+ eur: 'Euro',
75
+ gbp: 'British Pound',
76
+ try: 'Turkish Lira',
77
+ jpy: 'Japanese Yen',
78
+ cny: 'Chinese Yuan',
79
+ krw: 'South Korean Won',
80
+ inr: 'Indian Rupee',
81
+ rub: 'Russian Ruble',
82
+ brl: 'Brazilian Real',
83
+ aud: 'Australian Dollar',
84
+ cad: 'Canadian Dollar',
85
+ chf: 'Swiss Franc',
86
+ sek: 'Swedish Krona',
87
+ nok: 'Norwegian Krone',
88
+ dkk: 'Danish Krone',
89
+ pln: 'Polish Zloty',
90
+ mxn: 'Mexican Peso',
91
+ sgd: 'Singapore Dollar',
92
+ hkd: 'Hong Kong Dollar',
93
+ nzd: 'New Zealand Dollar',
94
+ zar: 'South African Rand',
95
+ aed: 'UAE Dirham',
96
+ sar: 'Saudi Riyal',
97
+ thb: 'Thai Baht',
98
+ myr: 'Malaysian Ringgit',
99
+ php: 'Philippine Peso',
100
+ idr: 'Indonesian Rupiah',
101
+ vnd: 'Vietnamese Dong',
102
+ egp: 'Egyptian Pound',
103
+ ngn: 'Nigerian Naira',
104
+ pkr: 'Pakistani Rupee',
105
+ bdt: 'Bangladeshi Taka',
106
+ cop: 'Colombian Peso',
107
+ ars: 'Argentine Peso',
108
+ clp: 'Chilean Peso',
109
+ pen: 'Peruvian Sol',
110
+ ils: 'Israeli Shekel',
111
+ kwd: 'Kuwaiti Dinar',
112
+ qar: 'Qatari Riyal',
113
+ bhd: 'Bahraini Dinar',
114
+ omr: 'Omani Rial'
115
+ };
116
+
20
117
  const handleChange = async (e) => {
21
118
  setSelectedCurrency(e.currentTarget.value);
22
119
  setIsModalOpen(true);
@@ -26,16 +123,64 @@ export const CurrencySelect = (props: CurrencySelectProps) => {
26
123
  setCurrency(selectedCurrency);
27
124
  };
28
125
 
126
+ // Get currency symbol from map or use provided symbol
127
+ const getCurrencySymbol = (curr: { code: string; symbol?: string }) => {
128
+ if (curr.symbol) return curr.symbol;
129
+ return (
130
+ currencySymbolMap[curr.code.toLowerCase()] || curr.code.toUpperCase()
131
+ );
132
+ };
133
+
134
+ // Get currency full name from map or use provided label
135
+ const getCurrencyName = (curr: { code: string; label: string }) => {
136
+ const name = currencyNameMap[curr.code.toLowerCase()];
137
+ // If name exists in map, use it. Otherwise check if label looks like a full name (not just code)
138
+ if (name) return name;
139
+ // If label is different from code, assume it's a proper name
140
+ if (curr.label.toLowerCase() !== curr.code.toLowerCase()) return curr.label;
141
+ // Fallback to code uppercase
142
+ return curr.code.toUpperCase();
143
+ };
144
+
145
+ // Format label based on labelFormat prop
146
+ const formatLabel = (curr: {
147
+ code: string;
148
+ label: string;
149
+ symbol?: string;
150
+ }) => {
151
+ switch (props.labelFormat) {
152
+ case 'symbol':
153
+ // Return currency symbol ($, €, etc.)
154
+ return getCurrencySymbol(curr);
155
+ case 'code':
156
+ // Return currency code (USD, EUR, etc.)
157
+ return curr.code.toUpperCase();
158
+ case 'full':
159
+ default:
160
+ // Return full label (US Dollar, Euro, etc.)
161
+ return getCurrencyName(curr);
162
+ }
163
+ };
164
+
165
+ // Check if customIcon has actual SVG content
166
+ const hasValidCustomIcon =
167
+ props.customIcon &&
168
+ typeof props.customIcon === 'string' &&
169
+ props.customIcon.includes('<svg');
170
+
29
171
  return (
30
172
  <>
31
173
  <Select
32
174
  onChange={handleChange}
33
- options={currencies.map((currency) => ({
34
- value: currency.code,
35
- label: currency.label
175
+ options={currencies.map((curr) => ({
176
+ value: curr.code,
177
+ label: formatLabel(curr)
36
178
  }))}
37
179
  value={currency}
38
- icon="money"
180
+ icon={
181
+ props.showIcon !== false && !hasValidCustomIcon ? 'money' : undefined
182
+ }
183
+ customIcon={props.showIcon !== false ? props.customIcon : undefined}
39
184
  data-testid="currency"
40
185
  borderless
41
186
  className={props.className}
@@ -70,6 +215,7 @@ export const CurrencySelect = (props: CurrencySelectProps) => {
70
215
  onClick={confirmModalHandleClick}
71
216
  appearance="filled"
72
217
  className="font-medium px-10 py-4 h-12"
218
+ data-testid="currency-modal-confirm"
73
219
  >
74
220
  {t('common.currency_modal.continue')}
75
221
  </Button>
@@ -1,11 +1,21 @@
1
1
  import { useState } from 'react';
2
2
  import { forwardRef } from 'react';
3
3
  import { FileInputProps } from '@theme/components/types';
4
- import clsx from 'clsx';
5
4
  import { useLocalization } from '@akinon/next/hooks';
5
+ import { twMerge } from 'tailwind-merge';
6
6
 
7
7
  export const FileInput = forwardRef<HTMLInputElement, FileInputProps>(
8
- function FileInput({ className, onChange, ...props }, ref) {
8
+ function FileInput(
9
+ {
10
+ buttonClassName,
11
+ onChange,
12
+ fileClassName,
13
+ fileNameWrapperClassName,
14
+ fileInputClassName,
15
+ ...props
16
+ },
17
+ ref
18
+ ) {
9
19
  const { t } = useLocalization();
10
20
  const [fileNames, setFileNames] = useState<string[]>([]);
11
21
 
@@ -24,24 +34,34 @@ export const FileInput = forwardRef<HTMLInputElement, FileInputProps>(
24
34
  type="file"
25
35
  {...props}
26
36
  ref={ref}
27
- className="absolute inset-0 w-full h-full opacity-0 cursor-pointer"
37
+ className={twMerge(
38
+ 'absolute inset-0 w-full h-full opacity-0 cursor-pointer',
39
+ fileInputClassName
40
+ )}
28
41
  onChange={handleFileChange}
29
42
  />
30
43
  <button
31
44
  type="button"
32
- className={clsx('bg-primary text-white py-2 px-4 text-sm', className)}
45
+ className={twMerge(
46
+ 'bg-primary text-white py-2 px-4 text-sm',
47
+ buttonClassName
48
+ )}
33
49
  >
34
50
  {t('common.file_input.select_file')}
35
51
  </button>
36
- <div className="mt-1 text-gray-500">
52
+ <div
53
+ className={twMerge('mt-1 text-gray-500', fileNameWrapperClassName)}
54
+ >
37
55
  {fileNames.length > 0 ? (
38
- <ul className="list-disc pl-4 text-xs">
56
+ <ul className={twMerge('list-disc pl-4 text-xs', fileClassName)}>
39
57
  {fileNames.map((name, index) => (
40
58
  <li key={index}>{name}</li>
41
59
  ))}
42
60
  </ul>
43
61
  ) : (
44
- <span className="text-xs">{t('common.file_input.no_file')}</span>
62
+ <span className={twMerge('text-xs', fileClassName)}>
63
+ {t('common.file_input.no_file')}
64
+ </span>
45
65
  )}
46
66
  </div>
47
67
  </div>
@@ -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';