@greatapps/common 1.1.700 → 1.1.702

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 (563) 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 +8 -1
  36. package/dist/components/modals/HexaPromoModalGate.mjs.map +1 -1
  37. package/dist/components/modals/Modals.mjs.map +1 -1
  38. package/dist/components/modals/PaidPlanRequiredModal.mjs.map +1 -1
  39. package/dist/components/modals/cards/AddCardModal.mjs.map +1 -1
  40. package/dist/components/modals/cards/CannotDeleteCardModal.mjs.map +1 -1
  41. package/dist/components/modals/cards/CardFormFields.mjs.map +1 -1
  42. package/dist/components/modals/cards/DeleteCardModal.mjs.map +1 -1
  43. package/dist/components/navigation/CancelledSubscriptionBanner.mjs.map +1 -1
  44. package/dist/components/navigation/NavItemsContext.mjs.map +1 -1
  45. package/dist/components/navigation/OverdueInvoiceBanner.mjs.map +1 -1
  46. package/dist/components/navigation/PendingCancellationBanner.mjs.map +1 -1
  47. package/dist/components/navigation/ProjectSelectorPopover.mjs.map +1 -1
  48. package/dist/components/navigation/SubscriptionBanner.mjs.map +1 -1
  49. package/dist/components/navigation/TrialBanner.mjs.map +1 -1
  50. package/dist/components/navigation/UpcomingInvoiceBanner.mjs.map +1 -1
  51. package/dist/components/navigation/shells/TabsMobileShell.mjs.map +1 -1
  52. package/dist/components/navigation/subcomponents/BottomLinks.mjs.map +1 -1
  53. package/dist/components/navigation/subcomponents/ProjectSelector.mjs.map +1 -1
  54. package/dist/components/pages/NotFoundPage.mjs.map +1 -1
  55. package/dist/components/pages/notifications/Notifications.mjs.map +1 -1
  56. package/dist/components/ui/buttons/Button.mjs.map +1 -1
  57. package/dist/components/ui/buttons/CancelButton.mjs.map +1 -1
  58. package/dist/components/ui/buttons/CopyButton.mjs.map +1 -1
  59. package/dist/components/ui/data-display/Accordion.mjs.map +1 -1
  60. package/dist/components/ui/data-display/Badge.mjs.map +1 -1
  61. package/dist/components/ui/data-display/Card.mjs.map +1 -1
  62. package/dist/components/ui/data-display/CardBrandIcons.mjs.map +1 -1
  63. package/dist/components/ui/data-display/CardItem.mjs.map +1 -1
  64. package/dist/components/ui/data-display/Pagination.mjs.map +1 -1
  65. package/dist/components/ui/data-display/PaymentInfoCard.mjs.map +1 -1
  66. package/dist/components/ui/data-display/ScrollArea.mjs.map +1 -1
  67. package/dist/components/ui/data-display/Separator.mjs.map +1 -1
  68. package/dist/components/ui/data-display/Table.mjs.map +1 -1
  69. package/dist/components/ui/data-display/Tabs.mjs.map +1 -1
  70. package/dist/components/ui/feedback/CircularProgress.mjs.map +1 -1
  71. package/dist/components/ui/feedback/DefaultCircularProgress.mjs.map +1 -1
  72. package/dist/components/ui/feedback/LoadingOverlay.mjs.map +1 -1
  73. package/dist/components/ui/feedback/Progress.mjs.map +1 -1
  74. package/dist/components/ui/feedback/Skeleton.mjs.map +1 -1
  75. package/dist/components/ui/feedback/Toast.mjs.map +1 -1
  76. package/dist/components/ui/form/Calendar.mjs.map +1 -1
  77. package/dist/components/ui/form/Checkbox.mjs.map +1 -1
  78. package/dist/components/ui/form/ComboboxField.mjs.map +1 -1
  79. package/dist/components/ui/form/DatePicker.mjs.map +1 -1
  80. package/dist/components/ui/form/DateRangePicker.mjs.map +1 -1
  81. package/dist/components/ui/form/FormField.mjs.map +1 -1
  82. package/dist/components/ui/form/Input.mjs.map +1 -1
  83. package/dist/components/ui/form/InputOtp.mjs.map +1 -1
  84. package/dist/components/ui/form/PhoneInput.mjs.map +1 -1
  85. package/dist/components/ui/form/RadioGroup.mjs.map +1 -1
  86. package/dist/components/ui/form/Select.mjs +1 -1
  87. package/dist/components/ui/form/Select.mjs.map +1 -1
  88. package/dist/components/ui/form/Switch.mjs.map +1 -1
  89. package/dist/components/ui/form/Textarea.mjs.map +1 -1
  90. package/dist/components/ui/overlay/Command.mjs.map +1 -1
  91. package/dist/components/ui/overlay/Dialog.mjs.map +1 -1
  92. package/dist/components/ui/overlay/Popover.mjs.map +1 -1
  93. package/dist/components/ui/overlay/Sheet.mjs.map +1 -1
  94. package/dist/components/ui/overlay/Tooltip.mjs.map +1 -1
  95. package/dist/components/widgets/ImageUpload/ImageCropModal.mjs.map +1 -1
  96. package/dist/components/widgets/ImageUpload/ImageTooSmallModal.mjs.map +1 -1
  97. package/dist/components/widgets/ImageUpload/ImageUpload.mjs.map +1 -1
  98. package/dist/components/widgets/ImageUpload/index.mjs.map +1 -1
  99. package/dist/components/widgets/notifications/NotificationCard.mjs.map +1 -1
  100. package/dist/handlers.mjs.map +1 -1
  101. package/dist/hooks/copy-to-clipboard.hook.mjs.map +1 -1
  102. package/dist/hooks/useAuthQueryKey.mjs.map +1 -1
  103. package/dist/hooks/useBrandLoadingIcon.mjs.map +1 -1
  104. package/dist/hooks/useRouter.mjs.map +1 -1
  105. package/dist/http.mjs.map +1 -1
  106. package/dist/i18n/config.mjs.map +1 -1
  107. package/dist/i18n/country-language.mjs.map +1 -1
  108. package/dist/i18n/messages/en-us.mjs.map +1 -1
  109. package/dist/i18n/messages/es-es.mjs.map +1 -1
  110. package/dist/i18n/messages/index.mjs.map +1 -1
  111. package/dist/i18n/messages/pt-br.mjs.map +1 -1
  112. package/dist/i18n/normalize.mjs.map +1 -1
  113. package/dist/i18n/resolve-locale.mjs.map +1 -1
  114. package/dist/i18n.mjs.map +1 -1
  115. package/dist/index.mjs.map +1 -1
  116. package/dist/infra/http/api-fetch.mjs.map +1 -1
  117. package/dist/infra/route/parse-id.mjs.map +1 -1
  118. package/dist/infra/route/parse-numeric.mjs.map +1 -1
  119. package/dist/infra/route/safe-route-handler.mjs.map +1 -1
  120. package/dist/infra/route/search-params.mjs.map +1 -1
  121. package/dist/infra/utils/array.mjs.map +1 -1
  122. package/dist/infra/utils/date.mjs.map +1 -1
  123. package/dist/middleware.mjs.map +1 -1
  124. package/dist/modules/accounts/actions/account-management.action.mjs.map +1 -1
  125. package/dist/modules/accounts/actions/find-current-account.action.mjs.map +1 -1
  126. package/dist/modules/accounts/actions/get-account-token.action.mjs.map +1 -1
  127. package/dist/modules/accounts/actions/list-currencies.action.mjs.map +1 -1
  128. package/dist/modules/accounts/actions/list-timezones.action.mjs.map +1 -1
  129. package/dist/modules/accounts/hooks/current-account.hook.mjs.map +1 -1
  130. package/dist/modules/accounts/hooks/use-account-token.hook.mjs.map +1 -1
  131. package/dist/modules/accounts/hooks/use-currency-formatter.hook.mjs.map +1 -1
  132. package/dist/modules/accounts/hooks/useAccountManagement.mjs.map +1 -1
  133. package/dist/modules/accounts/hooks/useCurrencies.mjs.map +1 -1
  134. package/dist/modules/accounts/hooks/useTimezones.mjs.map +1 -1
  135. package/dist/modules/accounts/hooks/useViaCep.mjs.map +1 -1
  136. package/dist/modules/accounts/services/account-token.service.mjs.map +1 -1
  137. package/dist/modules/accounts/services/account.service.mjs.map +1 -1
  138. package/dist/modules/auth/actions/social-google-login.action.mjs.map +1 -1
  139. package/dist/modules/auth/actions/social-google-onboarding.action.mjs.map +1 -1
  140. package/dist/modules/auth/actions/unlink-google.action.mjs.map +1 -1
  141. package/dist/modules/auth/actions/validate-session.action.mjs.map +1 -1
  142. package/dist/modules/auth/actions/verify-two-factor.action.mjs.map +1 -1
  143. package/dist/modules/auth/hooks/login.hook.mjs.map +1 -1
  144. package/dist/modules/auth/hooks/logout.hook.mjs.map +1 -1
  145. package/dist/modules/auth/hooks/register.hook.mjs.map +1 -1
  146. package/dist/modules/auth/hooks/social-google-login.hook.mjs.map +1 -1
  147. package/dist/modules/auth/hooks/social-google-onboarding.hook.mjs.map +1 -1
  148. package/dist/modules/auth/hooks/unlink-google.hook.mjs.map +1 -1
  149. package/dist/modules/auth/hooks/useManagementPermissions.mjs.map +1 -1
  150. package/dist/modules/auth/hooks/useUserQuery.mjs.map +1 -1
  151. package/dist/modules/auth/utils/assert-management-permission.mjs.map +1 -1
  152. package/dist/modules/auth/utils/assert-management-subscription.mjs.map +1 -1
  153. package/dist/modules/auth/utils/assert-paid-subscription.mjs.map +1 -1
  154. package/dist/modules/auth/utils/assert-subscription-addon.mjs.map +1 -1
  155. package/dist/modules/auth/utils/build-wl-override.mjs.map +1 -1
  156. package/dist/modules/auth/utils/require-token-not-expired.mjs.map +1 -1
  157. package/dist/modules/auth/utils/require-valid-session.mjs.map +1 -1
  158. package/dist/modules/cards/actions/create-card.action.mjs.map +1 -1
  159. package/dist/modules/cards/actions/create-setup-intent.action.mjs.map +1 -1
  160. package/dist/modules/cards/actions/delete-card.action.mjs.map +1 -1
  161. package/dist/modules/cards/actions/set-default-card.action.mjs.map +1 -1
  162. package/dist/modules/cards/handlers/find-card-by-id.handler.mjs.map +1 -1
  163. package/dist/modules/cards/handlers/list-cards.handler.mjs.map +1 -1
  164. package/dist/modules/cards/hooks/card-by-id.hook.mjs.map +1 -1
  165. package/dist/modules/cards/hooks/cards.hook.mjs.map +1 -1
  166. package/dist/modules/cards/hooks/create-card.hook.mjs.map +1 -1
  167. package/dist/modules/cards/hooks/create-setup-intent.hook.mjs.map +1 -1
  168. package/dist/modules/cards/hooks/delete-card.hook.mjs.map +1 -1
  169. package/dist/modules/cards/hooks/delete-confirmation.hook.mjs.map +1 -1
  170. package/dist/modules/cards/hooks/handle-delete-card.hook.mjs.map +1 -1
  171. package/dist/modules/cards/hooks/set-default-card.hook.mjs.map +1 -1
  172. package/dist/modules/cards/services/cards.service.mjs.map +1 -1
  173. package/dist/modules/cards/types.mjs.map +1 -1
  174. package/dist/modules/charges/actions/charge-action.action.mjs.map +1 -1
  175. package/dist/modules/charges/handlers/find-charge-by-id.handler.mjs.map +1 -1
  176. package/dist/modules/charges/handlers/list-charges.handler.mjs.map +1 -1
  177. package/dist/modules/charges/hooks/charge-action.hook.mjs.map +1 -1
  178. package/dist/modules/charges/hooks/charge-by-id.hook.mjs.map +1 -1
  179. package/dist/modules/charges/hooks/charges.hook.mjs.map +1 -1
  180. package/dist/modules/charges/services/charges.service.mjs.map +1 -1
  181. package/dist/modules/charges/types/charge.type.mjs.map +1 -1
  182. package/dist/modules/ia-credits/handlers/list-ia-credits.handler.mjs.map +1 -1
  183. package/dist/modules/ia-credits/hooks/ia-credits.hook.mjs.map +1 -1
  184. package/dist/modules/images/actions/process-image.action.mjs.map +1 -1
  185. package/dist/modules/images/constants/image.constants.mjs.map +1 -1
  186. package/dist/modules/images/hooks/use-image-upload.hook.mjs.map +1 -1
  187. package/dist/modules/images/services/image-processing.service.mjs.map +1 -1
  188. package/dist/modules/images/utils/base64.mjs.map +1 -1
  189. package/dist/modules/images/utils/compress-image.mjs.map +1 -1
  190. package/dist/modules/images/utils/crop-image.mjs.map +1 -1
  191. package/dist/modules/images/utils/validate-image.mjs.map +1 -1
  192. package/dist/modules/pages/constants/query-keys.constants.mjs.map +1 -1
  193. package/dist/modules/pages/handlers/count-pages.handler.mjs.map +1 -1
  194. package/dist/modules/pages/hooks/count-pages.hook.mjs.map +1 -1
  195. package/dist/modules/pages/services/pages.service.mjs.map +1 -1
  196. package/dist/modules/plans/handlers/find-plan-by-id.handler.mjs.map +1 -1
  197. package/dist/modules/plans/handlers/list-plans.handler.mjs.map +1 -1
  198. package/dist/modules/plans/hooks/list-plans.hook.mjs.map +1 -1
  199. package/dist/modules/plans/hooks/use-has-plan-addon.hook.mjs.map +1 -1
  200. package/dist/modules/plans/hooks/use-plan-by-id.hook.mjs.map +1 -1
  201. package/dist/modules/plans/services/plans.service.mjs.map +1 -1
  202. package/dist/modules/plans/types/plan.type.mjs.map +1 -1
  203. package/dist/modules/plans/utils/map-api-plan-to-ui.mjs.map +1 -1
  204. package/dist/modules/projects/actions/add-project-user.action.mjs.map +1 -1
  205. package/dist/modules/projects/actions/create-project.action.mjs.map +1 -1
  206. package/dist/modules/projects/actions/delete-project.action.mjs.map +1 -1
  207. package/dist/modules/projects/actions/find-project.action.mjs.map +1 -1
  208. package/dist/modules/projects/actions/list-project-users.action.mjs.map +1 -1
  209. package/dist/modules/projects/actions/list-projects.action.mjs.map +1 -1
  210. package/dist/modules/projects/actions/remove-project-user.action.mjs.map +1 -1
  211. package/dist/modules/projects/actions/update-project.action.mjs.map +1 -1
  212. package/dist/modules/projects/handlers/find-project.handler.mjs.map +1 -1
  213. package/dist/modules/projects/handlers/list-all-account-users.handler.mjs.map +1 -1
  214. package/dist/modules/projects/handlers/list-available-users.handler.mjs.map +1 -1
  215. package/dist/modules/projects/handlers/list-project-users.handler.mjs.map +1 -1
  216. package/dist/modules/projects/handlers/list-projects.handler.mjs.map +1 -1
  217. package/dist/modules/projects/hooks/add-project-user.hook.mjs.map +1 -1
  218. package/dist/modules/projects/hooks/create-project.hook.mjs.map +1 -1
  219. package/dist/modules/projects/hooks/delete-project.hook.mjs.map +1 -1
  220. package/dist/modules/projects/hooks/find-project.hook.mjs.map +1 -1
  221. package/dist/modules/projects/hooks/list-all-account-users.hook.mjs.map +1 -1
  222. package/dist/modules/projects/hooks/list-available-users.hook.mjs.map +1 -1
  223. package/dist/modules/projects/hooks/list-infinite-projects.hook.mjs.map +1 -1
  224. package/dist/modules/projects/hooks/list-project-users.hook.mjs.map +1 -1
  225. package/dist/modules/projects/hooks/list-projects.hook.mjs.map +1 -1
  226. package/dist/modules/projects/hooks/remove-project-user.hook.mjs.map +1 -1
  227. package/dist/modules/projects/hooks/update-project.hook.mjs.map +1 -1
  228. package/dist/modules/projects/services/projects.service.mjs.map +1 -1
  229. package/dist/modules/subscriptions/actions/calculate-subscription.action.mjs.map +1 -1
  230. package/dist/modules/subscriptions/actions/list-subscriptions.action.mjs.map +1 -1
  231. package/dist/modules/subscriptions/actions/update-subscription-payment.action.mjs.map +1 -1
  232. package/dist/modules/subscriptions/actions/update-subscription-plan.action.mjs.map +1 -1
  233. package/dist/modules/subscriptions/constants/query-keys.constants.mjs.map +1 -1
  234. package/dist/modules/subscriptions/constants/subscription.constants.mjs.map +1 -1
  235. package/dist/modules/subscriptions/handlers/list-subscriptions.handler.mjs.map +1 -1
  236. package/dist/modules/subscriptions/hooks/calculate-subscription.hook.mjs.map +1 -1
  237. package/dist/modules/subscriptions/hooks/find-active-subscription.hook.mjs.map +1 -1
  238. package/dist/modules/subscriptions/hooks/list-subscriptions.hook.mjs.map +1 -1
  239. package/dist/modules/subscriptions/hooks/update-subscription-payment.hook.mjs.map +1 -1
  240. package/dist/modules/subscriptions/hooks/update-subscription-plan.hook.mjs +2 -0
  241. package/dist/modules/subscriptions/hooks/update-subscription-plan.hook.mjs.map +1 -1
  242. package/dist/modules/subscriptions/hooks/use-cancelled-subscription-guard.mjs.map +1 -1
  243. package/dist/modules/subscriptions/types/calculate-subscription.type.mjs.map +1 -1
  244. package/dist/modules/subscriptions/types/pix-pending.type.mjs.map +1 -1
  245. package/dist/modules/subscriptions/utils/build-plan-extras.mjs.map +1 -1
  246. package/dist/modules/subscriptions/utils/get-subscription-cancellation-state.mjs.map +1 -1
  247. package/dist/modules/subscriptions/utils/get-subscription-expiry-date.mjs.map +1 -1
  248. package/dist/modules/subscriptions/utils/has-subscription-expired.mjs.map +1 -1
  249. package/dist/modules/subscriptions/utils/periodicity.mjs.map +1 -1
  250. package/dist/modules/subscriptions/utils/resolve-plan-extras-prices.mjs.map +1 -1
  251. package/dist/modules/users/action/find-user-by-id.action.mjs.map +1 -1
  252. package/dist/modules/users/action/mark-all-messages-as-read.action.mjs.map +1 -1
  253. package/dist/modules/users/action/mark-message-as-read.action.mjs.map +1 -1
  254. package/dist/modules/users/handlers/list-messages.handler.mjs.map +1 -1
  255. package/dist/modules/users/hooks/messages.hook.mjs.map +1 -1
  256. package/dist/modules/users/services/messages.service.mjs.map +1 -1
  257. package/dist/modules/whitelabel/actions/find-whitelabel.action.mjs.map +1 -1
  258. package/dist/modules/whitelabel/actions/revalidate-whitelabel.action.mjs.map +1 -1
  259. package/dist/modules/whitelabel/utils/normalize-hostname.mjs.map +1 -1
  260. package/dist/providers/auth.provider.mjs.map +1 -1
  261. package/dist/providers/navigation.provider.mjs.map +1 -1
  262. package/dist/providers/whitelabel.provider.mjs.map +1 -1
  263. package/dist/route.mjs.map +1 -1
  264. package/dist/store/useAccountModals.mjs.map +1 -1
  265. package/dist/store/useBuyCreditsModal.mjs.map +1 -1
  266. package/dist/store/useCreditsDisabledModal.mjs.map +1 -1
  267. package/dist/store/useDesktopSidebarStore.mjs.map +1 -1
  268. package/dist/store/useHexaPromoModal.mjs.map +1 -1
  269. package/dist/store/useMdSidebarStore.mjs.map +1 -1
  270. package/dist/store/usePaidPlanRequiredModal.mjs.map +1 -1
  271. package/dist/utils/constants/br-states.mjs.map +1 -1
  272. package/dist/utils/cookies/hexa-promo.mjs.map +1 -1
  273. package/dist/utils/countries.mjs.map +1 -1
  274. package/dist/utils/format/currency.mjs.map +1 -1
  275. package/dist/utils/intl/cookie-domain.mjs.map +1 -1
  276. package/dist/utils/intl/locale-cookie.mjs.map +1 -1
  277. package/dist/utils/next-navigation.mjs.map +1 -1
  278. package/dist/utils/redirect.mjs.map +1 -1
  279. package/dist/utils/safeMutationAction.mjs.map +1 -1
  280. package/dist/utils/safeServerAction.mjs.map +1 -1
  281. package/dist/utils/withAction.mjs.map +1 -1
  282. package/package.json +115 -115
  283. package/src/components/account/ConfigurationsMyAccountModal.tsx +179 -179
  284. package/src/components/account/ConfirmDeleteAccountModal.tsx +110 -110
  285. package/src/components/account/ConfirmGlobalPreferencesModal.tsx +68 -68
  286. package/src/components/account/DeleteAccountModal.tsx +160 -160
  287. package/src/components/account/DisableTwoFactorAuthModal.tsx +92 -92
  288. package/src/components/account/IsntPossibleDeleteAccountModal.tsx +51 -51
  289. package/src/components/account/TwoFactorAuthModal.tsx +220 -220
  290. package/src/components/account/hooks/useChangePhoneForm.tsx +113 -113
  291. package/src/components/account/hooks/useTwoFactorAuthForm.tsx +116 -116
  292. package/src/components/account/sections/ChangeEmailModal.tsx +239 -239
  293. package/src/components/account/sections/ChangePasswordSection.tsx +68 -68
  294. package/src/components/account/sections/ChangePhoneModal.tsx +273 -273
  295. package/src/components/account/sections/MyProfileSection.tsx +276 -276
  296. package/src/components/account/sections/PreferencesSection.tsx +278 -278
  297. package/src/components/account/sections/SecuritySection.tsx +102 -102
  298. package/src/components/account/sections/TokenSection.tsx +85 -85
  299. package/src/components/embeds/ClarityEmbed.tsx +70 -70
  300. package/src/components/embeds/CrispEmbed.tsx +195 -195
  301. package/src/components/embeds/EmbedWidgets.tsx +62 -62
  302. package/src/components/embeds/FrillEmbed.tsx +146 -146
  303. package/src/components/layouts/AppMobileNavBar.tsx +214 -214
  304. package/src/components/layouts/AppNavBar.tsx +40 -40
  305. package/src/components/layouts/MdSideBarNavigation.tsx +56 -56
  306. package/src/components/layouts/NavBar.tsx +228 -228
  307. package/src/components/layouts/NotificationsPopover.tsx +120 -120
  308. package/src/components/layouts/ProfilePopover.tsx +191 -191
  309. package/src/components/layouts/SideBarNavigation.tsx +65 -65
  310. package/src/components/layouts/UsersSelectorPopover.tsx +236 -236
  311. package/src/components/layouts/WhitelabelCodes.tsx +59 -59
  312. package/src/components/modals/BuyCreditsModal.tsx +390 -390
  313. package/src/components/modals/CreditsDisabledModal.tsx +62 -62
  314. package/src/components/modals/HexaPromoModal.tsx +212 -212
  315. package/src/components/modals/HexaPromoModalGate.tsx +93 -80
  316. package/src/components/modals/Modals.tsx +25 -25
  317. package/src/components/modals/PaidPlanRequiredModal.tsx +60 -60
  318. package/src/components/modals/cards/AddCardModal.tsx +420 -420
  319. package/src/components/modals/cards/CannotDeleteCardModal.tsx +124 -124
  320. package/src/components/modals/cards/CardFormFields.tsx +363 -363
  321. package/src/components/modals/cards/DeleteCardModal.tsx +136 -136
  322. package/src/components/navigation/CancelledSubscriptionBanner.tsx +62 -62
  323. package/src/components/navigation/NavItemsContext.ts +20 -20
  324. package/src/components/navigation/OverdueInvoiceBanner.tsx +51 -51
  325. package/src/components/navigation/PendingCancellationBanner.tsx +60 -60
  326. package/src/components/navigation/ProjectSelectorPopover.tsx +180 -180
  327. package/src/components/navigation/SubscriptionBanner.tsx +94 -94
  328. package/src/components/navigation/TrialBanner.tsx +54 -54
  329. package/src/components/navigation/UpcomingInvoiceBanner.tsx +55 -55
  330. package/src/components/navigation/shells/TabsMobileShell.tsx +74 -74
  331. package/src/components/navigation/subcomponents/BottomLinks.tsx +85 -85
  332. package/src/components/navigation/subcomponents/ProjectSelector.tsx +184 -184
  333. package/src/components/pages/NotFoundPage.tsx +75 -75
  334. package/src/components/pages/notifications/Notifications.tsx +190 -190
  335. package/src/components/ui/buttons/Button.tsx +77 -77
  336. package/src/components/ui/buttons/CancelButton.tsx +14 -14
  337. package/src/components/ui/buttons/CopyButton.tsx +59 -59
  338. package/src/components/ui/data-display/Accordion.tsx +81 -81
  339. package/src/components/ui/data-display/Badge.tsx +47 -47
  340. package/src/components/ui/data-display/Card.tsx +93 -93
  341. package/src/components/ui/data-display/CardBrandIcons.tsx +336 -336
  342. package/src/components/ui/data-display/CardItem.tsx +135 -135
  343. package/src/components/ui/data-display/Pagination.tsx +126 -126
  344. package/src/components/ui/data-display/PaymentInfoCard.tsx +193 -193
  345. package/src/components/ui/data-display/ScrollArea.tsx +59 -59
  346. package/src/components/ui/data-display/Separator.tsx +29 -29
  347. package/src/components/ui/data-display/Table.tsx +117 -117
  348. package/src/components/ui/data-display/Tabs.tsx +67 -67
  349. package/src/components/ui/feedback/CircularProgress.tsx +79 -79
  350. package/src/components/ui/feedback/DefaultCircularProgress.tsx +67 -67
  351. package/src/components/ui/feedback/LoadingOverlay.tsx +30 -30
  352. package/src/components/ui/feedback/Progress.tsx +40 -40
  353. package/src/components/ui/feedback/Skeleton.tsx +5 -5
  354. package/src/components/ui/feedback/Toast.tsx +104 -104
  355. package/src/components/ui/form/Calendar.tsx +228 -228
  356. package/src/components/ui/form/Checkbox.tsx +31 -31
  357. package/src/components/ui/form/ComboboxField.tsx +159 -159
  358. package/src/components/ui/form/DatePicker.tsx +100 -100
  359. package/src/components/ui/form/DateRangePicker.tsx +111 -111
  360. package/src/components/ui/form/FormField.tsx +133 -133
  361. package/src/components/ui/form/Input.tsx +20 -20
  362. package/src/components/ui/form/InputOtp.tsx +80 -80
  363. package/src/components/ui/form/PhoneInput.tsx +210 -210
  364. package/src/components/ui/form/RadioGroup.tsx +45 -45
  365. package/src/components/ui/form/Select.tsx +200 -200
  366. package/src/components/ui/form/Switch.tsx +32 -32
  367. package/src/components/ui/form/Textarea.tsx +19 -19
  368. package/src/components/ui/overlay/Command.tsx +185 -185
  369. package/src/components/ui/overlay/Dialog.tsx +153 -153
  370. package/src/components/ui/overlay/Popover.tsx +49 -49
  371. package/src/components/ui/overlay/Sheet.tsx +170 -170
  372. package/src/components/ui/overlay/Tooltip.tsx +62 -62
  373. package/src/components/widgets/ImageUpload/ImageCropModal.tsx +392 -392
  374. package/src/components/widgets/ImageUpload/ImageTooSmallModal.tsx +62 -62
  375. package/src/components/widgets/ImageUpload/ImageUpload.tsx +131 -131
  376. package/src/components/widgets/ImageUpload/index.ts +3 -3
  377. package/src/components/widgets/notifications/NotificationCard.tsx +73 -73
  378. package/src/handlers.ts +22 -22
  379. package/src/hooks/copy-to-clipboard.hook.tsx +67 -67
  380. package/src/hooks/useAuthQueryKey.ts +32 -32
  381. package/src/hooks/useBrandLoadingIcon.tsx +18 -18
  382. package/src/hooks/useRouter.ts +38 -38
  383. package/src/http.ts +1 -1
  384. package/src/i18n/config.ts +17 -17
  385. package/src/i18n/country-language.ts +60 -60
  386. package/src/i18n/messages/en-us.ts +519 -519
  387. package/src/i18n/messages/es-es.ts +520 -520
  388. package/src/i18n/messages/index.ts +24 -24
  389. package/src/i18n/messages/pt-br.ts +543 -543
  390. package/src/i18n/normalize.ts +15 -15
  391. package/src/i18n/resolve-locale.ts +77 -77
  392. package/src/i18n.ts +10 -10
  393. package/src/index.ts +587 -587
  394. package/src/infra/http/api-fetch.ts +39 -39
  395. package/src/infra/route/parse-id.ts +9 -9
  396. package/src/infra/route/parse-numeric.ts +16 -16
  397. package/src/infra/route/safe-route-handler.ts +16 -16
  398. package/src/infra/route/search-params.ts +9 -9
  399. package/src/infra/utils/array.ts +167 -167
  400. package/src/infra/utils/date.ts +59 -59
  401. package/src/middleware.ts +4 -4
  402. package/src/modules/accounts/actions/account-management.action.ts +109 -109
  403. package/src/modules/accounts/actions/find-current-account.action.ts +9 -9
  404. package/src/modules/accounts/actions/get-account-token.action.ts +8 -8
  405. package/src/modules/accounts/actions/list-currencies.action.ts +8 -8
  406. package/src/modules/accounts/actions/list-timezones.action.ts +8 -8
  407. package/src/modules/accounts/hooks/current-account.hook.tsx +26 -26
  408. package/src/modules/accounts/hooks/use-account-token.hook.tsx +14 -14
  409. package/src/modules/accounts/hooks/use-currency-formatter.hook.tsx +32 -32
  410. package/src/modules/accounts/hooks/useAccountManagement.ts +95 -95
  411. package/src/modules/accounts/hooks/useCurrencies.ts +18 -18
  412. package/src/modules/accounts/hooks/useTimezones.ts +18 -18
  413. package/src/modules/accounts/hooks/useViaCep.ts +25 -25
  414. package/src/modules/accounts/services/account-token.service.ts +52 -52
  415. package/src/modules/accounts/services/account.service.ts +243 -243
  416. package/src/modules/accounts/types.ts +230 -230
  417. package/src/modules/auth/actions/social-google-login.action.ts +12 -12
  418. package/src/modules/auth/actions/social-google-onboarding.action.ts +13 -13
  419. package/src/modules/auth/actions/unlink-google.action.ts +8 -8
  420. package/src/modules/auth/actions/validate-session.action.ts +70 -70
  421. package/src/modules/auth/actions/verify-two-factor.action.ts +19 -19
  422. package/src/modules/auth/hooks/login.hook.tsx +13 -13
  423. package/src/modules/auth/hooks/logout.hook.tsx +11 -11
  424. package/src/modules/auth/hooks/register.hook.tsx +11 -11
  425. package/src/modules/auth/hooks/social-google-login.hook.tsx +13 -13
  426. package/src/modules/auth/hooks/social-google-onboarding.hook.tsx +13 -13
  427. package/src/modules/auth/hooks/unlink-google.hook.tsx +13 -13
  428. package/src/modules/auth/hooks/useManagementPermissions.ts +52 -52
  429. package/src/modules/auth/hooks/useUserQuery.ts +103 -103
  430. package/src/modules/auth/types/management-permission.type.ts +14 -14
  431. package/src/modules/auth/utils/assert-management-permission.ts +56 -56
  432. package/src/modules/auth/utils/assert-management-subscription.ts +38 -38
  433. package/src/modules/auth/utils/assert-paid-subscription.ts +47 -47
  434. package/src/modules/auth/utils/assert-subscription-addon.ts +42 -42
  435. package/src/modules/auth/utils/build-wl-override.ts +43 -43
  436. package/src/modules/auth/utils/require-token-not-expired.ts +53 -53
  437. package/src/modules/auth/utils/require-valid-session.ts +35 -35
  438. package/src/modules/cards/actions/create-card.action.ts +9 -9
  439. package/src/modules/cards/actions/create-setup-intent.action.ts +8 -8
  440. package/src/modules/cards/actions/delete-card.action.ts +8 -8
  441. package/src/modules/cards/actions/set-default-card.action.ts +8 -8
  442. package/src/modules/cards/handlers/find-card-by-id.handler.ts +15 -15
  443. package/src/modules/cards/handlers/list-cards.handler.ts +10 -10
  444. package/src/modules/cards/hooks/card-by-id.hook.ts +17 -17
  445. package/src/modules/cards/hooks/cards.hook.ts +22 -22
  446. package/src/modules/cards/hooks/create-card.hook.ts +30 -30
  447. package/src/modules/cards/hooks/create-setup-intent.hook.ts +11 -11
  448. package/src/modules/cards/hooks/delete-card.hook.ts +52 -52
  449. package/src/modules/cards/hooks/delete-confirmation.hook.ts +40 -40
  450. package/src/modules/cards/hooks/handle-delete-card.hook.ts +47 -47
  451. package/src/modules/cards/hooks/set-default-card.hook.ts +55 -55
  452. package/src/modules/cards/services/cards.service.ts +136 -136
  453. package/src/modules/cards/types.ts +52 -52
  454. package/src/modules/charges/actions/charge-action.action.ts +13 -13
  455. package/src/modules/charges/handlers/find-charge-by-id.handler.ts +14 -14
  456. package/src/modules/charges/handlers/list-charges.handler.ts +15 -15
  457. package/src/modules/charges/hooks/charge-action.hook.ts +24 -24
  458. package/src/modules/charges/hooks/charge-by-id.hook.ts +19 -19
  459. package/src/modules/charges/hooks/charges.hook.ts +19 -19
  460. package/src/modules/charges/services/charges.service.ts +63 -63
  461. package/src/modules/charges/types/charge.type.ts +68 -68
  462. package/src/modules/ia-credits/handlers/list-ia-credits.handler.ts +14 -14
  463. package/src/modules/ia-credits/hooks/ia-credits.hook.ts +103 -103
  464. package/src/modules/images/actions/process-image.action.ts +40 -40
  465. package/src/modules/images/constants/image.constants.ts +11 -11
  466. package/src/modules/images/hooks/use-image-upload.hook.ts +153 -153
  467. package/src/modules/images/services/image-processing.service.ts +75 -75
  468. package/src/modules/images/types/image.type.ts +54 -54
  469. package/src/modules/images/utils/base64.ts +26 -26
  470. package/src/modules/images/utils/compress-image.ts +20 -20
  471. package/src/modules/images/utils/crop-image.ts +68 -68
  472. package/src/modules/images/utils/validate-image.ts +86 -86
  473. package/src/modules/pages/constants/query-keys.constants.ts +1 -1
  474. package/src/modules/pages/handlers/count-pages.handler.ts +12 -12
  475. package/src/modules/pages/hooks/count-pages.hook.ts +21 -21
  476. package/src/modules/pages/services/pages.service.ts +27 -27
  477. package/src/modules/plans/handlers/find-plan-by-id.handler.ts +14 -14
  478. package/src/modules/plans/handlers/list-plans.handler.ts +22 -22
  479. package/src/modules/plans/hooks/list-plans.hook.ts +23 -23
  480. package/src/modules/plans/hooks/use-has-plan-addon.hook.ts +14 -14
  481. package/src/modules/plans/hooks/use-plan-by-id.hook.ts +39 -39
  482. package/src/modules/plans/services/plans.service.ts +136 -136
  483. package/src/modules/plans/types/plan.type.ts +79 -79
  484. package/src/modules/plans/utils/map-api-plan-to-ui.ts +167 -167
  485. package/src/modules/projects/actions/add-project-user.action.ts +9 -9
  486. package/src/modules/projects/actions/create-project.action.ts +9 -9
  487. package/src/modules/projects/actions/delete-project.action.ts +8 -8
  488. package/src/modules/projects/actions/find-project.action.ts +8 -8
  489. package/src/modules/projects/actions/list-project-users.action.ts +9 -9
  490. package/src/modules/projects/actions/list-projects.action.ts +16 -16
  491. package/src/modules/projects/actions/remove-project-user.action.ts +9 -9
  492. package/src/modules/projects/actions/update-project.action.ts +9 -9
  493. package/src/modules/projects/handlers/find-project.handler.ts +15 -15
  494. package/src/modules/projects/handlers/list-all-account-users.handler.ts +23 -23
  495. package/src/modules/projects/handlers/list-available-users.handler.ts +26 -26
  496. package/src/modules/projects/handlers/list-project-users.handler.ts +26 -26
  497. package/src/modules/projects/handlers/list-projects.handler.ts +23 -23
  498. package/src/modules/projects/hooks/add-project-user.hook.ts +72 -72
  499. package/src/modules/projects/hooks/create-project.hook.ts +120 -120
  500. package/src/modules/projects/hooks/delete-project.hook.ts +58 -58
  501. package/src/modules/projects/hooks/find-project.hook.ts +18 -18
  502. package/src/modules/projects/hooks/list-all-account-users.hook.ts +40 -40
  503. package/src/modules/projects/hooks/list-available-users.hook.ts +39 -39
  504. package/src/modules/projects/hooks/list-infinite-projects.hook.ts +44 -44
  505. package/src/modules/projects/hooks/list-project-users.hook.ts +39 -39
  506. package/src/modules/projects/hooks/list-projects.hook.ts +23 -23
  507. package/src/modules/projects/hooks/remove-project-user.hook.ts +72 -72
  508. package/src/modules/projects/hooks/update-project.hook.ts +86 -86
  509. package/src/modules/projects/services/projects.service.ts +156 -156
  510. package/src/modules/subscriptions/actions/calculate-subscription.action.ts +9 -9
  511. package/src/modules/subscriptions/actions/list-subscriptions.action.ts +9 -9
  512. package/src/modules/subscriptions/actions/update-subscription-payment.action.ts +13 -13
  513. package/src/modules/subscriptions/actions/update-subscription-plan.action.ts +14 -14
  514. package/src/modules/subscriptions/constants/query-keys.constants.ts +3 -3
  515. package/src/modules/subscriptions/constants/subscription.constants.ts +1 -1
  516. package/src/modules/subscriptions/handlers/list-subscriptions.handler.ts +17 -17
  517. package/src/modules/subscriptions/hooks/calculate-subscription.hook.ts +13 -13
  518. package/src/modules/subscriptions/hooks/find-active-subscription.hook.ts +22 -22
  519. package/src/modules/subscriptions/hooks/list-subscriptions.hook.ts +22 -22
  520. package/src/modules/subscriptions/hooks/update-subscription-payment.hook.ts +25 -25
  521. package/src/modules/subscriptions/hooks/update-subscription-plan.hook.ts +31 -28
  522. package/src/modules/subscriptions/hooks/use-cancelled-subscription-guard.ts +44 -44
  523. package/src/modules/subscriptions/types/billing-period.type.ts +1 -1
  524. package/src/modules/subscriptions/types/calculate-subscription.type.ts +116 -116
  525. package/src/modules/subscriptions/types/pix-pending.type.ts +38 -38
  526. package/src/modules/subscriptions/utils/build-plan-extras.ts +56 -56
  527. package/src/modules/subscriptions/utils/get-subscription-cancellation-state.ts +37 -37
  528. package/src/modules/subscriptions/utils/get-subscription-expiry-date.ts +33 -33
  529. package/src/modules/subscriptions/utils/has-subscription-expired.ts +11 -11
  530. package/src/modules/subscriptions/utils/periodicity.ts +79 -79
  531. package/src/modules/subscriptions/utils/resolve-plan-extras-prices.ts +23 -23
  532. package/src/modules/users/action/find-user-by-id.action.ts +8 -8
  533. package/src/modules/users/action/mark-all-messages-as-read.action.ts +8 -8
  534. package/src/modules/users/action/mark-message-as-read.action.ts +8 -8
  535. package/src/modules/users/handlers/list-messages.handler.ts +39 -39
  536. package/src/modules/users/hooks/messages.hook.ts +69 -69
  537. package/src/modules/users/services/messages.service.ts +49 -49
  538. package/src/modules/whitelabel/actions/find-whitelabel.action.ts +23 -23
  539. package/src/modules/whitelabel/actions/revalidate-whitelabel.action.ts +19 -19
  540. package/src/modules/whitelabel/schema.ts +84 -84
  541. package/src/modules/whitelabel/utils/normalize-hostname.ts +26 -26
  542. package/src/providers/auth.provider.tsx +267 -267
  543. package/src/providers/navigation.provider.tsx +99 -99
  544. package/src/providers/whitelabel.provider.tsx +90 -90
  545. package/src/route.ts +4 -4
  546. package/src/store/useAccountModals.ts +85 -85
  547. package/src/store/useBuyCreditsModal.ts +21 -21
  548. package/src/store/useCreditsDisabledModal.ts +11 -11
  549. package/src/store/useDesktopSidebarStore.ts +47 -47
  550. package/src/store/useHexaPromoModal.ts +13 -13
  551. package/src/store/useMdSidebarStore.ts +34 -34
  552. package/src/store/usePaidPlanRequiredModal.ts +19 -19
  553. package/src/utils/constants/br-states.ts +29 -29
  554. package/src/utils/cookies/hexa-promo.ts +114 -114
  555. package/src/utils/countries.ts +224 -224
  556. package/src/utils/format/currency.ts +70 -70
  557. package/src/utils/intl/cookie-domain.ts +29 -29
  558. package/src/utils/intl/locale-cookie.ts +18 -18
  559. package/src/utils/next-navigation.ts +7 -7
  560. package/src/utils/redirect.ts +78 -78
  561. package/src/utils/safeMutationAction.ts +24 -24
  562. package/src/utils/safeServerAction.ts +21 -21
  563. 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
+ }