@greatapps/common 1.1.699 → 1.1.700

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