@greatapps/common 1.1.697 → 1.1.699

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