@greatapps/common 1.1.694 → 1.1.697

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