@greatapps/common 1.1.700 → 1.1.701

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 (561) hide show
  1. package/dist/components/account/ConfigurationsMyAccountModal.mjs +1 -1
  2. package/dist/components/account/ConfigurationsMyAccountModal.mjs.map +1 -1
  3. package/dist/components/account/ConfirmDeleteAccountModal.mjs.map +1 -1
  4. package/dist/components/account/ConfirmGlobalPreferencesModal.mjs.map +1 -1
  5. package/dist/components/account/DeleteAccountModal.mjs.map +1 -1
  6. package/dist/components/account/DisableTwoFactorAuthModal.mjs.map +1 -1
  7. package/dist/components/account/IsntPossibleDeleteAccountModal.mjs.map +1 -1
  8. package/dist/components/account/TwoFactorAuthModal.mjs.map +1 -1
  9. package/dist/components/account/hooks/useChangePhoneForm.mjs.map +1 -1
  10. package/dist/components/account/hooks/useTwoFactorAuthForm.mjs.map +1 -1
  11. package/dist/components/account/sections/ChangeEmailModal.mjs.map +1 -1
  12. package/dist/components/account/sections/ChangePasswordSection.mjs.map +1 -1
  13. package/dist/components/account/sections/ChangePhoneModal.mjs.map +1 -1
  14. package/dist/components/account/sections/MyProfileSection.mjs.map +1 -1
  15. package/dist/components/account/sections/PreferencesSection.mjs.map +1 -1
  16. package/dist/components/account/sections/SecuritySection.mjs.map +1 -1
  17. package/dist/components/account/sections/TokenSection.mjs.map +1 -1
  18. package/dist/components/embeds/ClarityEmbed.mjs.map +1 -1
  19. package/dist/components/embeds/CrispEmbed.mjs.map +1 -1
  20. package/dist/components/embeds/EmbedWidgets.mjs.map +1 -1
  21. package/dist/components/embeds/FrillEmbed.mjs.map +1 -1
  22. package/dist/components/layouts/AppMobileNavBar.mjs.map +1 -1
  23. package/dist/components/layouts/AppNavBar.mjs.map +1 -1
  24. package/dist/components/layouts/MdSideBarNavigation.mjs.map +1 -1
  25. package/dist/components/layouts/NavBar.mjs.map +1 -1
  26. package/dist/components/layouts/NotificationsPopover.mjs.map +1 -1
  27. package/dist/components/layouts/ProfilePopover.mjs.map +1 -1
  28. package/dist/components/layouts/SideBarNavigation.mjs.map +1 -1
  29. package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
  30. package/dist/components/layouts/WhitelabelCodes.mjs.map +1 -1
  31. package/dist/components/modals/BuyCreditsModal.mjs.map +1 -1
  32. package/dist/components/modals/CreditsDisabledModal.mjs.map +1 -1
  33. package/dist/components/modals/HexaPromoModal.mjs +2 -2
  34. package/dist/components/modals/HexaPromoModal.mjs.map +1 -1
  35. package/dist/components/modals/HexaPromoModalGate.mjs.map +1 -1
  36. package/dist/components/modals/Modals.mjs.map +1 -1
  37. package/dist/components/modals/PaidPlanRequiredModal.mjs.map +1 -1
  38. package/dist/components/modals/cards/AddCardModal.mjs.map +1 -1
  39. package/dist/components/modals/cards/CannotDeleteCardModal.mjs.map +1 -1
  40. package/dist/components/modals/cards/CardFormFields.mjs.map +1 -1
  41. package/dist/components/modals/cards/DeleteCardModal.mjs.map +1 -1
  42. package/dist/components/navigation/CancelledSubscriptionBanner.mjs.map +1 -1
  43. package/dist/components/navigation/NavItemsContext.mjs.map +1 -1
  44. package/dist/components/navigation/OverdueInvoiceBanner.mjs.map +1 -1
  45. package/dist/components/navigation/PendingCancellationBanner.mjs.map +1 -1
  46. package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
  47. package/dist/components/navigation/SubscriptionBanner.mjs.map +1 -1
  48. package/dist/components/navigation/TrialBanner.mjs.map +1 -1
  49. package/dist/components/navigation/UpcomingInvoiceBanner.mjs.map +1 -1
  50. package/dist/components/navigation/shells/TabsMobileShell.mjs.map +1 -1
  51. package/dist/components/navigation/subcomponents/BottomLinks.mjs.map +1 -1
  52. package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
  53. package/dist/components/pages/NotFoundPage.mjs.map +1 -1
  54. package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
  55. package/dist/components/ui/buttons/Button.mjs.map +1 -1
  56. package/dist/components/ui/buttons/CancelButton.mjs.map +1 -1
  57. package/dist/components/ui/buttons/CopyButton.mjs.map +1 -1
  58. package/dist/components/ui/data-display/Accordion.mjs.map +1 -1
  59. package/dist/components/ui/data-display/Badge.mjs.map +1 -1
  60. package/dist/components/ui/data-display/Card.mjs.map +1 -1
  61. package/dist/components/ui/data-display/CardBrandIcons.mjs.map +1 -1
  62. package/dist/components/ui/data-display/CardItem.mjs.map +1 -1
  63. package/dist/components/ui/data-display/Pagination.mjs.map +1 -1
  64. package/dist/components/ui/data-display/PaymentInfoCard.mjs.map +1 -1
  65. package/dist/components/ui/data-display/ScrollArea.mjs.map +1 -1
  66. package/dist/components/ui/data-display/Separator.mjs.map +1 -1
  67. package/dist/components/ui/data-display/Table.mjs.map +1 -1
  68. package/dist/components/ui/data-display/Tabs.mjs.map +1 -1
  69. package/dist/components/ui/feedback/CircularProgress.mjs.map +1 -1
  70. package/dist/components/ui/feedback/DefaultCircularProgress.mjs.map +1 -1
  71. package/dist/components/ui/feedback/LoadingOverlay.mjs.map +1 -1
  72. package/dist/components/ui/feedback/Progress.mjs.map +1 -1
  73. package/dist/components/ui/feedback/Skeleton.mjs.map +1 -1
  74. package/dist/components/ui/feedback/Toast.mjs.map +1 -1
  75. package/dist/components/ui/form/Calendar.mjs.map +1 -1
  76. package/dist/components/ui/form/Checkbox.mjs.map +1 -1
  77. package/dist/components/ui/form/ComboboxField.mjs.map +1 -1
  78. package/dist/components/ui/form/DatePicker.mjs.map +1 -1
  79. package/dist/components/ui/form/DateRangePicker.mjs.map +1 -1
  80. package/dist/components/ui/form/FormField.mjs.map +1 -1
  81. package/dist/components/ui/form/Input.mjs.map +1 -1
  82. package/dist/components/ui/form/InputOtp.mjs.map +1 -1
  83. package/dist/components/ui/form/PhoneInput.mjs.map +1 -1
  84. package/dist/components/ui/form/RadioGroup.mjs.map +1 -1
  85. package/dist/components/ui/form/Select.mjs +1 -1
  86. package/dist/components/ui/form/Select.mjs.map +1 -1
  87. package/dist/components/ui/form/Switch.mjs.map +1 -1
  88. package/dist/components/ui/form/Textarea.mjs.map +1 -1
  89. package/dist/components/ui/overlay/Command.mjs.map +1 -1
  90. package/dist/components/ui/overlay/Dialog.mjs.map +1 -1
  91. package/dist/components/ui/overlay/Popover.mjs.map +1 -1
  92. package/dist/components/ui/overlay/Sheet.mjs.map +1 -1
  93. package/dist/components/ui/overlay/Tooltip.mjs.map +1 -1
  94. package/dist/components/widgets/ImageUpload/ImageCropModal.mjs.map +1 -1
  95. package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs.map +1 -1
  96. package/dist/components/widgets/ImageUpload/ImageUpload.mjs.map +1 -1
  97. package/dist/components/widgets/ImageUpload/index.mjs.map +1 -1
  98. package/dist/components/widgets/notifications/NotificationCard.mjs.map +1 -1
  99. package/dist/handlers.mjs.map +1 -1
  100. package/dist/hooks/copy-to-clipboard.hook.mjs.map +1 -1
  101. package/dist/hooks/useAuthQueryKey.mjs.map +1 -1
  102. package/dist/hooks/useBrandLoadingIcon.mjs.map +1 -1
  103. package/dist/hooks/useRouter.mjs.map +1 -1
  104. package/dist/http.mjs.map +1 -1
  105. package/dist/i18n/config.mjs.map +1 -1
  106. package/dist/i18n/country-language.mjs.map +1 -1
  107. package/dist/i18n/messages/en-us.mjs.map +1 -1
  108. package/dist/i18n/messages/es-es.mjs.map +1 -1
  109. package/dist/i18n/messages/index.mjs.map +1 -1
  110. package/dist/i18n/messages/pt-br.mjs.map +1 -1
  111. package/dist/i18n/normalize.mjs.map +1 -1
  112. package/dist/i18n/resolve-locale.mjs.map +1 -1
  113. package/dist/i18n.mjs.map +1 -1
  114. package/dist/index.mjs.map +1 -1
  115. package/dist/infra/http/api-fetch.mjs.map +1 -1
  116. package/dist/infra/route/parse-id.mjs.map +1 -1
  117. package/dist/infra/route/parse-numeric.mjs.map +1 -1
  118. package/dist/infra/route/safe-route-handler.mjs.map +1 -1
  119. package/dist/infra/route/search-params.mjs.map +1 -1
  120. package/dist/infra/utils/array.mjs.map +1 -1
  121. package/dist/infra/utils/date.mjs.map +1 -1
  122. package/dist/middleware.mjs.map +1 -1
  123. package/dist/modules/accounts/actions/account-management.action.mjs.map +1 -1
  124. package/dist/modules/accounts/actions/find-current-account.action.mjs.map +1 -1
  125. package/dist/modules/accounts/actions/get-account-token.action.mjs.map +1 -1
  126. package/dist/modules/accounts/actions/list-currencies.action.mjs.map +1 -1
  127. package/dist/modules/accounts/actions/list-timezones.action.mjs.map +1 -1
  128. package/dist/modules/accounts/hooks/current-account.hook.mjs.map +1 -1
  129. package/dist/modules/accounts/hooks/use-account-token.hook.mjs.map +1 -1
  130. package/dist/modules/accounts/hooks/use-currency-formatter.hook.mjs.map +1 -1
  131. package/dist/modules/accounts/hooks/useAccountManagement.mjs.map +1 -1
  132. package/dist/modules/accounts/hooks/useCurrencies.mjs.map +1 -1
  133. package/dist/modules/accounts/hooks/useTimezones.mjs.map +1 -1
  134. package/dist/modules/accounts/hooks/useViaCep.mjs.map +1 -1
  135. package/dist/modules/accounts/services/account-token.service.mjs.map +1 -1
  136. package/dist/modules/accounts/services/account.service.mjs.map +1 -1
  137. package/dist/modules/auth/actions/social-google-login.action.mjs.map +1 -1
  138. package/dist/modules/auth/actions/social-google-onboarding.action.mjs.map +1 -1
  139. package/dist/modules/auth/actions/unlink-google.action.mjs.map +1 -1
  140. package/dist/modules/auth/actions/validate-session.action.mjs.map +1 -1
  141. package/dist/modules/auth/actions/verify-two-factor.action.mjs.map +1 -1
  142. package/dist/modules/auth/hooks/login.hook.mjs.map +1 -1
  143. package/dist/modules/auth/hooks/logout.hook.mjs.map +1 -1
  144. package/dist/modules/auth/hooks/register.hook.mjs.map +1 -1
  145. package/dist/modules/auth/hooks/social-google-login.hook.mjs.map +1 -1
  146. package/dist/modules/auth/hooks/social-google-onboarding.hook.mjs.map +1 -1
  147. package/dist/modules/auth/hooks/unlink-google.hook.mjs.map +1 -1
  148. package/dist/modules/auth/hooks/useManagementPermissions.mjs.map +1 -1
  149. package/dist/modules/auth/hooks/useUserQuery.mjs.map +1 -1
  150. package/dist/modules/auth/utils/assert-management-permission.mjs.map +1 -1
  151. package/dist/modules/auth/utils/assert-management-subscription.mjs.map +1 -1
  152. package/dist/modules/auth/utils/assert-paid-subscription.mjs.map +1 -1
  153. package/dist/modules/auth/utils/assert-subscription-addon.mjs.map +1 -1
  154. package/dist/modules/auth/utils/build-wl-override.mjs.map +1 -1
  155. package/dist/modules/auth/utils/require-token-not-expired.mjs.map +1 -1
  156. package/dist/modules/auth/utils/require-valid-session.mjs.map +1 -1
  157. package/dist/modules/cards/actions/create-card.action.mjs.map +1 -1
  158. package/dist/modules/cards/actions/create-setup-intent.action.mjs.map +1 -1
  159. package/dist/modules/cards/actions/delete-card.action.mjs.map +1 -1
  160. package/dist/modules/cards/actions/set-default-card.action.mjs.map +1 -1
  161. package/dist/modules/cards/handlers/find-card-by-id.handler.mjs.map +1 -1
  162. package/dist/modules/cards/handlers/list-cards.handler.mjs.map +1 -1
  163. package/dist/modules/cards/hooks/card-by-id.hook.mjs.map +1 -1
  164. package/dist/modules/cards/hooks/cards.hook.mjs.map +1 -1
  165. package/dist/modules/cards/hooks/create-card.hook.mjs.map +1 -1
  166. package/dist/modules/cards/hooks/create-setup-intent.hook.mjs.map +1 -1
  167. package/dist/modules/cards/hooks/delete-card.hook.mjs.map +1 -1
  168. package/dist/modules/cards/hooks/delete-confirmation.hook.mjs.map +1 -1
  169. package/dist/modules/cards/hooks/handle-delete-card.hook.mjs.map +1 -1
  170. package/dist/modules/cards/hooks/set-default-card.hook.mjs.map +1 -1
  171. package/dist/modules/cards/services/cards.service.mjs.map +1 -1
  172. package/dist/modules/cards/types.mjs.map +1 -1
  173. package/dist/modules/charges/actions/charge-action.action.mjs.map +1 -1
  174. package/dist/modules/charges/handlers/find-charge-by-id.handler.mjs.map +1 -1
  175. package/dist/modules/charges/handlers/list-charges.handler.mjs.map +1 -1
  176. package/dist/modules/charges/hooks/charge-action.hook.mjs.map +1 -1
  177. package/dist/modules/charges/hooks/charge-by-id.hook.mjs.map +1 -1
  178. package/dist/modules/charges/hooks/charges.hook.mjs.map +1 -1
  179. package/dist/modules/charges/services/charges.service.mjs.map +1 -1
  180. package/dist/modules/charges/types/charge.type.mjs.map +1 -1
  181. package/dist/modules/ia-credits/handlers/list-ia-credits.handler.mjs.map +1 -1
  182. package/dist/modules/ia-credits/hooks/ia-credits.hook.mjs.map +1 -1
  183. package/dist/modules/images/actions/process-image.action.mjs.map +1 -1
  184. package/dist/modules/images/constants/image.constants.mjs.map +1 -1
  185. package/dist/modules/images/hooks/use-image-upload.hook.mjs.map +1 -1
  186. package/dist/modules/images/services/image-processing.service.mjs.map +1 -1
  187. package/dist/modules/images/utils/base64.mjs.map +1 -1
  188. package/dist/modules/images/utils/compress-image.mjs.map +1 -1
  189. package/dist/modules/images/utils/crop-image.mjs.map +1 -1
  190. package/dist/modules/images/utils/validate-image.mjs.map +1 -1
  191. package/dist/modules/pages/constants/query-keys.constants.mjs.map +1 -1
  192. package/dist/modules/pages/handlers/count-pages.handler.mjs.map +1 -1
  193. package/dist/modules/pages/hooks/count-pages.hook.mjs.map +1 -1
  194. package/dist/modules/pages/services/pages.service.mjs.map +1 -1
  195. package/dist/modules/plans/handlers/find-plan-by-id.handler.mjs.map +1 -1
  196. package/dist/modules/plans/handlers/list-plans.handler.mjs.map +1 -1
  197. package/dist/modules/plans/hooks/list-plans.hook.mjs.map +1 -1
  198. package/dist/modules/plans/hooks/use-has-plan-addon.hook.mjs.map +1 -1
  199. package/dist/modules/plans/hooks/use-plan-by-id.hook.mjs.map +1 -1
  200. package/dist/modules/plans/services/plans.service.mjs.map +1 -1
  201. package/dist/modules/plans/types/plan.type.mjs.map +1 -1
  202. package/dist/modules/plans/utils/map-api-plan-to-ui.mjs.map +1 -1
  203. package/dist/modules/projects/actions/add-project-user.action.mjs.map +1 -1
  204. package/dist/modules/projects/actions/create-project.action.mjs.map +1 -1
  205. package/dist/modules/projects/actions/delete-project.action.mjs.map +1 -1
  206. package/dist/modules/projects/actions/find-project.action.mjs.map +1 -1
  207. package/dist/modules/projects/actions/list-project-users.action.mjs.map +1 -1
  208. package/dist/modules/projects/actions/list-projects.action.mjs.map +1 -1
  209. package/dist/modules/projects/actions/remove-project-user.action.mjs.map +1 -1
  210. package/dist/modules/projects/actions/update-project.action.mjs.map +1 -1
  211. package/dist/modules/projects/handlers/find-project.handler.mjs.map +1 -1
  212. package/dist/modules/projects/handlers/list-all-account-users.handler.mjs.map +1 -1
  213. package/dist/modules/projects/handlers/list-available-users.handler.mjs.map +1 -1
  214. package/dist/modules/projects/handlers/list-project-users.handler.mjs.map +1 -1
  215. package/dist/modules/projects/handlers/list-projects.handler.mjs.map +1 -1
  216. package/dist/modules/projects/hooks/add-project-user.hook.mjs.map +1 -1
  217. package/dist/modules/projects/hooks/create-project.hook.mjs.map +1 -1
  218. package/dist/modules/projects/hooks/delete-project.hook.mjs.map +1 -1
  219. package/dist/modules/projects/hooks/find-project.hook.mjs.map +1 -1
  220. package/dist/modules/projects/hooks/list-all-account-users.hook.mjs.map +1 -1
  221. package/dist/modules/projects/hooks/list-available-users.hook.mjs.map +1 -1
  222. package/dist/modules/projects/hooks/list-infinite-projects.hook.mjs.map +1 -1
  223. package/dist/modules/projects/hooks/list-project-users.hook.mjs.map +1 -1
  224. package/dist/modules/projects/hooks/list-projects.hook.mjs.map +1 -1
  225. package/dist/modules/projects/hooks/remove-project-user.hook.mjs.map +1 -1
  226. package/dist/modules/projects/hooks/update-project.hook.mjs.map +1 -1
  227. package/dist/modules/projects/services/projects.service.mjs.map +1 -1
  228. package/dist/modules/subscriptions/actions/calculate-subscription.action.mjs.map +1 -1
  229. package/dist/modules/subscriptions/actions/list-subscriptions.action.mjs.map +1 -1
  230. package/dist/modules/subscriptions/actions/update-subscription-payment.action.mjs.map +1 -1
  231. package/dist/modules/subscriptions/actions/update-subscription-plan.action.mjs.map +1 -1
  232. package/dist/modules/subscriptions/constants/query-keys.constants.mjs.map +1 -1
  233. package/dist/modules/subscriptions/constants/subscription.constants.mjs.map +1 -1
  234. package/dist/modules/subscriptions/handlers/list-subscriptions.handler.mjs.map +1 -1
  235. package/dist/modules/subscriptions/hooks/calculate-subscription.hook.mjs.map +1 -1
  236. package/dist/modules/subscriptions/hooks/find-active-subscription.hook.mjs.map +1 -1
  237. package/dist/modules/subscriptions/hooks/list-subscriptions.hook.mjs.map +1 -1
  238. package/dist/modules/subscriptions/hooks/update-subscription-payment.hook.mjs.map +1 -1
  239. package/dist/modules/subscriptions/hooks/update-subscription-plan.hook.mjs.map +1 -1
  240. package/dist/modules/subscriptions/hooks/use-cancelled-subscription-guard.mjs.map +1 -1
  241. package/dist/modules/subscriptions/types/calculate-subscription.type.mjs.map +1 -1
  242. package/dist/modules/subscriptions/types/pix-pending.type.mjs.map +1 -1
  243. package/dist/modules/subscriptions/utils/build-plan-extras.mjs.map +1 -1
  244. package/dist/modules/subscriptions/utils/get-subscription-cancellation-state.mjs.map +1 -1
  245. package/dist/modules/subscriptions/utils/get-subscription-expiry-date.mjs.map +1 -1
  246. package/dist/modules/subscriptions/utils/has-subscription-expired.mjs.map +1 -1
  247. package/dist/modules/subscriptions/utils/periodicity.mjs.map +1 -1
  248. package/dist/modules/subscriptions/utils/resolve-plan-extras-prices.mjs.map +1 -1
  249. package/dist/modules/users/action/find-user-by-id.action.mjs.map +1 -1
  250. package/dist/modules/users/action/mark-all-messages-as-read.action.mjs.map +1 -1
  251. package/dist/modules/users/action/mark-message-as-read.action.mjs.map +1 -1
  252. package/dist/modules/users/handlers/list-messages.handler.mjs.map +1 -1
  253. package/dist/modules/users/hooks/messages.hook.mjs.map +1 -1
  254. package/dist/modules/users/services/messages.service.mjs.map +1 -1
  255. package/dist/modules/whitelabel/actions/find-whitelabel.action.mjs.map +1 -1
  256. package/dist/modules/whitelabel/actions/revalidate-whitelabel.action.mjs.map +1 -1
  257. package/dist/modules/whitelabel/utils/normalize-hostname.mjs.map +1 -1
  258. package/dist/providers/auth.provider.mjs.map +1 -1
  259. package/dist/providers/navigation.provider.mjs.map +1 -1
  260. package/dist/providers/whitelabel.provider.mjs.map +1 -1
  261. package/dist/route.mjs.map +1 -1
  262. package/dist/store/useAccountModals.mjs.map +1 -1
  263. package/dist/store/useBuyCreditsModal.mjs.map +1 -1
  264. package/dist/store/useCreditsDisabledModal.mjs.map +1 -1
  265. package/dist/store/useDesktopSidebarStore.mjs.map +1 -1
  266. package/dist/store/useHexaPromoModal.mjs.map +1 -1
  267. package/dist/store/useMdSidebarStore.mjs.map +1 -1
  268. package/dist/store/usePaidPlanRequiredModal.mjs.map +1 -1
  269. package/dist/utils/constants/br-states.mjs.map +1 -1
  270. package/dist/utils/cookies/hexa-promo.mjs.map +1 -1
  271. package/dist/utils/countries.mjs.map +1 -1
  272. package/dist/utils/format/currency.mjs.map +1 -1
  273. package/dist/utils/intl/cookie-domain.mjs.map +1 -1
  274. package/dist/utils/intl/locale-cookie.mjs.map +1 -1
  275. package/dist/utils/next-navigation.mjs.map +1 -1
  276. package/dist/utils/redirect.mjs.map +1 -1
  277. package/dist/utils/safeMutationAction.mjs.map +1 -1
  278. package/dist/utils/safeServerAction.mjs.map +1 -1
  279. package/dist/utils/withAction.mjs.map +1 -1
  280. package/package.json +115 -115
  281. package/src/components/account/ConfigurationsMyAccountModal.tsx +179 -179
  282. package/src/components/account/ConfirmDeleteAccountModal.tsx +110 -110
  283. package/src/components/account/ConfirmGlobalPreferencesModal.tsx +68 -68
  284. package/src/components/account/DeleteAccountModal.tsx +160 -160
  285. package/src/components/account/DisableTwoFactorAuthModal.tsx +92 -92
  286. package/src/components/account/IsntPossibleDeleteAccountModal.tsx +51 -51
  287. package/src/components/account/TwoFactorAuthModal.tsx +220 -220
  288. package/src/components/account/hooks/useChangePhoneForm.tsx +113 -113
  289. package/src/components/account/hooks/useTwoFactorAuthForm.tsx +116 -116
  290. package/src/components/account/sections/ChangeEmailModal.tsx +239 -239
  291. package/src/components/account/sections/ChangePasswordSection.tsx +68 -68
  292. package/src/components/account/sections/ChangePhoneModal.tsx +273 -273
  293. package/src/components/account/sections/MyProfileSection.tsx +276 -276
  294. package/src/components/account/sections/PreferencesSection.tsx +278 -278
  295. package/src/components/account/sections/SecuritySection.tsx +102 -102
  296. package/src/components/account/sections/TokenSection.tsx +85 -85
  297. package/src/components/embeds/ClarityEmbed.tsx +70 -70
  298. package/src/components/embeds/CrispEmbed.tsx +195 -195
  299. package/src/components/embeds/EmbedWidgets.tsx +62 -62
  300. package/src/components/embeds/FrillEmbed.tsx +146 -146
  301. package/src/components/layouts/AppMobileNavBar.tsx +214 -214
  302. package/src/components/layouts/AppNavBar.tsx +40 -40
  303. package/src/components/layouts/MdSideBarNavigation.tsx +56 -56
  304. package/src/components/layouts/NavBar.tsx +228 -228
  305. package/src/components/layouts/NotificationsPopover.tsx +120 -120
  306. package/src/components/layouts/ProfilePopover.tsx +191 -191
  307. package/src/components/layouts/SideBarNavigation.tsx +65 -65
  308. package/src/components/layouts/UsersSelectorPopover.tsx +236 -236
  309. package/src/components/layouts/WhitelabelCodes.tsx +59 -59
  310. package/src/components/modals/BuyCreditsModal.tsx +390 -390
  311. package/src/components/modals/CreditsDisabledModal.tsx +62 -62
  312. package/src/components/modals/HexaPromoModal.tsx +212 -212
  313. package/src/components/modals/HexaPromoModalGate.tsx +80 -80
  314. package/src/components/modals/Modals.tsx +25 -25
  315. package/src/components/modals/PaidPlanRequiredModal.tsx +60 -60
  316. package/src/components/modals/cards/AddCardModal.tsx +420 -420
  317. package/src/components/modals/cards/CannotDeleteCardModal.tsx +124 -124
  318. package/src/components/modals/cards/CardFormFields.tsx +363 -363
  319. package/src/components/modals/cards/DeleteCardModal.tsx +136 -136
  320. package/src/components/navigation/CancelledSubscriptionBanner.tsx +62 -62
  321. package/src/components/navigation/NavItemsContext.ts +20 -20
  322. package/src/components/navigation/OverdueInvoiceBanner.tsx +51 -51
  323. package/src/components/navigation/PendingCancellationBanner.tsx +60 -60
  324. package/src/components/navigation/ProjectSelectorPopover.tsx +180 -180
  325. package/src/components/navigation/SubscriptionBanner.tsx +94 -94
  326. package/src/components/navigation/TrialBanner.tsx +54 -54
  327. package/src/components/navigation/UpcomingInvoiceBanner.tsx +55 -55
  328. package/src/components/navigation/shells/TabsMobileShell.tsx +74 -74
  329. package/src/components/navigation/subcomponents/BottomLinks.tsx +85 -85
  330. package/src/components/navigation/subcomponents/ProjectSelector.tsx +184 -184
  331. package/src/components/pages/NotFoundPage.tsx +75 -75
  332. package/src/components/pages/notifications/Notifications.tsx +190 -190
  333. package/src/components/ui/buttons/Button.tsx +77 -77
  334. package/src/components/ui/buttons/CancelButton.tsx +14 -14
  335. package/src/components/ui/buttons/CopyButton.tsx +59 -59
  336. package/src/components/ui/data-display/Accordion.tsx +81 -81
  337. package/src/components/ui/data-display/Badge.tsx +47 -47
  338. package/src/components/ui/data-display/Card.tsx +93 -93
  339. package/src/components/ui/data-display/CardBrandIcons.tsx +336 -336
  340. package/src/components/ui/data-display/CardItem.tsx +135 -135
  341. package/src/components/ui/data-display/Pagination.tsx +126 -126
  342. package/src/components/ui/data-display/PaymentInfoCard.tsx +193 -193
  343. package/src/components/ui/data-display/ScrollArea.tsx +59 -59
  344. package/src/components/ui/data-display/Separator.tsx +29 -29
  345. package/src/components/ui/data-display/Table.tsx +117 -117
  346. package/src/components/ui/data-display/Tabs.tsx +67 -67
  347. package/src/components/ui/feedback/CircularProgress.tsx +79 -79
  348. package/src/components/ui/feedback/DefaultCircularProgress.tsx +67 -67
  349. package/src/components/ui/feedback/LoadingOverlay.tsx +30 -30
  350. package/src/components/ui/feedback/Progress.tsx +40 -40
  351. package/src/components/ui/feedback/Skeleton.tsx +5 -5
  352. package/src/components/ui/feedback/Toast.tsx +104 -104
  353. package/src/components/ui/form/Calendar.tsx +228 -228
  354. package/src/components/ui/form/Checkbox.tsx +31 -31
  355. package/src/components/ui/form/ComboboxField.tsx +159 -159
  356. package/src/components/ui/form/DatePicker.tsx +100 -100
  357. package/src/components/ui/form/DateRangePicker.tsx +111 -111
  358. package/src/components/ui/form/FormField.tsx +133 -133
  359. package/src/components/ui/form/Input.tsx +20 -20
  360. package/src/components/ui/form/InputOtp.tsx +80 -80
  361. package/src/components/ui/form/PhoneInput.tsx +210 -210
  362. package/src/components/ui/form/RadioGroup.tsx +45 -45
  363. package/src/components/ui/form/Select.tsx +200 -200
  364. package/src/components/ui/form/Switch.tsx +32 -32
  365. package/src/components/ui/form/Textarea.tsx +19 -19
  366. package/src/components/ui/overlay/Command.tsx +185 -185
  367. package/src/components/ui/overlay/Dialog.tsx +153 -153
  368. package/src/components/ui/overlay/Popover.tsx +49 -49
  369. package/src/components/ui/overlay/Sheet.tsx +170 -170
  370. package/src/components/ui/overlay/Tooltip.tsx +62 -62
  371. package/src/components/widgets/ImageUpload/ImageCropModal.tsx +392 -392
  372. package/src/components/widgets/ImageUpload/ImageTooSmallModal.tsx +62 -62
  373. package/src/components/widgets/ImageUpload/ImageUpload.tsx +131 -131
  374. package/src/components/widgets/ImageUpload/index.ts +3 -3
  375. package/src/components/widgets/notifications/NotificationCard.tsx +73 -73
  376. package/src/handlers.ts +22 -22
  377. package/src/hooks/copy-to-clipboard.hook.tsx +67 -67
  378. package/src/hooks/useAuthQueryKey.ts +32 -32
  379. package/src/hooks/useBrandLoadingIcon.tsx +18 -18
  380. package/src/hooks/useRouter.ts +38 -38
  381. package/src/http.ts +1 -1
  382. package/src/i18n/config.ts +17 -17
  383. package/src/i18n/country-language.ts +60 -60
  384. package/src/i18n/messages/en-us.ts +519 -519
  385. package/src/i18n/messages/es-es.ts +520 -520
  386. package/src/i18n/messages/index.ts +24 -24
  387. package/src/i18n/messages/pt-br.ts +543 -543
  388. package/src/i18n/normalize.ts +15 -15
  389. package/src/i18n/resolve-locale.ts +77 -77
  390. package/src/i18n.ts +10 -10
  391. package/src/index.ts +587 -587
  392. package/src/infra/http/api-fetch.ts +39 -39
  393. package/src/infra/route/parse-id.ts +9 -9
  394. package/src/infra/route/parse-numeric.ts +16 -16
  395. package/src/infra/route/safe-route-handler.ts +16 -16
  396. package/src/infra/route/search-params.ts +9 -9
  397. package/src/infra/utils/array.ts +167 -167
  398. package/src/infra/utils/date.ts +59 -59
  399. package/src/middleware.ts +4 -4
  400. package/src/modules/accounts/actions/account-management.action.ts +109 -109
  401. package/src/modules/accounts/actions/find-current-account.action.ts +9 -9
  402. package/src/modules/accounts/actions/get-account-token.action.ts +8 -8
  403. package/src/modules/accounts/actions/list-currencies.action.ts +8 -8
  404. package/src/modules/accounts/actions/list-timezones.action.ts +8 -8
  405. package/src/modules/accounts/hooks/current-account.hook.tsx +26 -26
  406. package/src/modules/accounts/hooks/use-account-token.hook.tsx +14 -14
  407. package/src/modules/accounts/hooks/use-currency-formatter.hook.tsx +32 -32
  408. package/src/modules/accounts/hooks/useAccountManagement.ts +95 -95
  409. package/src/modules/accounts/hooks/useCurrencies.ts +18 -18
  410. package/src/modules/accounts/hooks/useTimezones.ts +18 -18
  411. package/src/modules/accounts/hooks/useViaCep.ts +25 -25
  412. package/src/modules/accounts/services/account-token.service.ts +52 -52
  413. package/src/modules/accounts/services/account.service.ts +243 -243
  414. package/src/modules/accounts/types.ts +230 -230
  415. package/src/modules/auth/actions/social-google-login.action.ts +12 -12
  416. package/src/modules/auth/actions/social-google-onboarding.action.ts +13 -13
  417. package/src/modules/auth/actions/unlink-google.action.ts +8 -8
  418. package/src/modules/auth/actions/validate-session.action.ts +70 -70
  419. package/src/modules/auth/actions/verify-two-factor.action.ts +19 -19
  420. package/src/modules/auth/hooks/login.hook.tsx +13 -13
  421. package/src/modules/auth/hooks/logout.hook.tsx +11 -11
  422. package/src/modules/auth/hooks/register.hook.tsx +11 -11
  423. package/src/modules/auth/hooks/social-google-login.hook.tsx +13 -13
  424. package/src/modules/auth/hooks/social-google-onboarding.hook.tsx +13 -13
  425. package/src/modules/auth/hooks/unlink-google.hook.tsx +13 -13
  426. package/src/modules/auth/hooks/useManagementPermissions.ts +52 -52
  427. package/src/modules/auth/hooks/useUserQuery.ts +103 -103
  428. package/src/modules/auth/types/management-permission.type.ts +14 -14
  429. package/src/modules/auth/utils/assert-management-permission.ts +56 -56
  430. package/src/modules/auth/utils/assert-management-subscription.ts +38 -38
  431. package/src/modules/auth/utils/assert-paid-subscription.ts +47 -47
  432. package/src/modules/auth/utils/assert-subscription-addon.ts +42 -42
  433. package/src/modules/auth/utils/build-wl-override.ts +43 -43
  434. package/src/modules/auth/utils/require-token-not-expired.ts +53 -53
  435. package/src/modules/auth/utils/require-valid-session.ts +35 -35
  436. package/src/modules/cards/actions/create-card.action.ts +9 -9
  437. package/src/modules/cards/actions/create-setup-intent.action.ts +8 -8
  438. package/src/modules/cards/actions/delete-card.action.ts +8 -8
  439. package/src/modules/cards/actions/set-default-card.action.ts +8 -8
  440. package/src/modules/cards/handlers/find-card-by-id.handler.ts +15 -15
  441. package/src/modules/cards/handlers/list-cards.handler.ts +10 -10
  442. package/src/modules/cards/hooks/card-by-id.hook.ts +17 -17
  443. package/src/modules/cards/hooks/cards.hook.ts +22 -22
  444. package/src/modules/cards/hooks/create-card.hook.ts +30 -30
  445. package/src/modules/cards/hooks/create-setup-intent.hook.ts +11 -11
  446. package/src/modules/cards/hooks/delete-card.hook.ts +52 -52
  447. package/src/modules/cards/hooks/delete-confirmation.hook.ts +40 -40
  448. package/src/modules/cards/hooks/handle-delete-card.hook.ts +47 -47
  449. package/src/modules/cards/hooks/set-default-card.hook.ts +55 -55
  450. package/src/modules/cards/services/cards.service.ts +136 -136
  451. package/src/modules/cards/types.ts +52 -52
  452. package/src/modules/charges/actions/charge-action.action.ts +13 -13
  453. package/src/modules/charges/handlers/find-charge-by-id.handler.ts +14 -14
  454. package/src/modules/charges/handlers/list-charges.handler.ts +15 -15
  455. package/src/modules/charges/hooks/charge-action.hook.ts +24 -24
  456. package/src/modules/charges/hooks/charge-by-id.hook.ts +19 -19
  457. package/src/modules/charges/hooks/charges.hook.ts +19 -19
  458. package/src/modules/charges/services/charges.service.ts +63 -63
  459. package/src/modules/charges/types/charge.type.ts +68 -68
  460. package/src/modules/ia-credits/handlers/list-ia-credits.handler.ts +14 -14
  461. package/src/modules/ia-credits/hooks/ia-credits.hook.ts +103 -103
  462. package/src/modules/images/actions/process-image.action.ts +40 -40
  463. package/src/modules/images/constants/image.constants.ts +11 -11
  464. package/src/modules/images/hooks/use-image-upload.hook.ts +153 -153
  465. package/src/modules/images/services/image-processing.service.ts +75 -75
  466. package/src/modules/images/types/image.type.ts +54 -54
  467. package/src/modules/images/utils/base64.ts +26 -26
  468. package/src/modules/images/utils/compress-image.ts +20 -20
  469. package/src/modules/images/utils/crop-image.ts +68 -68
  470. package/src/modules/images/utils/validate-image.ts +86 -86
  471. package/src/modules/pages/constants/query-keys.constants.ts +1 -1
  472. package/src/modules/pages/handlers/count-pages.handler.ts +12 -12
  473. package/src/modules/pages/hooks/count-pages.hook.ts +21 -21
  474. package/src/modules/pages/services/pages.service.ts +27 -27
  475. package/src/modules/plans/handlers/find-plan-by-id.handler.ts +14 -14
  476. package/src/modules/plans/handlers/list-plans.handler.ts +22 -22
  477. package/src/modules/plans/hooks/list-plans.hook.ts +23 -23
  478. package/src/modules/plans/hooks/use-has-plan-addon.hook.ts +14 -14
  479. package/src/modules/plans/hooks/use-plan-by-id.hook.ts +39 -39
  480. package/src/modules/plans/services/plans.service.ts +136 -136
  481. package/src/modules/plans/types/plan.type.ts +79 -79
  482. package/src/modules/plans/utils/map-api-plan-to-ui.ts +167 -167
  483. package/src/modules/projects/actions/add-project-user.action.ts +9 -9
  484. package/src/modules/projects/actions/create-project.action.ts +9 -9
  485. package/src/modules/projects/actions/delete-project.action.ts +8 -8
  486. package/src/modules/projects/actions/find-project.action.ts +8 -8
  487. package/src/modules/projects/actions/list-project-users.action.ts +9 -9
  488. package/src/modules/projects/actions/list-projects.action.ts +16 -16
  489. package/src/modules/projects/actions/remove-project-user.action.ts +9 -9
  490. package/src/modules/projects/actions/update-project.action.ts +9 -9
  491. package/src/modules/projects/handlers/find-project.handler.ts +15 -15
  492. package/src/modules/projects/handlers/list-all-account-users.handler.ts +23 -23
  493. package/src/modules/projects/handlers/list-available-users.handler.ts +26 -26
  494. package/src/modules/projects/handlers/list-project-users.handler.ts +26 -26
  495. package/src/modules/projects/handlers/list-projects.handler.ts +23 -23
  496. package/src/modules/projects/hooks/add-project-user.hook.ts +72 -72
  497. package/src/modules/projects/hooks/create-project.hook.ts +120 -120
  498. package/src/modules/projects/hooks/delete-project.hook.ts +58 -58
  499. package/src/modules/projects/hooks/find-project.hook.ts +18 -18
  500. package/src/modules/projects/hooks/list-all-account-users.hook.ts +40 -40
  501. package/src/modules/projects/hooks/list-available-users.hook.ts +39 -39
  502. package/src/modules/projects/hooks/list-infinite-projects.hook.ts +44 -44
  503. package/src/modules/projects/hooks/list-project-users.hook.ts +39 -39
  504. package/src/modules/projects/hooks/list-projects.hook.ts +23 -23
  505. package/src/modules/projects/hooks/remove-project-user.hook.ts +72 -72
  506. package/src/modules/projects/hooks/update-project.hook.ts +86 -86
  507. package/src/modules/projects/services/projects.service.ts +156 -156
  508. package/src/modules/subscriptions/actions/calculate-subscription.action.ts +9 -9
  509. package/src/modules/subscriptions/actions/list-subscriptions.action.ts +9 -9
  510. package/src/modules/subscriptions/actions/update-subscription-payment.action.ts +13 -13
  511. package/src/modules/subscriptions/actions/update-subscription-plan.action.ts +14 -14
  512. package/src/modules/subscriptions/constants/query-keys.constants.ts +3 -3
  513. package/src/modules/subscriptions/constants/subscription.constants.ts +1 -1
  514. package/src/modules/subscriptions/handlers/list-subscriptions.handler.ts +17 -17
  515. package/src/modules/subscriptions/hooks/calculate-subscription.hook.ts +13 -13
  516. package/src/modules/subscriptions/hooks/find-active-subscription.hook.ts +22 -22
  517. package/src/modules/subscriptions/hooks/list-subscriptions.hook.ts +22 -22
  518. package/src/modules/subscriptions/hooks/update-subscription-payment.hook.ts +25 -25
  519. package/src/modules/subscriptions/hooks/update-subscription-plan.hook.ts +28 -28
  520. package/src/modules/subscriptions/hooks/use-cancelled-subscription-guard.ts +44 -44
  521. package/src/modules/subscriptions/types/billing-period.type.ts +1 -1
  522. package/src/modules/subscriptions/types/calculate-subscription.type.ts +116 -116
  523. package/src/modules/subscriptions/types/pix-pending.type.ts +38 -38
  524. package/src/modules/subscriptions/utils/build-plan-extras.ts +56 -56
  525. package/src/modules/subscriptions/utils/get-subscription-cancellation-state.ts +37 -37
  526. package/src/modules/subscriptions/utils/get-subscription-expiry-date.ts +33 -33
  527. package/src/modules/subscriptions/utils/has-subscription-expired.ts +11 -11
  528. package/src/modules/subscriptions/utils/periodicity.ts +79 -79
  529. package/src/modules/subscriptions/utils/resolve-plan-extras-prices.ts +23 -23
  530. package/src/modules/users/action/find-user-by-id.action.ts +8 -8
  531. package/src/modules/users/action/mark-all-messages-as-read.action.ts +8 -8
  532. package/src/modules/users/action/mark-message-as-read.action.ts +8 -8
  533. package/src/modules/users/handlers/list-messages.handler.ts +39 -39
  534. package/src/modules/users/hooks/messages.hook.ts +69 -69
  535. package/src/modules/users/services/messages.service.ts +49 -49
  536. package/src/modules/whitelabel/actions/find-whitelabel.action.ts +23 -23
  537. package/src/modules/whitelabel/actions/revalidate-whitelabel.action.ts +19 -19
  538. package/src/modules/whitelabel/schema.ts +84 -84
  539. package/src/modules/whitelabel/utils/normalize-hostname.ts +26 -26
  540. package/src/providers/auth.provider.tsx +267 -267
  541. package/src/providers/navigation.provider.tsx +99 -99
  542. package/src/providers/whitelabel.provider.tsx +90 -90
  543. package/src/route.ts +4 -4
  544. package/src/store/useAccountModals.ts +85 -85
  545. package/src/store/useBuyCreditsModal.ts +21 -21
  546. package/src/store/useCreditsDisabledModal.ts +11 -11
  547. package/src/store/useDesktopSidebarStore.ts +47 -47
  548. package/src/store/useHexaPromoModal.ts +13 -13
  549. package/src/store/useMdSidebarStore.ts +34 -34
  550. package/src/store/usePaidPlanRequiredModal.ts +19 -19
  551. package/src/utils/constants/br-states.ts +29 -29
  552. package/src/utils/cookies/hexa-promo.ts +114 -114
  553. package/src/utils/countries.ts +224 -224
  554. package/src/utils/format/currency.ts +70 -70
  555. package/src/utils/intl/cookie-domain.ts +29 -29
  556. package/src/utils/intl/locale-cookie.ts +18 -18
  557. package/src/utils/next-navigation.ts +7 -7
  558. package/src/utils/redirect.ts +78 -78
  559. package/src/utils/safeMutationAction.ts +24 -24
  560. package/src/utils/safeServerAction.ts +21 -21
  561. package/src/utils/withAction.ts +13 -13
@@ -1,392 +1,392 @@
1
- 'use client'
2
-
3
- import { useEffect, useRef, useState } from 'react'
4
- import { useTranslations } from 'next-intl'
5
- import ReactCrop, {
6
- type Crop,
7
- centerCrop,
8
- makeAspectCrop,
9
- } from 'react-image-crop'
10
- import 'react-image-crop/dist/ReactCrop.css'
11
- import {
12
- Dialog,
13
- DialogContent,
14
- DialogFooter,
15
- DialogHeader,
16
- DialogTitle,
17
- } from '../../ui/overlay/Dialog'
18
- import { Button } from '../../ui/buttons/Button'
19
-
20
- // CSS customizado para grid pontilhado fino e círculo
21
- const baseCropStyles = `
22
- .custom-crop-area .ReactCrop__crop-selection {
23
- border: 2px solid white !important;
24
- box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.5) !important;
25
- }
26
-
27
- /* Grid de 9 quadrados - linhas pontilhadas finas */
28
- .custom-crop-area .ReactCrop__crop-selection .crop-grid {
29
- position: absolute;
30
- inset: 0;
31
- pointer-events: none;
32
- }
33
-
34
- .custom-crop-area .ReactCrop__crop-selection .crop-grid-line {
35
- position: absolute;
36
- background: repeating-linear-gradient(
37
- to right,
38
- rgba(255, 255, 255, 0.5) 0,
39
- rgba(255, 255, 255, 0.5) 4px,
40
- transparent 4px,
41
- transparent 8px
42
- );
43
- }
44
-
45
- .custom-crop-area .ReactCrop__crop-selection .crop-grid-line.horizontal {
46
- left: 0;
47
- right: 0;
48
- height: 1px;
49
- }
50
-
51
- .custom-crop-area .ReactCrop__crop-selection .crop-grid-line.vertical {
52
- top: 0;
53
- bottom: 0;
54
- width: 1px;
55
- background: repeating-linear-gradient(
56
- to bottom,
57
- rgba(255, 255, 255, 0.5) 0,
58
- rgba(255, 255, 255, 0.5) 4px,
59
- transparent 4px,
60
- transparent 8px
61
- );
62
- }
63
-
64
- .custom-crop-area .ReactCrop__crop-selection .crop-grid-line.h1 { top: 33.33%; }
65
- .custom-crop-area .ReactCrop__crop-selection .crop-grid-line.h2 { top: 66.66%; }
66
- .custom-crop-area .ReactCrop__crop-selection .crop-grid-line.v1 { left: 33.33%; }
67
- .custom-crop-area .ReactCrop__crop-selection .crop-grid-line.v2 { left: 66.66%; }
68
-
69
- /* Círculo inscrito */
70
- .custom-crop-area.with-circle .ReactCrop__crop-selection .crop-circle {
71
- position: absolute;
72
- inset: 0;
73
- border: 1px dashed rgba(255, 255, 255, 0.6);
74
- border-radius: 50%;
75
- pointer-events: none;
76
- }
77
-
78
- /* Ocultar handles das laterais (manter só os 4 cantos) */
79
- .custom-crop-area .ReactCrop__drag-handle.ord-n,
80
- .custom-crop-area .ReactCrop__drag-handle.ord-s,
81
- .custom-crop-area .ReactCrop__drag-handle.ord-e,
82
- .custom-crop-area .ReactCrop__drag-handle.ord-w {
83
- display: none !important;
84
- }
85
-
86
- /* Estilizar handles dos cantos — indicador preto em L nos cantos */
87
- .custom-crop-area .ReactCrop__drag-handle.ord-nw,
88
- .custom-crop-area .ReactCrop__drag-handle.ord-ne,
89
- .custom-crop-area .ReactCrop__drag-handle.ord-sw,
90
- .custom-crop-area .ReactCrop__drag-handle.ord-se {
91
- width: 20px;
92
- height: 20px;
93
- background: transparent !important;
94
- border: none !important;
95
- }
96
-
97
- .custom-crop-area .ReactCrop__drag-handle.ord-nw::after,
98
- .custom-crop-area .ReactCrop__drag-handle.ord-ne::after,
99
- .custom-crop-area .ReactCrop__drag-handle.ord-sw::after,
100
- .custom-crop-area .ReactCrop__drag-handle.ord-se::after {
101
- content: '';
102
- position: absolute;
103
- width: 22px;
104
- height: 22px;
105
- border-color: white;
106
- border-style: solid;
107
- border-width: 0;
108
- }
109
-
110
- .custom-crop-area .ReactCrop__drag-handle.ord-nw::after {
111
- top: -2px; left: -2px;
112
- border-top-width: 4px;
113
- border-left-width: 4px;
114
- }
115
-
116
- .custom-crop-area .ReactCrop__drag-handle.ord-ne::after {
117
- top: -2px; right: -2px;
118
- border-top-width: 4px;
119
- border-right-width: 4px;
120
- }
121
-
122
- .custom-crop-area .ReactCrop__drag-handle.ord-sw::after {
123
- bottom: -2px; left: -2px;
124
- border-bottom-width: 4px;
125
- border-left-width: 4px;
126
- }
127
-
128
- .custom-crop-area .ReactCrop__drag-handle.ord-se::after {
129
- bottom: -2px; right: -2px;
130
- border-bottom-width: 4px;
131
- border-right-width: 4px;
132
- }
133
-
134
- /* Desabilitar drag da imagem de fundo */
135
- .custom-crop-area img {
136
- pointer-events: none;
137
- user-select: none;
138
- -webkit-user-drag: none;
139
- /* Xadrez de transparência: fica atrás dos pixels da imagem, então só
140
- aparece onde a imagem é transparente. Imagens opacas cobrem o padrão. */
141
- background-color: #fff;
142
- background-image:
143
- linear-gradient(45deg, #ccc 25%, transparent 25%),
144
- linear-gradient(-45deg, #ccc 25%, transparent 25%),
145
- linear-gradient(45deg, transparent 75%, #ccc 75%),
146
- linear-gradient(-45deg, transparent 75%, #ccc 75%);
147
- background-size: 16px 16px;
148
- background-position: 0 0, 0 8px, 8px -8px, -8px 0;
149
- }
150
- `
151
-
152
- interface ImageCropModalProps {
153
- open: boolean
154
- onOpenChange: (open: boolean) => void
155
- imageSrc: string
156
- aspectRatio: number
157
- onConfirm: (image: HTMLImageElement, crop: Crop) => void
158
- onCancel?: () => void
159
- onImageLoad?: (naturalWidth: number, naturalHeight: number) => void
160
- showCircleGuide?: boolean
161
- minWidth?: number
162
- minHeight?: number
163
- /**
164
- * Nome do arquivo atual, usado na mensagem da variante "imagem muito pequena".
165
- * Opcional — se ausente, a mensagem cai num texto genérico.
166
- */
167
- fileName?: string
168
- /**
169
- * Callback disparado quando o usuário clica em "Enviar outra" na variante
170
- * "imagem muito pequena". Normalmente abre um file input. Se não for passado,
171
- * o botão "Enviar outra" é escondido.
172
- */
173
- onSelectAnother?: () => void
174
- }
175
-
176
- type ImageStatus = 'loading' | 'too-small' | 'ok'
177
-
178
- export function ImageCropModal({
179
- open,
180
- onOpenChange,
181
- imageSrc,
182
- aspectRatio,
183
- onConfirm,
184
- onCancel,
185
- onImageLoad: onImageLoadCallback,
186
- showCircleGuide,
187
- minWidth,
188
- minHeight,
189
- fileName,
190
- onSelectAnother,
191
- }: ImageCropModalProps) {
192
- const translate = useTranslations()
193
- const imgRef = useRef<HTMLImageElement>(null)
194
- const [crop, setCrop] = useState<Crop>()
195
- const [imageSize, setImageSize] = useState({ width: 0, height: 0 })
196
- const [imageStatus, setImageStatus] = useState<ImageStatus>('loading')
197
-
198
- // Ref pra callback externo — evita re-rodar o effect de preload toda vez que
199
- // a identidade do callback muda.
200
- const onImageLoadCallbackRef = useRef(onImageLoadCallback)
201
- useEffect(() => {
202
- onImageLoadCallbackRef.current = onImageLoadCallback
203
- })
204
-
205
- // Pre-carrega a imagem fora do DOM pra medir dimensões ANTES de montar
206
- // o ReactCrop. Assim conseguimos decidir entre a variante de crop e a
207
- // variante "imagem muito pequena" sem flash de UI.
208
- useEffect(() => {
209
- if (!open || !imageSrc) {
210
- setImageStatus('loading')
211
- return
212
- }
213
-
214
- setImageStatus('loading')
215
- let cancelled = false
216
-
217
- const img = new window.Image()
218
- img.onload = () => {
219
- if (cancelled) return
220
- const { naturalWidth, naturalHeight } = img
221
- setImageSize({ width: naturalWidth, height: naturalHeight })
222
- onImageLoadCallbackRef.current?.(naturalWidth, naturalHeight)
223
-
224
- const tooSmall =
225
- (minWidth !== undefined && naturalWidth < minWidth) ||
226
- (minHeight !== undefined && naturalHeight < minHeight)
227
- setImageStatus(tooSmall ? 'too-small' : 'ok')
228
- }
229
- img.onerror = () => {
230
- if (cancelled) return
231
- setImageStatus('too-small')
232
- }
233
- img.src = imageSrc
234
-
235
- return () => {
236
- cancelled = true
237
- }
238
- }, [open, imageSrc, minWidth, minHeight])
239
-
240
- // Inicializa o crop quando o <img> do ReactCrop monta. A imagem já está em
241
- // cache vinda do preload, então carrega instantâneo.
242
- const onCropImgLoad = (e: React.SyntheticEvent<HTMLImageElement>) => {
243
- const { naturalWidth, naturalHeight } = e.currentTarget
244
- const initialCrop = centerCrop(
245
- makeAspectCrop(
246
- { unit: '%', width: 90 },
247
- aspectRatio,
248
- naturalWidth,
249
- naturalHeight
250
- ),
251
- naturalWidth,
252
- naturalHeight
253
- )
254
- setCrop(initialCrop)
255
- }
256
-
257
- // Calcula tamanho mínimo em porcentagem baseado nas dimensões mínimas em pixels
258
- const minCropWidth = minWidth && imageSize.width > 0
259
- ? Math.min((minWidth / imageSize.width) * 100, 100)
260
- : undefined
261
- const minCropHeight = minHeight && imageSize.height > 0
262
- ? Math.min((minHeight / imageSize.height) * 100, 100)
263
- : undefined
264
-
265
- const handleConfirm = () => {
266
- if (imgRef.current && crop) {
267
- onConfirm(imgRef.current, crop)
268
- }
269
- }
270
-
271
- const handleCancel = () => {
272
- onCancel?.()
273
- onOpenChange(false)
274
- }
275
-
276
- // Determina se deve mostrar círculo (aspect ratio 1:1 por padrão)
277
- const shouldShowCircle = showCircleGuide ?? aspectRatio === 1
278
-
279
- // Renderiza grid, círculo e bolinhas dentro da área de crop
280
- const renderSelectionAddon = () => (
281
- <>
282
- {/* Grid de 9 quadrados com linhas pontilhadas */}
283
- <div className="crop-grid">
284
- <div className="crop-grid-line horizontal h1" />
285
- <div className="crop-grid-line horizontal h2" />
286
- <div className="crop-grid-line vertical v1" />
287
- <div className="crop-grid-line vertical v2" />
288
- </div>
289
- {/* Círculo inscrito */}
290
- {shouldShowCircle && <div className="crop-circle" />}
291
- </>
292
- )
293
-
294
- const dimensionText =
295
- minWidth !== undefined && minHeight !== undefined
296
- ? `${minWidth}x${minHeight}px`
297
- : null
298
-
299
- const isTooSmall = imageStatus === 'too-small'
300
-
301
- return (
302
- <Dialog open={open} onOpenChange={onOpenChange}>
303
- <style>{baseCropStyles}</style>
304
- <DialogContent
305
- className={
306
- isTooSmall
307
- ? 'w-full md:w-[480px]! lg:w-[480px]! max-w-[480px]! max-[480px]:w-[calc(100%-32px)] p-0 gap-0 z-[1003]!'
308
- : 'w-full md:w-[650px]! lg:w-[650px]! max-w-[650px]! max-[650px]:w-[calc(100%-32px)] p-0 gap-0 z-[1003]!'
309
- }
310
- overlayClassName="z-[1002]!"
311
- >
312
- {isTooSmall ? (
313
- <>
314
- <DialogHeader className="p-5">
315
- <DialogTitle className="text-center text-[16px]!">
316
- {dimensionText
317
- ? translate('common.imageUpload.tooSmallTitleWithDimension', { dimensionText })
318
- : translate('common.imageUpload.tooSmallTitleGeneric')}
319
- </DialogTitle>
320
- </DialogHeader>
321
-
322
- <div className="px-5 pb-5">
323
- <p className="paragraph-small-regular text-zinc-600 text-center">
324
- {fileName && dimensionText
325
- ? translate('common.imageUpload.tooSmallBodyFileWithDimension', { fileName, dimensionText })
326
- : fileName && !dimensionText
327
- ? translate('common.imageUpload.tooSmallBodyFileGeneric', { fileName })
328
- : !fileName && dimensionText
329
- ? translate('common.imageUpload.tooSmallBodyNoFileWithDimension', { dimensionText })
330
- : translate('common.imageUpload.tooSmallBodyNoFileGeneric')}
331
- </p>
332
- </div>
333
-
334
- <DialogFooter className="flex-row! items-center justify-start! gap-3 p-5 border-t border-zinc-200">
335
- {onSelectAnother && <Button onClick={onSelectAnother}>{translate('common.imageUpload.sendAnother')}</Button>}
336
- <Button variant="secondary" onClick={handleCancel}>
337
- {translate('common.actions.cancel')}
338
- </Button>
339
- </DialogFooter>
340
- </>
341
- ) : (
342
- <>
343
- <DialogHeader className="p-5">
344
- <DialogTitle className="text-center text-[16px]!">
345
- {translate('common.imageUpload.cropTitle')}
346
- </DialogTitle>
347
- </DialogHeader>
348
-
349
- <div className="flex flex-col gap-4 px-5 pb-5">
350
- <div className="flex justify-center overflow-hidden rounded-lg min-h-[200px]">
351
- {imageStatus === 'ok' && (
352
- <ReactCrop
353
- crop={crop}
354
- onChange={(c: Crop) => setCrop(c)}
355
- aspect={aspectRatio}
356
- className={`max-h-[50vh] custom-crop-area ${shouldShowCircle ? 'with-circle' : ''}`}
357
- keepSelection
358
- minWidth={minCropWidth}
359
- minHeight={minCropHeight}
360
- renderSelectionAddon={renderSelectionAddon}
361
- >
362
- <img
363
- ref={imgRef}
364
- src={imageSrc}
365
- alt={translate('common.imageUpload.cropAlt')}
366
- onLoad={onCropImgLoad}
367
- draggable={false}
368
- className="max-h-[50vh] object-contain select-none"
369
- />
370
- </ReactCrop>
371
- )}
372
- </div>
373
-
374
- <p className="paragraph-small-regular text-zinc-500 text-center">
375
- {translate('common.imageUpload.cropHint')}
376
- </p>
377
- </div>
378
-
379
- <DialogFooter className="flex-row! items-center justify-start! gap-3 p-5 border-t border-zinc-200">
380
- <Button onClick={handleConfirm} disabled={imageStatus !== 'ok' || !crop}>
381
- {translate('common.actions.confirm')}
382
- </Button>
383
- <Button variant="secondary" onClick={handleCancel}>
384
- {translate('common.actions.cancel')}
385
- </Button>
386
- </DialogFooter>
387
- </>
388
- )}
389
- </DialogContent>
390
- </Dialog>
391
- )
392
- }
1
+ 'use client'
2
+
3
+ import { useEffect, useRef, useState } from 'react'
4
+ import { useTranslations } from 'next-intl'
5
+ import ReactCrop, {
6
+ type Crop,
7
+ centerCrop,
8
+ makeAspectCrop,
9
+ } from 'react-image-crop'
10
+ import 'react-image-crop/dist/ReactCrop.css'
11
+ import {
12
+ Dialog,
13
+ DialogContent,
14
+ DialogFooter,
15
+ DialogHeader,
16
+ DialogTitle,
17
+ } from '../../ui/overlay/Dialog'
18
+ import { Button } from '../../ui/buttons/Button'
19
+
20
+ // CSS customizado para grid pontilhado fino e círculo
21
+ const baseCropStyles = `
22
+ .custom-crop-area .ReactCrop__crop-selection {
23
+ border: 2px solid white !important;
24
+ box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.5) !important;
25
+ }
26
+
27
+ /* Grid de 9 quadrados - linhas pontilhadas finas */
28
+ .custom-crop-area .ReactCrop__crop-selection .crop-grid {
29
+ position: absolute;
30
+ inset: 0;
31
+ pointer-events: none;
32
+ }
33
+
34
+ .custom-crop-area .ReactCrop__crop-selection .crop-grid-line {
35
+ position: absolute;
36
+ background: repeating-linear-gradient(
37
+ to right,
38
+ rgba(255, 255, 255, 0.5) 0,
39
+ rgba(255, 255, 255, 0.5) 4px,
40
+ transparent 4px,
41
+ transparent 8px
42
+ );
43
+ }
44
+
45
+ .custom-crop-area .ReactCrop__crop-selection .crop-grid-line.horizontal {
46
+ left: 0;
47
+ right: 0;
48
+ height: 1px;
49
+ }
50
+
51
+ .custom-crop-area .ReactCrop__crop-selection .crop-grid-line.vertical {
52
+ top: 0;
53
+ bottom: 0;
54
+ width: 1px;
55
+ background: repeating-linear-gradient(
56
+ to bottom,
57
+ rgba(255, 255, 255, 0.5) 0,
58
+ rgba(255, 255, 255, 0.5) 4px,
59
+ transparent 4px,
60
+ transparent 8px
61
+ );
62
+ }
63
+
64
+ .custom-crop-area .ReactCrop__crop-selection .crop-grid-line.h1 { top: 33.33%; }
65
+ .custom-crop-area .ReactCrop__crop-selection .crop-grid-line.h2 { top: 66.66%; }
66
+ .custom-crop-area .ReactCrop__crop-selection .crop-grid-line.v1 { left: 33.33%; }
67
+ .custom-crop-area .ReactCrop__crop-selection .crop-grid-line.v2 { left: 66.66%; }
68
+
69
+ /* Círculo inscrito */
70
+ .custom-crop-area.with-circle .ReactCrop__crop-selection .crop-circle {
71
+ position: absolute;
72
+ inset: 0;
73
+ border: 1px dashed rgba(255, 255, 255, 0.6);
74
+ border-radius: 50%;
75
+ pointer-events: none;
76
+ }
77
+
78
+ /* Ocultar handles das laterais (manter só os 4 cantos) */
79
+ .custom-crop-area .ReactCrop__drag-handle.ord-n,
80
+ .custom-crop-area .ReactCrop__drag-handle.ord-s,
81
+ .custom-crop-area .ReactCrop__drag-handle.ord-e,
82
+ .custom-crop-area .ReactCrop__drag-handle.ord-w {
83
+ display: none !important;
84
+ }
85
+
86
+ /* Estilizar handles dos cantos — indicador preto em L nos cantos */
87
+ .custom-crop-area .ReactCrop__drag-handle.ord-nw,
88
+ .custom-crop-area .ReactCrop__drag-handle.ord-ne,
89
+ .custom-crop-area .ReactCrop__drag-handle.ord-sw,
90
+ .custom-crop-area .ReactCrop__drag-handle.ord-se {
91
+ width: 20px;
92
+ height: 20px;
93
+ background: transparent !important;
94
+ border: none !important;
95
+ }
96
+
97
+ .custom-crop-area .ReactCrop__drag-handle.ord-nw::after,
98
+ .custom-crop-area .ReactCrop__drag-handle.ord-ne::after,
99
+ .custom-crop-area .ReactCrop__drag-handle.ord-sw::after,
100
+ .custom-crop-area .ReactCrop__drag-handle.ord-se::after {
101
+ content: '';
102
+ position: absolute;
103
+ width: 22px;
104
+ height: 22px;
105
+ border-color: white;
106
+ border-style: solid;
107
+ border-width: 0;
108
+ }
109
+
110
+ .custom-crop-area .ReactCrop__drag-handle.ord-nw::after {
111
+ top: -2px; left: -2px;
112
+ border-top-width: 4px;
113
+ border-left-width: 4px;
114
+ }
115
+
116
+ .custom-crop-area .ReactCrop__drag-handle.ord-ne::after {
117
+ top: -2px; right: -2px;
118
+ border-top-width: 4px;
119
+ border-right-width: 4px;
120
+ }
121
+
122
+ .custom-crop-area .ReactCrop__drag-handle.ord-sw::after {
123
+ bottom: -2px; left: -2px;
124
+ border-bottom-width: 4px;
125
+ border-left-width: 4px;
126
+ }
127
+
128
+ .custom-crop-area .ReactCrop__drag-handle.ord-se::after {
129
+ bottom: -2px; right: -2px;
130
+ border-bottom-width: 4px;
131
+ border-right-width: 4px;
132
+ }
133
+
134
+ /* Desabilitar drag da imagem de fundo */
135
+ .custom-crop-area img {
136
+ pointer-events: none;
137
+ user-select: none;
138
+ -webkit-user-drag: none;
139
+ /* Xadrez de transparência: fica atrás dos pixels da imagem, então só
140
+ aparece onde a imagem é transparente. Imagens opacas cobrem o padrão. */
141
+ background-color: #fff;
142
+ background-image:
143
+ linear-gradient(45deg, #ccc 25%, transparent 25%),
144
+ linear-gradient(-45deg, #ccc 25%, transparent 25%),
145
+ linear-gradient(45deg, transparent 75%, #ccc 75%),
146
+ linear-gradient(-45deg, transparent 75%, #ccc 75%);
147
+ background-size: 16px 16px;
148
+ background-position: 0 0, 0 8px, 8px -8px, -8px 0;
149
+ }
150
+ `
151
+
152
+ interface ImageCropModalProps {
153
+ open: boolean
154
+ onOpenChange: (open: boolean) => void
155
+ imageSrc: string
156
+ aspectRatio: number
157
+ onConfirm: (image: HTMLImageElement, crop: Crop) => void
158
+ onCancel?: () => void
159
+ onImageLoad?: (naturalWidth: number, naturalHeight: number) => void
160
+ showCircleGuide?: boolean
161
+ minWidth?: number
162
+ minHeight?: number
163
+ /**
164
+ * Nome do arquivo atual, usado na mensagem da variante "imagem muito pequena".
165
+ * Opcional — se ausente, a mensagem cai num texto genérico.
166
+ */
167
+ fileName?: string
168
+ /**
169
+ * Callback disparado quando o usuário clica em "Enviar outra" na variante
170
+ * "imagem muito pequena". Normalmente abre um file input. Se não for passado,
171
+ * o botão "Enviar outra" é escondido.
172
+ */
173
+ onSelectAnother?: () => void
174
+ }
175
+
176
+ type ImageStatus = 'loading' | 'too-small' | 'ok'
177
+
178
+ export function ImageCropModal({
179
+ open,
180
+ onOpenChange,
181
+ imageSrc,
182
+ aspectRatio,
183
+ onConfirm,
184
+ onCancel,
185
+ onImageLoad: onImageLoadCallback,
186
+ showCircleGuide,
187
+ minWidth,
188
+ minHeight,
189
+ fileName,
190
+ onSelectAnother,
191
+ }: ImageCropModalProps) {
192
+ const translate = useTranslations()
193
+ const imgRef = useRef<HTMLImageElement>(null)
194
+ const [crop, setCrop] = useState<Crop>()
195
+ const [imageSize, setImageSize] = useState({ width: 0, height: 0 })
196
+ const [imageStatus, setImageStatus] = useState<ImageStatus>('loading')
197
+
198
+ // Ref pra callback externo — evita re-rodar o effect de preload toda vez que
199
+ // a identidade do callback muda.
200
+ const onImageLoadCallbackRef = useRef(onImageLoadCallback)
201
+ useEffect(() => {
202
+ onImageLoadCallbackRef.current = onImageLoadCallback
203
+ })
204
+
205
+ // Pre-carrega a imagem fora do DOM pra medir dimensões ANTES de montar
206
+ // o ReactCrop. Assim conseguimos decidir entre a variante de crop e a
207
+ // variante "imagem muito pequena" sem flash de UI.
208
+ useEffect(() => {
209
+ if (!open || !imageSrc) {
210
+ setImageStatus('loading')
211
+ return
212
+ }
213
+
214
+ setImageStatus('loading')
215
+ let cancelled = false
216
+
217
+ const img = new window.Image()
218
+ img.onload = () => {
219
+ if (cancelled) return
220
+ const { naturalWidth, naturalHeight } = img
221
+ setImageSize({ width: naturalWidth, height: naturalHeight })
222
+ onImageLoadCallbackRef.current?.(naturalWidth, naturalHeight)
223
+
224
+ const tooSmall =
225
+ (minWidth !== undefined && naturalWidth < minWidth) ||
226
+ (minHeight !== undefined && naturalHeight < minHeight)
227
+ setImageStatus(tooSmall ? 'too-small' : 'ok')
228
+ }
229
+ img.onerror = () => {
230
+ if (cancelled) return
231
+ setImageStatus('too-small')
232
+ }
233
+ img.src = imageSrc
234
+
235
+ return () => {
236
+ cancelled = true
237
+ }
238
+ }, [open, imageSrc, minWidth, minHeight])
239
+
240
+ // Inicializa o crop quando o <img> do ReactCrop monta. A imagem já está em
241
+ // cache vinda do preload, então carrega instantâneo.
242
+ const onCropImgLoad = (e: React.SyntheticEvent<HTMLImageElement>) => {
243
+ const { naturalWidth, naturalHeight } = e.currentTarget
244
+ const initialCrop = centerCrop(
245
+ makeAspectCrop(
246
+ { unit: '%', width: 90 },
247
+ aspectRatio,
248
+ naturalWidth,
249
+ naturalHeight
250
+ ),
251
+ naturalWidth,
252
+ naturalHeight
253
+ )
254
+ setCrop(initialCrop)
255
+ }
256
+
257
+ // Calcula tamanho mínimo em porcentagem baseado nas dimensões mínimas em pixels
258
+ const minCropWidth = minWidth && imageSize.width > 0
259
+ ? Math.min((minWidth / imageSize.width) * 100, 100)
260
+ : undefined
261
+ const minCropHeight = minHeight && imageSize.height > 0
262
+ ? Math.min((minHeight / imageSize.height) * 100, 100)
263
+ : undefined
264
+
265
+ const handleConfirm = () => {
266
+ if (imgRef.current && crop) {
267
+ onConfirm(imgRef.current, crop)
268
+ }
269
+ }
270
+
271
+ const handleCancel = () => {
272
+ onCancel?.()
273
+ onOpenChange(false)
274
+ }
275
+
276
+ // Determina se deve mostrar círculo (aspect ratio 1:1 por padrão)
277
+ const shouldShowCircle = showCircleGuide ?? aspectRatio === 1
278
+
279
+ // Renderiza grid, círculo e bolinhas dentro da área de crop
280
+ const renderSelectionAddon = () => (
281
+ <>
282
+ {/* Grid de 9 quadrados com linhas pontilhadas */}
283
+ <div className="crop-grid">
284
+ <div className="crop-grid-line horizontal h1" />
285
+ <div className="crop-grid-line horizontal h2" />
286
+ <div className="crop-grid-line vertical v1" />
287
+ <div className="crop-grid-line vertical v2" />
288
+ </div>
289
+ {/* Círculo inscrito */}
290
+ {shouldShowCircle && <div className="crop-circle" />}
291
+ </>
292
+ )
293
+
294
+ const dimensionText =
295
+ minWidth !== undefined && minHeight !== undefined
296
+ ? `${minWidth}x${minHeight}px`
297
+ : null
298
+
299
+ const isTooSmall = imageStatus === 'too-small'
300
+
301
+ return (
302
+ <Dialog open={open} onOpenChange={onOpenChange}>
303
+ <style>{baseCropStyles}</style>
304
+ <DialogContent
305
+ className={
306
+ isTooSmall
307
+ ? 'w-full md:w-[480px]! lg:w-[480px]! max-w-[480px]! max-[480px]:w-[calc(100%-32px)] p-0 gap-0 z-[1003]!'
308
+ : 'w-full md:w-[650px]! lg:w-[650px]! max-w-[650px]! max-[650px]:w-[calc(100%-32px)] p-0 gap-0 z-[1003]!'
309
+ }
310
+ overlayClassName="z-[1002]!"
311
+ >
312
+ {isTooSmall ? (
313
+ <>
314
+ <DialogHeader className="p-5">
315
+ <DialogTitle className="text-center text-[16px]!">
316
+ {dimensionText
317
+ ? translate('common.imageUpload.tooSmallTitleWithDimension', { dimensionText })
318
+ : translate('common.imageUpload.tooSmallTitleGeneric')}
319
+ </DialogTitle>
320
+ </DialogHeader>
321
+
322
+ <div className="px-5 pb-5">
323
+ <p className="paragraph-small-regular text-zinc-600 text-center">
324
+ {fileName && dimensionText
325
+ ? translate('common.imageUpload.tooSmallBodyFileWithDimension', { fileName, dimensionText })
326
+ : fileName && !dimensionText
327
+ ? translate('common.imageUpload.tooSmallBodyFileGeneric', { fileName })
328
+ : !fileName && dimensionText
329
+ ? translate('common.imageUpload.tooSmallBodyNoFileWithDimension', { dimensionText })
330
+ : translate('common.imageUpload.tooSmallBodyNoFileGeneric')}
331
+ </p>
332
+ </div>
333
+
334
+ <DialogFooter className="flex-row! items-center justify-start! gap-3 p-5 border-t border-zinc-200">
335
+ {onSelectAnother && <Button onClick={onSelectAnother}>{translate('common.imageUpload.sendAnother')}</Button>}
336
+ <Button variant="secondary" onClick={handleCancel}>
337
+ {translate('common.actions.cancel')}
338
+ </Button>
339
+ </DialogFooter>
340
+ </>
341
+ ) : (
342
+ <>
343
+ <DialogHeader className="p-5">
344
+ <DialogTitle className="text-center text-[16px]!">
345
+ {translate('common.imageUpload.cropTitle')}
346
+ </DialogTitle>
347
+ </DialogHeader>
348
+
349
+ <div className="flex flex-col gap-4 px-5 pb-5">
350
+ <div className="flex justify-center overflow-hidden rounded-lg min-h-[200px]">
351
+ {imageStatus === 'ok' && (
352
+ <ReactCrop
353
+ crop={crop}
354
+ onChange={(c: Crop) => setCrop(c)}
355
+ aspect={aspectRatio}
356
+ className={`max-h-[50vh] custom-crop-area ${shouldShowCircle ? 'with-circle' : ''}`}
357
+ keepSelection
358
+ minWidth={minCropWidth}
359
+ minHeight={minCropHeight}
360
+ renderSelectionAddon={renderSelectionAddon}
361
+ >
362
+ <img
363
+ ref={imgRef}
364
+ src={imageSrc}
365
+ alt={translate('common.imageUpload.cropAlt')}
366
+ onLoad={onCropImgLoad}
367
+ draggable={false}
368
+ className="max-h-[50vh] object-contain select-none"
369
+ />
370
+ </ReactCrop>
371
+ )}
372
+ </div>
373
+
374
+ <p className="paragraph-small-regular text-zinc-500 text-center">
375
+ {translate('common.imageUpload.cropHint')}
376
+ </p>
377
+ </div>
378
+
379
+ <DialogFooter className="flex-row! items-center justify-start! gap-3 p-5 border-t border-zinc-200">
380
+ <Button onClick={handleConfirm} disabled={imageStatus !== 'ok' || !crop}>
381
+ {translate('common.actions.confirm')}
382
+ </Button>
383
+ <Button variant="secondary" onClick={handleCancel}>
384
+ {translate('common.actions.cancel')}
385
+ </Button>
386
+ </DialogFooter>
387
+ </>
388
+ )}
389
+ </DialogContent>
390
+ </Dialog>
391
+ )
392
+ }