@stackcraftmx/calcita 0.32.1 → 0.47.0

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 (338) hide show
  1. package/README.md +263 -2
  2. package/cli/packageVersions.js +12 -3
  3. package/cli/projectFiles.js +5 -2
  4. package/cli/templates/module/__Name__Page.test.jsx.tpl +24 -0
  5. package/cli/templates/project/README.md.tpl +14 -1
  6. package/cli/templates/project/src/app/appRouter.jsx.tpl +5 -2
  7. package/cli/templates/project/src/core/accountConnector.js.tpl +4 -2
  8. package/cli/templates/project/src/modules/auth/SignInPage.test.jsx.tpl +20 -0
  9. package/cli/templates/project/src/modules/home/HomePage.test.jsx.tpl +16 -0
  10. package/cli/templates/project/src/testing/browserGaps.js.tpl +70 -0
  11. package/cli/templates/project/src/testing/openScreen.jsx.tpl +58 -0
  12. package/cli/templates/project/src/testing/setup.js.tpl +25 -0
  13. package/cli/templates/project/vite.config.js.tpl +12 -0
  14. package/dist/DataTable/GoToPage.js +69 -13
  15. package/dist/DataTable/GoToPage.js.map +1 -1
  16. package/dist/DataTable/ServerTable.js +2 -0
  17. package/dist/DataTable/ServerTable.js.map +1 -1
  18. package/dist/DataTable/ServerTableFilterDrawer.js +52 -0
  19. package/dist/DataTable/ServerTableFilterDrawer.js.map +1 -0
  20. package/dist/DataTable/filterContext.js.map +1 -1
  21. package/dist/DataTable/goToPageOptions.js +17 -0
  22. package/dist/DataTable/goToPageOptions.js.map +1 -0
  23. package/dist/date-pickers.js +28 -2
  24. package/dist/date-pickers.js.map +1 -1
  25. package/dist/datePickers/DateInput.js +15 -34
  26. package/dist/datePickers/DateInput.js.map +1 -1
  27. package/dist/datePickers/DateTimeInput.js +75 -0
  28. package/dist/datePickers/DateTimeInput.js.map +1 -0
  29. package/dist/datePickers/FormDateTimeField.js +12 -0
  30. package/dist/datePickers/FormDateTimeField.js.map +1 -0
  31. package/dist/datePickers/FormMonthField.js +12 -0
  32. package/dist/datePickers/FormMonthField.js.map +1 -0
  33. package/dist/datePickers/FormTimeField.js +12 -0
  34. package/dist/datePickers/FormTimeField.js.map +1 -0
  35. package/dist/datePickers/MonthInput.js +58 -0
  36. package/dist/datePickers/MonthInput.js.map +1 -0
  37. package/dist/datePickers/PickerFrame.js +27 -0
  38. package/dist/datePickers/PickerFrame.js.map +1 -0
  39. package/dist/datePickers/TimeInput.js +55 -0
  40. package/dist/datePickers/TimeInput.js.map +1 -0
  41. package/dist/datePickers/dateTimeRules.js +24 -0
  42. package/dist/datePickers/dateTimeRules.js.map +1 -0
  43. package/dist/datePickers/pickerValues.js +106 -0
  44. package/dist/datePickers/pickerValues.js.map +1 -0
  45. package/dist/datePickers/useCurrentMinute.js +28 -0
  46. package/dist/datePickers/useCurrentMinute.js.map +1 -0
  47. package/dist/datePickers/usePickerField.js +22 -0
  48. package/dist/datePickers/usePickerField.js.map +1 -0
  49. package/dist/dictionaries/dictionaries.js +3 -1
  50. package/dist/dictionaries/dictionaries.js.map +1 -1
  51. package/dist/forms/FormAttachmentsField.js +12 -0
  52. package/dist/forms/FormAttachmentsField.js.map +1 -0
  53. package/dist/forms/FormCheckboxGroupField.js +12 -0
  54. package/dist/forms/FormCheckboxGroupField.js.map +1 -0
  55. package/dist/forms/FormFileField.js +12 -0
  56. package/dist/forms/FormFileField.js.map +1 -0
  57. package/dist/forms/FormFileUploadField.js +12 -0
  58. package/dist/forms/FormFileUploadField.js.map +1 -0
  59. package/dist/forms/FormImageField.js +12 -0
  60. package/dist/forms/FormImageField.js.map +1 -0
  61. package/dist/forms/FormMaskedField.js +12 -0
  62. package/dist/forms/FormMaskedField.js.map +1 -0
  63. package/dist/forms/FormRepeatingFields.js +54 -0
  64. package/dist/forms/FormRepeatingFields.js.map +1 -0
  65. package/dist/forms/FormTransferListField.js +12 -0
  66. package/dist/forms/FormTransferListField.js.map +1 -0
  67. package/dist/forms/applyServerProblem.js +10 -3
  68. package/dist/forms/applyServerProblem.js.map +1 -1
  69. package/dist/forms/listRules.js +111 -0
  70. package/dist/forms/listRules.js.map +1 -0
  71. package/dist/forms/serverProblemFields.js +17 -0
  72. package/dist/forms/serverProblemFields.js.map +1 -1
  73. package/dist/forms.js +51 -29
  74. package/dist/forms.js.map +1 -1
  75. package/dist/hookForm/FormAttachmentsField.js +12 -0
  76. package/dist/hookForm/FormAttachmentsField.js.map +1 -0
  77. package/dist/hookForm/FormCheckboxGroupField.js +12 -0
  78. package/dist/hookForm/FormCheckboxGroupField.js.map +1 -0
  79. package/dist/hookForm/FormFileField.js +12 -0
  80. package/dist/hookForm/FormFileField.js.map +1 -0
  81. package/dist/hookForm/FormFileUploadField.js +12 -0
  82. package/dist/hookForm/FormFileUploadField.js.map +1 -0
  83. package/dist/hookForm/FormImageField.js +12 -0
  84. package/dist/hookForm/FormImageField.js.map +1 -0
  85. package/dist/hookForm/FormMaskedField.js +12 -0
  86. package/dist/hookForm/FormMaskedField.js.map +1 -0
  87. package/dist/hookForm/FormRepeatingFields.js +44 -0
  88. package/dist/hookForm/FormRepeatingFields.js.map +1 -0
  89. package/dist/hookForm/FormTransferListField.js +12 -0
  90. package/dist/hookForm/FormTransferListField.js.map +1 -0
  91. package/dist/hookForm/applyServerProblem.js +8 -3
  92. package/dist/hookForm/applyServerProblem.js.map +1 -1
  93. package/dist/index.js +188 -100
  94. package/dist/index.js.map +1 -1
  95. package/dist/inputs/CatalogInput.js +74 -7
  96. package/dist/inputs/CatalogInput.js.map +1 -1
  97. package/dist/inputs/CheckboxGroupInput.js +100 -0
  98. package/dist/inputs/CheckboxGroupInput.js.map +1 -0
  99. package/dist/inputs/MaskedInput.js +86 -0
  100. package/dist/inputs/MaskedInput.js.map +1 -0
  101. package/dist/inputs/NumberInput.js +12 -1
  102. package/dist/inputs/NumberInput.js.map +1 -1
  103. package/dist/inputs/RepeatingFields.js +177 -0
  104. package/dist/inputs/RepeatingFields.js.map +1 -0
  105. package/dist/inputs/SelectInput.js +43 -5
  106. package/dist/inputs/SelectInput.js.map +1 -1
  107. package/dist/inputs/TransferListInput.js +215 -0
  108. package/dist/inputs/TransferListInput.js.map +1 -0
  109. package/dist/inputs/inputMasks.js +84 -0
  110. package/dist/inputs/inputMasks.js.map +1 -0
  111. package/dist/inputs/selectAllState.js +20 -0
  112. package/dist/inputs/selectAllState.js.map +1 -0
  113. package/dist/inputs/useRowKeys.js +26 -0
  114. package/dist/inputs/useRowKeys.js.map +1 -0
  115. package/dist/legal/CookieNotice.js +79 -0
  116. package/dist/legal/CookieNotice.js.map +1 -0
  117. package/dist/legal/TermsAcceptanceDialog.js +129 -0
  118. package/dist/legal/TermsAcceptanceDialog.js.map +1 -0
  119. package/dist/legal/consentStorage.js +18 -0
  120. package/dist/legal/consentStorage.js.map +1 -0
  121. package/dist/legal/useCookieConsent.js +17 -0
  122. package/dist/legal/useCookieConsent.js.map +1 -0
  123. package/dist/locales/en.js +233 -1
  124. package/dist/locales/en.js.map +1 -1
  125. package/dist/locales/es.js +233 -1
  126. package/dist/locales/es.js.map +1 -1
  127. package/dist/mexico/CfdiSummary.js +81 -0
  128. package/dist/mexico/CfdiSummary.js.map +1 -0
  129. package/dist/mexico/EfirmaFields.js +167 -0
  130. package/dist/mexico/EfirmaFields.js.map +1 -0
  131. package/dist/mexico/certificateReader.js +79 -0
  132. package/dist/mexico/certificateReader.js.map +1 -0
  133. package/dist/mexico/cfdiReader.js +81 -0
  134. package/dist/mexico/cfdiReader.js.map +1 -0
  135. package/dist/mexico/derReader.js +81 -0
  136. package/dist/mexico/derReader.js.map +1 -0
  137. package/dist/mexico/efirmaKey.js +51 -0
  138. package/dist/mexico/efirmaKey.js.map +1 -0
  139. package/dist/mexico/mexicoIdentifiers.js +86 -0
  140. package/dist/mexico/mexicoIdentifiers.js.map +1 -0
  141. package/dist/mexico/mexicoRules.js +16 -0
  142. package/dist/mexico/mexicoRules.js.map +1 -0
  143. package/dist/mexico.js +32 -0
  144. package/dist/mexico.js.map +1 -0
  145. package/dist/react-hook-form.js +40 -17
  146. package/dist/react-hook-form.js.map +1 -1
  147. package/dist/rich-text.js +19 -0
  148. package/dist/rich-text.js.map +1 -0
  149. package/dist/richText/FormRichTextField.js +12 -0
  150. package/dist/richText/FormRichTextField.js.map +1 -0
  151. package/dist/richText/RichTextEditor.js +108 -0
  152. package/dist/richText/RichTextEditor.js.map +1 -0
  153. package/dist/richText/RichTextLinkPopover.js +57 -0
  154. package/dist/richText/RichTextLinkPopover.js.map +1 -0
  155. package/dist/richText/RichTextToolbar.js +189 -0
  156. package/dist/richText/RichTextToolbar.js.map +1 -0
  157. package/dist/richText/RichTextView.js +26 -0
  158. package/dist/richText/RichTextView.js.map +1 -0
  159. package/dist/richText/richTextContentSx.js +42 -0
  160. package/dist/richText/richTextContentSx.js.map +1 -0
  161. package/dist/richText/richTextExtensions.js +44 -0
  162. package/dist/richText/richTextExtensions.js.map +1 -0
  163. package/dist/richText/richTextRules.js +46 -0
  164. package/dist/richText/richTextRules.js.map +1 -0
  165. package/dist/security/SessionsCard.js +11 -7
  166. package/dist/security/SessionsCard.js.map +1 -1
  167. package/dist/table.js +2 -0
  168. package/dist/table.js.map +1 -1
  169. package/dist/theme/components/glassComponents.js +27 -0
  170. package/dist/theme/components/glassComponents.js.map +1 -1
  171. package/dist/theme/components/minimalComponents.js +12 -0
  172. package/dist/theme/components/minimalComponents.js.map +1 -1
  173. package/dist/types/DataTable/ServerTableFilterDrawer.d.ts +21 -0
  174. package/dist/types/DataTable/filterContext.d.ts +2 -1
  175. package/dist/types/DataTable/goToPageOptions.d.ts +15 -0
  176. package/dist/types/DataTable/index.d.ts +1 -0
  177. package/dist/types/date-pickers.d.ts +10 -1
  178. package/dist/types/datePickers/DateInput.d.ts +6 -4
  179. package/dist/types/datePickers/DateTimeInput.d.ts +50 -0
  180. package/dist/types/datePickers/FormDateTimeField.d.ts +7 -0
  181. package/dist/types/datePickers/FormMonthField.d.ts +7 -0
  182. package/dist/types/datePickers/FormTimeField.d.ts +7 -0
  183. package/dist/types/datePickers/MonthInput.d.ts +39 -0
  184. package/dist/types/datePickers/PickerFrame.d.ts +22 -0
  185. package/dist/types/datePickers/TimeInput.d.ts +38 -0
  186. package/dist/types/datePickers/dateTimeRules.d.ts +31 -0
  187. package/dist/types/datePickers/pickerValues.d.ts +114 -0
  188. package/dist/types/datePickers/useCurrentMinute.d.ts +5 -0
  189. package/dist/types/datePickers/usePickerField.d.ts +24 -0
  190. package/dist/types/dictionaries/dictionaries.d.ts +6 -3
  191. package/dist/types/forms/FormAttachmentsField.d.ts +7 -0
  192. package/dist/types/forms/FormCheckboxGroupField.d.ts +7 -0
  193. package/dist/types/forms/FormFileField.d.ts +7 -0
  194. package/dist/types/forms/FormFileUploadField.d.ts +7 -0
  195. package/dist/types/forms/FormImageField.d.ts +7 -0
  196. package/dist/types/forms/FormMaskedField.d.ts +7 -0
  197. package/dist/types/forms/FormRepeatingFields.d.ts +25 -0
  198. package/dist/types/forms/FormTransferListField.d.ts +7 -0
  199. package/dist/types/forms/index.d.ts +10 -1
  200. package/dist/types/forms/listRules.d.ts +48 -0
  201. package/dist/types/forms/serverProblemFields.d.ts +13 -0
  202. package/dist/types/forms.d.ts +1 -1
  203. package/dist/types/hookForm/FormAttachmentsField.d.ts +8 -0
  204. package/dist/types/hookForm/FormCheckboxGroupField.d.ts +8 -0
  205. package/dist/types/hookForm/FormFileField.d.ts +8 -0
  206. package/dist/types/hookForm/FormFileUploadField.d.ts +8 -0
  207. package/dist/types/hookForm/FormImageField.d.ts +8 -0
  208. package/dist/types/hookForm/FormMaskedField.d.ts +9 -0
  209. package/dist/types/hookForm/FormRepeatingFields.d.ts +27 -0
  210. package/dist/types/hookForm/FormTransferListField.d.ts +8 -0
  211. package/dist/types/index.d.ts +25 -3
  212. package/dist/types/inputs/CatalogInput.d.ts +7 -1
  213. package/dist/types/inputs/CheckboxGroupInput.d.ts +39 -0
  214. package/dist/types/inputs/MaskedInput.d.ts +35 -0
  215. package/dist/types/inputs/RepeatingFields.d.ts +52 -0
  216. package/dist/types/inputs/SelectInput.d.ts +6 -1
  217. package/dist/types/inputs/TransferListInput.d.ts +43 -0
  218. package/dist/types/inputs/inputMasks.d.ts +52 -0
  219. package/dist/types/inputs/selectAllState.d.ts +11 -0
  220. package/dist/types/inputs/useRowKeys.d.ts +11 -0
  221. package/dist/types/legal/CookieNotice.d.ts +30 -0
  222. package/dist/types/legal/TermsAcceptanceDialog.d.ts +32 -0
  223. package/dist/types/legal/consentStorage.d.ts +16 -0
  224. package/dist/types/legal/useCookieConsent.d.ts +13 -0
  225. package/dist/types/locales/en.d.ts +232 -0
  226. package/dist/types/locales/es.d.ts +232 -0
  227. package/dist/types/mexico/CfdiSummary.d.ts +17 -0
  228. package/dist/types/mexico/EfirmaFields.d.ts +38 -0
  229. package/dist/types/mexico/certificateReader.d.ts +37 -0
  230. package/dist/types/mexico/cfdiReader.d.ts +95 -0
  231. package/dist/types/mexico/derReader.d.ts +54 -0
  232. package/dist/types/mexico/efirmaKey.d.ts +26 -0
  233. package/dist/types/mexico/mexicoIdentifiers.d.ts +61 -0
  234. package/dist/types/mexico/mexicoRules.d.ts +29 -0
  235. package/dist/types/mexico.d.ts +11 -0
  236. package/dist/types/react-hook-form.d.ts +10 -1
  237. package/dist/types/rich-text.d.ts +5 -0
  238. package/dist/types/richText/FormRichTextField.d.ts +7 -0
  239. package/dist/types/richText/RichTextEditor.d.ts +42 -0
  240. package/dist/types/richText/RichTextLinkPopover.d.ts +17 -0
  241. package/dist/types/richText/RichTextToolbar.d.ts +15 -0
  242. package/dist/types/richText/RichTextView.d.ts +13 -0
  243. package/dist/types/richText/richTextContentSx.d.ts +7 -0
  244. package/dist/types/richText/richTextExtensions.d.ts +15 -0
  245. package/dist/types/richText/richTextRules.d.ts +41 -0
  246. package/dist/types/table.d.ts +1 -1
  247. package/dist/types/ui/actions/ActionsMenu.d.ts +18 -3
  248. package/dist/types/ui/actions/CopyButton.d.ts +7 -4
  249. package/dist/types/ui/actions/tableRowText.d.ts +6 -0
  250. package/dist/types/ui/cards/RecordCard.d.ts +65 -0
  251. package/dist/types/ui/cards/RecordCardSkeleton.d.ts +17 -0
  252. package/dist/types/ui/countdown/Countdown.d.ts +31 -0
  253. package/dist/types/ui/countdown/countdownParts.d.ts +39 -0
  254. package/dist/types/ui/countdown/useCountdown.d.ts +14 -0
  255. package/dist/types/ui/documents/PdfViewerDialog.d.ts +21 -0
  256. package/dist/types/ui/filters/FilterDrawer.d.ts +34 -0
  257. package/dist/types/ui/filters/filterDrawerFields.d.ts +139 -0
  258. package/dist/types/ui/help/HelpButton.d.ts +15 -0
  259. package/dist/types/ui/help/HelpCarouselDialog.d.ts +35 -0
  260. package/dist/types/ui/help/useHelpCarousel.d.ts +21 -0
  261. package/dist/types/ui/index.d.ts +10 -0
  262. package/dist/types/ui/labels/IconBadge.d.ts +34 -0
  263. package/dist/types/ui/navigation/RouteTabs.d.ts +44 -0
  264. package/dist/types/ui/navigation/routeTabMatching.d.ts +27 -0
  265. package/dist/types/upload/AttachmentsInput.d.ts +62 -0
  266. package/dist/types/upload/FileChip.d.ts +18 -0
  267. package/dist/types/upload/FileDropzone.d.ts +3 -0
  268. package/dist/types/upload/FileInput.d.ts +48 -0
  269. package/dist/types/upload/FileUploadInput.d.ts +80 -0
  270. package/dist/types/upload/ImageInput.d.ts +53 -0
  271. package/dist/types/upload/TemplateDownloadButton.d.ts +39 -0
  272. package/dist/types/upload/fileAppearance.d.ts +8 -0
  273. package/dist/types/upload/fileRules.d.ts +38 -0
  274. package/dist/types/upload/transferProgress.d.ts +18 -0
  275. package/dist/types/upload/uploadMachine.d.ts +6 -2
  276. package/dist/types/upload/uploadWithProgress.d.ts +6 -2
  277. package/dist/types/upload/useFilePicker.d.ts +39 -0
  278. package/dist/ui/actions/ActionsMenu.js +98 -15
  279. package/dist/ui/actions/ActionsMenu.js.map +1 -1
  280. package/dist/ui/actions/CopyButton.js +31 -11
  281. package/dist/ui/actions/CopyButton.js.map +1 -1
  282. package/dist/ui/actions/tableRowText.js +7 -0
  283. package/dist/ui/actions/tableRowText.js.map +1 -0
  284. package/dist/ui/cards/RecordCard.js +145 -0
  285. package/dist/ui/cards/RecordCard.js.map +1 -0
  286. package/dist/ui/cards/RecordCardSkeleton.js +33 -0
  287. package/dist/ui/cards/RecordCardSkeleton.js.map +1 -0
  288. package/dist/ui/countdown/Countdown.js +38 -0
  289. package/dist/ui/countdown/Countdown.js.map +1 -0
  290. package/dist/ui/countdown/countdownParts.js +34 -0
  291. package/dist/ui/countdown/countdownParts.js.map +1 -0
  292. package/dist/ui/countdown/useCountdown.js +35 -0
  293. package/dist/ui/countdown/useCountdown.js.map +1 -0
  294. package/dist/ui/documents/PdfViewerDialog.js +81 -0
  295. package/dist/ui/documents/PdfViewerDialog.js.map +1 -0
  296. package/dist/ui/filters/FilterDrawer.js +211 -0
  297. package/dist/ui/filters/FilterDrawer.js.map +1 -0
  298. package/dist/ui/filters/filterDrawerFields.js +119 -0
  299. package/dist/ui/filters/filterDrawerFields.js.map +1 -0
  300. package/dist/ui/help/HelpButton.js +17 -0
  301. package/dist/ui/help/HelpButton.js.map +1 -0
  302. package/dist/ui/help/HelpCarouselDialog.js +154 -0
  303. package/dist/ui/help/HelpCarouselDialog.js.map +1 -0
  304. package/dist/ui/help/useHelpCarousel.js +25 -0
  305. package/dist/ui/help/useHelpCarousel.js.map +1 -0
  306. package/dist/ui/labels/IconBadge.js +82 -0
  307. package/dist/ui/labels/IconBadge.js.map +1 -0
  308. package/dist/ui/navigation/RouteTabs.js +75 -0
  309. package/dist/ui/navigation/RouteTabs.js.map +1 -0
  310. package/dist/ui/navigation/routeTabMatching.js +23 -0
  311. package/dist/ui/navigation/routeTabMatching.js.map +1 -0
  312. package/dist/upload/AttachmentsInput.js +127 -0
  313. package/dist/upload/AttachmentsInput.js.map +1 -0
  314. package/dist/upload/FileChip.js +27 -0
  315. package/dist/upload/FileChip.js.map +1 -0
  316. package/dist/upload/FileDropzone.js +19 -84
  317. package/dist/upload/FileDropzone.js.map +1 -1
  318. package/dist/upload/FileInput.js +112 -0
  319. package/dist/upload/FileInput.js.map +1 -0
  320. package/dist/upload/FileUploadInput.js +285 -0
  321. package/dist/upload/FileUploadInput.js.map +1 -0
  322. package/dist/upload/ImageInput.js +125 -0
  323. package/dist/upload/ImageInput.js.map +1 -0
  324. package/dist/upload/TemplateDownloadButton.js +67 -0
  325. package/dist/upload/TemplateDownloadButton.js.map +1 -0
  326. package/dist/upload/fileAppearance.js +21 -0
  327. package/dist/upload/fileAppearance.js.map +1 -0
  328. package/dist/upload/fileRules.js +27 -1
  329. package/dist/upload/fileRules.js.map +1 -1
  330. package/dist/upload/transferProgress.js +23 -0
  331. package/dist/upload/transferProgress.js.map +1 -0
  332. package/dist/upload/uploadMachine.js +8 -8
  333. package/dist/upload/uploadMachine.js.map +1 -1
  334. package/dist/upload/uploadWithProgress.js +1 -1
  335. package/dist/upload/uploadWithProgress.js.map +1 -1
  336. package/dist/upload/useFilePicker.js +101 -0
  337. package/dist/upload/useFilePicker.js.map +1 -0
  338. package/package.json +44 -1
@@ -0,0 +1,86 @@
1
+ const RFC_PATTERN = /^([A-ZÑ&]{3,4})(\d{2})(\d{2})(\d{2})([A-Z\d]{2})([A\d])$/;
2
+ const GENERIC_RFCS = Object.freeze(["XAXX010101000", "XEXX010101000"]);
3
+ const RFC_CHECK_TABLE = "0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ Ñ";
4
+ const RFC_CHECK_MODULUS = 11;
5
+ const RFC_CHECK_LENGTH = 12;
6
+ const CURP_PATTERN = /^[A-Z][AEIOUX][A-Z]{2}(\d{2})(\d{2})(\d{2})[HMX](AS|BC|BS|CC|CL|CM|CS|CH|DF|DG|GT|GR|HG|JC|MC|MN|MS|NT|NL|OC|PL|QT|QR|SP|SL|SR|TC|TS|TL|VZ|YN|ZS|NE)[B-DF-HJ-NP-TV-Z]{3}[A-Z\d]\d$/;
7
+ const CURP_CHECK_TABLE = "0123456789ABCDEFGHIJKLMNÑOPQRSTUVWXYZ";
8
+ const CURP_BODY_LENGTH = 17;
9
+ const CLABE_PATTERN = /^\d{18}$/;
10
+ const CLABE_WEIGHTS = Object.freeze([3, 7, 1]);
11
+ const DECIMAL_BASE = 10;
12
+ const RFC_KIND = Object.freeze({ company: "company", person: "person", generic: "generic" });
13
+ function isRealShortDate(year, month, day) {
14
+ const date = new Date(Date.UTC(2e3 + Number(year), Number(month) - 1, Number(day)));
15
+ return date.getUTCMonth() === Number(month) - 1 && date.getUTCDate() === Number(day);
16
+ }
17
+ function rfcCheckDigitOf(rfc) {
18
+ const body = rfc.slice(0, -1).toUpperCase();
19
+ const padded = body.padStart(RFC_CHECK_LENGTH, " ");
20
+ let sum = 0;
21
+ for (let position = 0; position < RFC_CHECK_LENGTH; position += 1) {
22
+ sum += RFC_CHECK_TABLE.indexOf(padded[position]) * (RFC_CHECK_LENGTH + 1 - position);
23
+ }
24
+ const rest = sum % RFC_CHECK_MODULUS;
25
+ if (rest === 0) {
26
+ return "0";
27
+ }
28
+ return rest === 1 ? "A" : String(RFC_CHECK_MODULUS - rest);
29
+ }
30
+ function rfcKindOf(rfc) {
31
+ const clean = (rfc ?? "").trim().toUpperCase();
32
+ if (GENERIC_RFCS.includes(clean)) {
33
+ return RFC_KIND.generic;
34
+ }
35
+ const match = RFC_PATTERN.exec(clean);
36
+ if (!match) {
37
+ return null;
38
+ }
39
+ return match[1].length === 3 ? RFC_KIND.company : RFC_KIND.person;
40
+ }
41
+ function isValidRfc(rfc, { strict = false } = {}) {
42
+ const clean = (rfc ?? "").trim().toUpperCase();
43
+ if (GENERIC_RFCS.includes(clean)) {
44
+ return true;
45
+ }
46
+ const match = RFC_PATTERN.exec(clean);
47
+ if (!match || !isRealShortDate(match[2], match[3], match[4])) {
48
+ return false;
49
+ }
50
+ return !strict || rfcCheckDigitOf(clean) === clean.at(-1);
51
+ }
52
+ function curpCheckDigitOf(curp) {
53
+ const body = curp.slice(0, CURP_BODY_LENGTH).toUpperCase();
54
+ let sum = 0;
55
+ for (let position = 0; position < CURP_BODY_LENGTH; position += 1) {
56
+ sum += CURP_CHECK_TABLE.indexOf(body[position]) * (CURP_BODY_LENGTH + 1 - position);
57
+ }
58
+ return String((DECIMAL_BASE - sum % DECIMAL_BASE) % DECIMAL_BASE);
59
+ }
60
+ function isValidCurp(curp) {
61
+ const clean = (curp ?? "").trim().toUpperCase();
62
+ const match = CURP_PATTERN.exec(clean);
63
+ return Boolean(match) && isRealShortDate(match[1], match[2], match[3]) && curpCheckDigitOf(clean) === clean.at(-1);
64
+ }
65
+ function clabeCheckDigitOf(clabe) {
66
+ let sum = 0;
67
+ for (let position = 0; position < 17; position += 1) {
68
+ sum += Number(clabe[position]) * CLABE_WEIGHTS[position % CLABE_WEIGHTS.length] % DECIMAL_BASE;
69
+ }
70
+ return String((DECIMAL_BASE - sum % DECIMAL_BASE) % DECIMAL_BASE);
71
+ }
72
+ function isValidClabe(clabe) {
73
+ const clean = (clabe ?? "").replace(/\s/g, "");
74
+ return CLABE_PATTERN.test(clean) && clabeCheckDigitOf(clean) === clean.at(-1);
75
+ }
76
+ export {
77
+ RFC_KIND,
78
+ clabeCheckDigitOf,
79
+ curpCheckDigitOf,
80
+ isValidClabe,
81
+ isValidCurp,
82
+ isValidRfc,
83
+ rfcCheckDigitOf,
84
+ rfcKindOf
85
+ };
86
+ //# sourceMappingURL=mexicoIdentifiers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mexicoIdentifiers.js","sources":["../../src/mexico/mexicoIdentifiers.js"],"sourcesContent":["// Las claves de México que se escriben en casi cualquier sistema: el RFC (SAT), la CURP (RENAPO) y la CLABE (Banxico). Revisan\n// la forma de cada una y su dígito verificador, para avisar ANTES de mandar algo mal escrito. Lo que de verdad vale (que el\n// RFC exista, que la CLABE sea de esa persona) lo dice el SAT o el banco, del lado del servidor.\n//\n// Son estándares nacionales, no reglas de un cliente.\n//\n// Puro (sin React): se prueba con node (mexicoIdentifiers.test.js).\n//\n// Genérico del paquete: function (regla de la casa).\n\n// RFC: 3 letras (persona moral) o 4 (persona física), la fecha AAMMDD y la homoclave de 3 (la última es el dígito)\nconst RFC_PATTERN = /^([A-ZÑ&]{3,4})(\\d{2})(\\d{2})(\\d{2})([A-Z\\d]{2})([A\\d])$/;\n// los genéricos del SAT: público en general (nacional) y extranjero\nconst GENERIC_RFCS = Object.freeze(['XAXX010101000', 'XEXX010101000']);\nconst RFC_CHECK_TABLE = '0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ Ñ';\nconst RFC_CHECK_MODULUS = 11;\nconst RFC_CHECK_LENGTH = 12;\n\n// CURP: 4 letras, la fecha AAMMDD, el sexo (H, M o X), el estado (o NE: nacido en el extranjero), 3 consonantes, el carácter\n// que distingue al siglo y el dígito\nconst CURP_PATTERN = /^[A-Z][AEIOUX][A-Z]{2}(\\d{2})(\\d{2})(\\d{2})[HMX](AS|BC|BS|CC|CL|CM|CS|CH|DF|DG|GT|GR|HG|JC|MC|MN|MS|NT|NL|OC|PL|QT|QR|SP|SL|SR|TC|TS|TL|VZ|YN|ZS|NE)[B-DF-HJ-NP-TV-Z]{3}[A-Z\\d]\\d$/;\nconst CURP_CHECK_TABLE = '0123456789ABCDEFGHIJKLMNÑOPQRSTUVWXYZ';\nconst CURP_BODY_LENGTH = 17;\n\n// CLABE: 18 dígitos; los pesos 3, 7, 1 se repiten sobre los primeros 17\nconst CLABE_PATTERN = /^\\d{18}$/;\nconst CLABE_WEIGHTS = Object.freeze([3, 7, 1]);\nconst DECIMAL_BASE = 10;\n\n/** De qué tipo es un RFC. */\nexport const RFC_KIND = Object.freeze({company: 'company', person: 'person', generic: 'generic'});\n\n/**\n * ¿La fecha AAMMDD existe? (el 31 de febrero no).\n *\n * @param {string} year dos dígitos\n * @param {string} month\n * @param {string} day\n * @returns {boolean}\n */\nfunction isRealShortDate(year, month, day) {\n // el siglo no importa para saber si el día existe, salvo el 29 de febrero: 2000 fue bisiesto y 1900 no, y las dos se\n // escriben «00». Se toma el 2000 (el de cualquier persona viva nacida un 29 de febrero «00»)\n const date = new Date(Date.UTC(2000 + Number(year), Number(month) - 1, Number(day)));\n return date.getUTCMonth() === Number(month) - 1 && date.getUTCDate() === Number(day);\n}\n\n/**\n * El dígito verificador de un RFC (el último carácter), calculado con el resto de 11 del SAT.\n *\n * @param {string} rfc el RFC completo (se ignora su último carácter)\n * @returns {string} '0'-'9' o 'A'\n */\nexport function rfcCheckDigitOf(rfc) {\n const body = rfc.slice(0, -1).toUpperCase();\n // la persona moral (11 sin el dígito) se rellena a 12 con un espacio al frente\n const padded = body.padStart(RFC_CHECK_LENGTH, ' ');\n let sum = 0;\n for (let position = 0; position < RFC_CHECK_LENGTH; position += 1) {\n sum += RFC_CHECK_TABLE.indexOf(padded[position]) * (RFC_CHECK_LENGTH + 1 - position);\n }\n const rest = sum % RFC_CHECK_MODULUS;\n if (rest === 0) {\n return '0';\n }\n return rest === 1 ? 'A' : String(RFC_CHECK_MODULUS - rest);\n}\n\n/**\n * De qué tipo es un RFC bien formado; null si no tiene la forma.\n *\n * @param {string|null|undefined} rfc\n * @returns {string|null} RFC_KIND\n */\nexport function rfcKindOf(rfc) {\n const clean = (rfc ?? '').trim().toUpperCase();\n if (GENERIC_RFCS.includes(clean)) {\n return RFC_KIND.generic;\n }\n const match = RFC_PATTERN.exec(clean);\n if (!match) {\n return null;\n }\n return match[1].length === 3 ? RFC_KIND.company : RFC_KIND.person;\n}\n\n/**\n * ¿El RFC está bien escrito? Revisa su forma (persona moral, física o genérico) y que la fecha exista.\n *\n * El dígito verificador va aparte (strict) y no por omisión: si un RFC real no lo cumpliera, la persona se quedaría sin poder\n * seguir, y quien dice si un RFC existe es el SAT.\n *\n * @param {string|null|undefined} rfc\n * @param {{strict?: boolean}} [options] strict: además, el dígito verificador\n * @returns {boolean}\n */\nexport function isValidRfc(rfc, {strict = false} = {}) {\n const clean = (rfc ?? '').trim().toUpperCase();\n if (GENERIC_RFCS.includes(clean)) {\n return true;\n }\n const match = RFC_PATTERN.exec(clean);\n if (!match || !isRealShortDate(match[2], match[3], match[4])) {\n return false;\n }\n return !strict || rfcCheckDigitOf(clean) === clean.at(-1);\n}\n\n/**\n * El dígito verificador de una CURP (el último).\n *\n * @param {string} curp la CURP completa (se ignora su último carácter)\n * @returns {string}\n */\nexport function curpCheckDigitOf(curp) {\n const body = curp.slice(0, CURP_BODY_LENGTH).toUpperCase();\n let sum = 0;\n for (let position = 0; position < CURP_BODY_LENGTH; position += 1) {\n sum += CURP_CHECK_TABLE.indexOf(body[position]) * (CURP_BODY_LENGTH + 1 - position);\n }\n return String((DECIMAL_BASE - (sum % DECIMAL_BASE)) % DECIMAL_BASE);\n}\n\n/**\n * ¿La CURP está bien escrita? Su forma (con el estado y el sexo), que la fecha exista y su dígito verificador.\n *\n * @param {string|null|undefined} curp\n * @returns {boolean}\n */\nexport function isValidCurp(curp) {\n const clean = (curp ?? '').trim().toUpperCase();\n const match = CURP_PATTERN.exec(clean);\n return Boolean(match) && isRealShortDate(match[1], match[2], match[3]) && curpCheckDigitOf(clean) === clean.at(-1);\n}\n\n/**\n * El dígito verificador de una CLABE (el 18.º).\n *\n * @param {string} clabe la CLABE completa o sus primeros 17 dígitos\n * @returns {string}\n */\nexport function clabeCheckDigitOf(clabe) {\n let sum = 0;\n for (let position = 0; position < 17; position += 1) {\n sum += (Number(clabe[position]) * CLABE_WEIGHTS[position % CLABE_WEIGHTS.length]) % DECIMAL_BASE;\n }\n return String((DECIMAL_BASE - (sum % DECIMAL_BASE)) % DECIMAL_BASE);\n}\n\n/**\n * ¿La CLABE está bien escrita? 18 dígitos (los espacios no cuentan) y su dígito verificador.\n *\n * @param {string|null|undefined} clabe\n * @returns {boolean}\n */\nexport function isValidClabe(clabe) {\n const clean = (clabe ?? '').replace(/\\s/g, '');\n return CLABE_PATTERN.test(clean) && clabeCheckDigitOf(clean) === clean.at(-1);\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { isValidClabe, isValidCurp, isValidRfc } from "./mexicoIdentifiers.js";
2
+ function rfcRule({ strict = false } = {}) {
3
+ return { name: "rfc", message: { key: "validation:rfc" }, test: (value) => !value || isValidRfc(String(value), { strict }) };
4
+ }
5
+ function curpRule() {
6
+ return { name: "curp", message: { key: "validation:curp" }, test: (value) => !value || isValidCurp(String(value)) };
7
+ }
8
+ function clabeRule() {
9
+ return { name: "clabe", message: { key: "validation:clabe" }, test: (value) => !value || isValidClabe(String(value)) };
10
+ }
11
+ export {
12
+ clabeRule,
13
+ curpRule,
14
+ rfcRule
15
+ };
16
+ //# sourceMappingURL=mexicoRules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mexicoRules.js","sources":["../../src/mexico/mexicoRules.js"],"sourcesContent":["// Las reglas de yup para el RFC, la CURP y la CLABE, con sus mensajes en el idioma activo (validation:rfc, validation:curp,\n// validation:clabe). Un campo vacío pasa: que sea obligatorio lo dice required().\n//\n// Yup.object({rfc: Yup.string().required().test(rfcRule()), clabe: Yup.string().test(clabeRule())})\n//\n// Son objetos de .test() y no un Yup propio: el proyecto usa su copia de yup y aquí no se importa.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {isValidClabe, isValidCurp, isValidRfc} from '@/mexico/mexicoIdentifiers.js';\n\n/**\n * @param {{strict?: boolean}} [options] strict: también el dígito verificador (ver isValidRfc)\n * @returns {{name: string, message: {key: string}, test: (value: unknown) => boolean}}\n */\nexport function rfcRule({strict = false} = {}) {\n return {name: 'rfc', message: {key: 'validation:rfc'}, test: (value) => !value || isValidRfc(String(value), {strict})};\n}\n\n/** @returns {{name: string, message: {key: string}, test: (value: unknown) => boolean}} */\nexport function curpRule() {\n return {name: 'curp', message: {key: 'validation:curp'}, test: (value) => !value || isValidCurp(String(value))};\n}\n\n/** @returns {{name: string, message: {key: string}, test: (value: unknown) => boolean}} */\nexport function clabeRule() {\n return {name: 'clabe', message: {key: 'validation:clabe'}, test: (value) => !value || isValidClabe(String(value))};\n}\n"],"names":[],"mappings":";AAcO,SAAS,QAAQ,EAAC,SAAS,MAAK,IAAI,CAAA,GAAI;AAC3C,SAAO,EAAC,MAAM,OAAO,SAAS,EAAC,KAAK,iBAAgB,GAAG,MAAM,CAAC,UAAU,CAAC,SAAS,WAAW,OAAO,KAAK,GAAG,EAAC,OAAM,CAAC,EAAC;AACzH;AAGO,SAAS,WAAW;AACvB,SAAO,EAAC,MAAM,QAAQ,SAAS,EAAC,KAAK,kBAAiB,GAAG,MAAM,CAAC,UAAU,CAAC,SAAS,YAAY,OAAO,KAAK,CAAC,EAAC;AAClH;AAGO,SAAS,YAAY;AACxB,SAAO,EAAC,MAAM,SAAS,SAAS,EAAC,KAAK,mBAAkB,GAAG,MAAM,CAAC,UAAU,CAAC,SAAS,aAAa,OAAO,KAAK,CAAC,EAAC;AACrH;"}
package/dist/mexico.js ADDED
@@ -0,0 +1,32 @@
1
+ import { RFC_KIND, clabeCheckDigitOf, curpCheckDigitOf, isValidClabe, isValidCurp, isValidRfc, rfcCheckDigitOf, rfcKindOf } from "./mexico/mexicoIdentifiers.js";
2
+ import { clabeRule, curpRule, rfcRule } from "./mexico/mexicoRules.js";
3
+ import { CERTIFICATE_STATUS, certificateStatusOf, readCertificate } from "./mexico/certificateReader.js";
4
+ import { CFDI_VOUCHER_TYPE, readCfdi, readCfdiFile } from "./mexico/cfdiReader.js";
5
+ import { EFIRMA_KEY_PROBLEM, EfirmaKeyError, verifyEfirmaKey } from "./mexico/efirmaKey.js";
6
+ import { default as default2 } from "./mexico/CfdiSummary.js";
7
+ import { default as default3 } from "./mexico/EfirmaFields.js";
8
+ export {
9
+ CERTIFICATE_STATUS,
10
+ CFDI_VOUCHER_TYPE,
11
+ default2 as CfdiSummary,
12
+ EFIRMA_KEY_PROBLEM,
13
+ default3 as EfirmaFields,
14
+ EfirmaKeyError,
15
+ RFC_KIND,
16
+ certificateStatusOf,
17
+ clabeCheckDigitOf,
18
+ clabeRule,
19
+ curpCheckDigitOf,
20
+ curpRule,
21
+ isValidClabe,
22
+ isValidCurp,
23
+ isValidRfc,
24
+ readCertificate,
25
+ readCfdi,
26
+ readCfdiFile,
27
+ rfcCheckDigitOf,
28
+ rfcKindOf,
29
+ rfcRule,
30
+ verifyEfirmaKey
31
+ };
32
+ //# sourceMappingURL=mexico.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mexico.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
@@ -1,32 +1,55 @@
1
1
  "use client";
2
- import { Controller, FormProvider, useForm, useFormContext } from "react-hook-form";
2
+ import { Controller, FormProvider, useFieldArray, useForm, useFormContext, useWatch } from "react-hook-form";
3
3
  import { yupResolver } from "@hookform/resolvers/yup";
4
- import { default as default2 } from "./hookForm/FormCatalogField.js";
5
- import { default as default3 } from "./hookForm/FormColorField.js";
6
- import { default as default4 } from "./hookForm/FormNumberField.js";
7
- import { default as default5 } from "./hookForm/FormProblemAlert.js";
8
- import { default as default6 } from "./hookForm/FormSelectField.js";
9
- import { default as default7 } from "./hookForm/FormWizard.js";
10
- import { default as default8 } from "./hookForm/FormTextField.js";
11
- import { default as default9 } from "./hookForm/SubmitButton.js";
4
+ import { default as default2 } from "./hookForm/FormAttachmentsField.js";
5
+ import { default as default3 } from "./hookForm/FormCatalogField.js";
6
+ import { default as default4 } from "./hookForm/FormCheckboxGroupField.js";
7
+ import { default as default5 } from "./hookForm/FormColorField.js";
8
+ import { default as default6 } from "./hookForm/FormFileField.js";
9
+ import { default as default7 } from "./hookForm/FormFileUploadField.js";
10
+ import { default as default8 } from "./hookForm/FormImageField.js";
11
+ import { default as default9 } from "./hookForm/FormMaskedField.js";
12
+ import { default as default10 } from "./hookForm/FormNumberField.js";
13
+ import { default as default11 } from "./hookForm/FormProblemAlert.js";
14
+ import { default as default12 } from "./hookForm/FormRepeatingFields.js";
15
+ import { default as default13 } from "./hookForm/FormTransferListField.js";
16
+ import { listTotalAtMostRule, listTotalOf, orderedInListRule, uniqueInListRule } from "./forms/listRules.js";
17
+ import { default as default14 } from "./hookForm/FormSelectField.js";
18
+ import { default as default15 } from "./hookForm/FormWizard.js";
19
+ import { default as default16 } from "./hookForm/FormTextField.js";
20
+ import { default as default17 } from "./hookForm/SubmitButton.js";
12
21
  import { SERVER_PROBLEM_ROOT, applyServerProblem } from "./hookForm/applyServerProblem.js";
13
22
  import { useHookFormField } from "./hookForm/useHookFormField.js";
14
23
  export {
15
24
  Controller,
16
- default2 as FormCatalogField,
17
- default3 as FormColorField,
18
- default4 as FormNumberField,
19
- default5 as FormProblemAlert,
25
+ default2 as FormAttachmentsField,
26
+ default3 as FormCatalogField,
27
+ default4 as FormCheckboxGroupField,
28
+ default5 as FormColorField,
29
+ default6 as FormFileField,
30
+ default7 as FormFileUploadField,
31
+ default8 as FormImageField,
32
+ default9 as FormMaskedField,
33
+ default10 as FormNumberField,
34
+ default11 as FormProblemAlert,
20
35
  FormProvider,
21
- default6 as FormSelectField,
22
- default8 as FormTextField,
23
- default7 as FormWizard,
36
+ default12 as FormRepeatingFields,
37
+ default14 as FormSelectField,
38
+ default16 as FormTextField,
39
+ default13 as FormTransferListField,
40
+ default15 as FormWizard,
24
41
  SERVER_PROBLEM_ROOT,
25
- default9 as SubmitButton,
42
+ default17 as SubmitButton,
26
43
  applyServerProblem,
44
+ listTotalAtMostRule,
45
+ listTotalOf,
46
+ orderedInListRule,
47
+ uniqueInListRule,
48
+ useFieldArray,
27
49
  useForm,
28
50
  useFormContext,
29
51
  useHookFormField,
52
+ useWatch,
30
53
  yupResolver
31
54
  };
32
55
  //# sourceMappingURL=react-hook-form.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"react-hook-form.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;"}
1
+ {"version":3,"file":"react-hook-form.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,19 @@
1
+ import { default as default2 } from "./richText/FormRichTextField.js";
2
+ import { default as default3 } from "./richText/RichTextEditor.js";
3
+ import { default as default4 } from "./richText/RichTextView.js";
4
+ import { DEFAULT_RICH_TEXT_FEATURES, RICH_TEXT_FEATURE, SAFE_LINK_PROTOCOLS, isSafeLinkUrl, linkUrlOf, normalizedHtmlOf } from "./richText/richTextRules.js";
5
+ import { RICH_TEXT_HEADING_LEVELS, richTextExtensionsOf } from "./richText/richTextExtensions.js";
6
+ export {
7
+ DEFAULT_RICH_TEXT_FEATURES,
8
+ default2 as FormRichTextField,
9
+ RICH_TEXT_FEATURE,
10
+ RICH_TEXT_HEADING_LEVELS,
11
+ default3 as RichTextEditor,
12
+ default4 as RichTextView,
13
+ SAFE_LINK_PROTOCOLS,
14
+ isSafeLinkUrl,
15
+ linkUrlOf,
16
+ normalizedHtmlOf,
17
+ richTextExtensionsOf
18
+ };
19
+ //# sourceMappingURL=rich-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rich-text.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
@@ -0,0 +1,12 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useFormikField } from "../forms/useFormikField.js";
4
+ import RichTextEditor from "./RichTextEditor.js";
5
+ function FormRichTextField({ name, ...editorProps }) {
6
+ const fieldProps = useFormikField(name);
7
+ return /* @__PURE__ */ jsx(RichTextEditor, { ...editorProps, ...fieldProps });
8
+ }
9
+ export {
10
+ FormRichTextField as default
11
+ };
12
+ //# sourceMappingURL=FormRichTextField.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FormRichTextField.js","sources":["../../src/richText/FormRichTextField.jsx"],"sourcesContent":["// Campo de texto con formato de formik: RichTextEditor conectado a su campo. Al formulario llega el HTML ('' si no hay nada\n// escrito).\n//\n// Con react-hook-form no hay uno listo (esta puerta no pide react-hook-form): RichTextEditor va dentro de un Controller.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormikField} from '@/forms/useFormikField.js';\nimport RichTextEditor from '@/richText/RichTextEditor.jsx';\n\n/**\n * @param {{name: string} & Omit<Parameters<typeof import('@/richText/RichTextEditor.jsx').default>[0], 'name'|'value'|'onChange'|'onBlur'|'error'>} props las de\n * RichTextEditor (features, maxLength, placeholder…), sin value / onChange / onBlur / error\n */\nexport default function FormRichTextField({name, ...editorProps}) {\n const fieldProps = useFormikField(name);\n return <RichTextEditor {...editorProps} {...fieldProps} />;\n}\n"],"names":[],"mappings":";;;;AAaA,SAAwB,kBAAkB,EAAC,MAAM,GAAG,eAAc;AAC9D,QAAM,aAAa,eAAe,IAAI;AACtC,SAAO,oBAAC,gBAAA,EAAgB,GAAG,aAAc,GAAG,WAAA,CAAY;AAC5D;"}
@@ -0,0 +1,108 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useId, useRef, useEffect } from "react";
4
+ import { useEditor, useEditorState, EditorContent } from "@tiptap/react";
5
+ import FormHelperText from "@mui/material/FormHelperText";
6
+ import Paper from "@mui/material/Paper";
7
+ import Stack from "@mui/material/Stack";
8
+ import Box from "@mui/material/Box";
9
+ import { translateValidationMessage } from "../forms/validationMessages.js";
10
+ import FieldFrame from "../inputs/FieldFrame.js";
11
+ import { richTextContentSxOf } from "./richTextContentSx.js";
12
+ import { richTextExtensionsOf } from "./richTextExtensions.js";
13
+ import { DEFAULT_RICH_TEXT_FEATURES, normalizedHtmlOf } from "./richTextRules.js";
14
+ import RichTextToolbar from "./RichTextToolbar.js";
15
+ import { piecePart, usePieceProps } from "../theme/themePieces.js";
16
+ import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
17
+ import { warnUnknownProps } from "../toolkit/unknownProps.js";
18
+ const THEME_NAME = "CalcitaRichTextEditor";
19
+ const EditorRoot = piecePart(THEME_NAME, "Root", Paper);
20
+ const EditorToolbar = piecePart(THEME_NAME, "Toolbar", Stack);
21
+ const EditorContentArea = piecePart(THEME_NAME, "Content", Box);
22
+ const EditorFooter = piecePart(THEME_NAME, "Footer", Stack);
23
+ const DEFAULT_MIN_HEIGHT = 160;
24
+ function RichTextEditor(props) {
25
+ const {
26
+ name,
27
+ label,
28
+ value,
29
+ onChange,
30
+ onBlur,
31
+ placeholder,
32
+ error,
33
+ helperText = " ",
34
+ maxLength,
35
+ features = DEFAULT_RICH_TEXT_FEATURES,
36
+ extensions,
37
+ toolbarActions,
38
+ onEditorReady,
39
+ minHeight = DEFAULT_MIN_HEIGHT,
40
+ disabled = false,
41
+ sx,
42
+ texts,
43
+ ...unknownProps
44
+ } = usePieceProps(props, THEME_NAME);
45
+ warnUnknownProps(THEME_NAME, unknownProps);
46
+ const { t } = useToolkitTranslation("richText", texts);
47
+ const generatedId = useId();
48
+ const contentId = `${name ?? "rich-text"}-${generatedId}`;
49
+ const labelId = `${contentId}-label`;
50
+ const errorText = translateValidationMessage(t, error);
51
+ const latest = useRef({ onChange, onBlur, onEditorReady });
52
+ latest.current = { onChange, onBlur, onEditorReady };
53
+ const editor = useEditor({
54
+ extensions: richTextExtensionsOf({ features, placeholder, maxLength, extensions }),
55
+ content: value ?? "",
56
+ editable: !disabled,
57
+ // OJO: sin esto, al pintar en el servidor (Next) el editor avisa que no hay documento todavía
58
+ immediatelyRender: false,
59
+ editorProps: {
60
+ attributes: { id: contentId, role: "textbox", "aria-multiline": "true", "aria-labelledby": labelId, ...errorText && { "aria-invalid": "true" } }
61
+ },
62
+ onUpdate: ({ editor: current }) => latest.current.onChange(normalizedHtmlOf(current.getHTML())),
63
+ onBlur: () => latest.current.onBlur?.(),
64
+ onCreate: ({ editor: current }) => latest.current.onEditorReady?.(current)
65
+ }, [features.join(","), placeholder, maxLength, Boolean(errorText)]);
66
+ useEffect(() => {
67
+ if (editor && normalizedHtmlOf(editor.getHTML()) !== (value ?? "")) {
68
+ editor.commands.setContent(value ?? "", { emitUpdate: false });
69
+ }
70
+ }, [editor, value]);
71
+ useEffect(() => {
72
+ editor?.setEditable(!disabled);
73
+ }, [editor, disabled]);
74
+ const characters = useEditorState({ editor, selector: ({ editor: current }) => current?.storage.characterCount?.characters() ?? 0 });
75
+ return /* @__PURE__ */ jsx(FieldFrame, { inputId: contentId, labelId, label, children: /* @__PURE__ */ jsxs("div", { children: [
76
+ /* @__PURE__ */ jsxs(EditorRoot, { variant: "outlined", ownSx: (theme) => ({
77
+ borderRadius: 2,
78
+ overflow: "hidden",
79
+ opacity: disabled ? 0.6 : 1,
80
+ borderColor: errorText ? "error.main" : "divider",
81
+ "&:focus-within": { borderColor: errorText ? "error.main" : "primary.main", boxShadow: `0 0 0 1px ${(theme.vars ?? theme).palette[errorText ? "error" : "primary"].main}` }
82
+ }), sx, children: [
83
+ /* @__PURE__ */ jsx(
84
+ EditorToolbar,
85
+ {
86
+ role: "toolbar",
87
+ "aria-label": t("toolbar.label"),
88
+ "aria-controls": contentId,
89
+ direction: "row",
90
+ ownSx: { alignItems: "center", flexWrap: "wrap", gap: 0.25, px: 0.5, py: 0.5, borderBottom: 1, borderColor: "divider" },
91
+ children: /* @__PURE__ */ jsx(RichTextToolbar, { editor, features, disabled, t, actions: toolbarActions })
92
+ }
93
+ ),
94
+ /* @__PURE__ */ jsx(EditorContentArea, { ownSx: (theme) => {
95
+ const content = richTextContentSxOf(theme);
96
+ return { ...content, px: 2, py: 1.5, cursor: "text", "& .tiptap": { ...content["& .tiptap"], minHeight } };
97
+ }, onClick: () => editor?.commands.focus(), children: /* @__PURE__ */ jsx(EditorContent, { editor }) })
98
+ ] }),
99
+ /* @__PURE__ */ jsxs(EditorFooter, { direction: "row", ownSx: { justifyContent: "space-between", gap: 2 }, children: [
100
+ /* @__PURE__ */ jsx(FormHelperText, { error: Boolean(errorText), children: errorText ?? helperText }),
101
+ maxLength && /* @__PURE__ */ jsx(FormHelperText, { sx: { fontVariantNumeric: "tabular-nums", whiteSpace: "nowrap" }, children: t("counter", { count: characters, max: maxLength }) })
102
+ ] })
103
+ ] }) });
104
+ }
105
+ export {
106
+ RichTextEditor as default
107
+ };
108
+ //# sourceMappingURL=RichTextEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichTextEditor.js","sources":["../../src/richText/RichTextEditor.jsx"],"sourcesContent":["// El editor de texto con formato (Tiptap), con la etiqueta arriba como los demás campos del paquete: negrita, cursiva,\n// títulos, listas, cita, código, ligas seguras, alineación, deshacer y rehacer, y el contador de caracteres si hay tope.\n//\n// Viaja HTML ('<p>Hola <strong>mundo</strong></p>'); '' si no hay nada escrito (así required() funciona). Para ENSEÑAR lo\n// guardado va RichTextView, que solo deja pasar lo que el editor entiende: un <script> o un onclick pegado no llegan a la\n// página.\n//\n// Extensible sin tocar el paquete: features (qué botones trae; lo que no se pide tampoco entra al documento), extensions\n// (extensiones de Tiptap del proyecto: menciones, tablas…), toolbarActions (botones propios al final de la barra) y\n// onEditorReady (el editor de Tiptap, para lo que la barra no trae). Con formik: FormRichTextField; con react-hook-form, dentro\n// de un Controller.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaRichTextEditor con defaultProps y\n// styleOverrides de sus partes: root, toolbar, content, footer.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useId, useRef} from 'react';\nimport {EditorContent, useEditor, useEditorState} from '@tiptap/react';\nimport FormHelperText from '@mui/material/FormHelperText';\nimport Paper from '@mui/material/Paper';\nimport Stack from '@mui/material/Stack';\nimport Box from '@mui/material/Box';\n\nimport {translateValidationMessage} from '@/forms/validationMessages.js';\nimport FieldFrame from '@/inputs/FieldFrame.jsx';\nimport {richTextContentSxOf} from '@/richText/richTextContentSx.js';\nimport {richTextExtensionsOf} from '@/richText/richTextExtensions.js';\nimport {DEFAULT_RICH_TEXT_FEATURES, normalizedHtmlOf} from '@/richText/richTextRules.js';\nimport RichTextToolbar from '@/richText/RichTextToolbar.jsx';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaRichTextEditor)\nconst THEME_NAME = 'CalcitaRichTextEditor';\nconst EditorRoot = piecePart(THEME_NAME, 'Root', Paper);\nconst EditorToolbar = piecePart(THEME_NAME, 'Toolbar', Stack);\nconst EditorContentArea = piecePart(THEME_NAME, 'Content', Box);\nconst EditorFooter = piecePart(THEME_NAME, 'Footer', Stack);\n\nconst DEFAULT_MIN_HEIGHT = 160;\n\n/**\n * @param {object} props\n * @param {string} [props.name]\n * @param {import('react').ReactNode} props.label ya traducida\n * @param {string|null|undefined} props.value el HTML guardado ('' sin texto)\n * @param {(html: string) => void} props.onChange recibe el HTML ('' si se borra todo)\n * @param {() => void} [props.onBlur]\n * @param {string} [props.placeholder] ya traducido: lo que se ve con el editor vacío\n * @param {string|{key: string, values?: object}} [props.error]\n * @param {string} [props.helperText] ya traducida\n * @param {number} [props.maxLength] el tope de caracteres (con su contador abajo)\n * @param {string[]} [props.features] los botones de la barra (RICH_TEXT_FEATURE); por omisión todos\n * @param {Array<object>} [props.extensions] extensiones de Tiptap del proyecto\n * @param {import('react').ReactNode} [props.toolbarActions] botones propios al final de la barra\n * @param {(editor: import('@tiptap/react').Editor) => void} [props.onEditorReady] el editor de Tiptap, al estar listo\n * @param {number} [props.minHeight] el alto mínimo del texto en px; por omisión 160\n * @param {boolean} [props.disabled]\n * @param {object} [props.sx]\n * @param {object} [props.texts] los textos que cambian, con la forma de `richText` en los textos del paquete\n */\nexport default function RichTextEditor(props) {\n const {\n name, label, value, onChange, onBlur, placeholder, error, helperText = ' ', maxLength, features = DEFAULT_RICH_TEXT_FEATURES, extensions,\n toolbarActions, onEditorReady, minHeight = DEFAULT_MIN_HEIGHT, disabled = false, sx, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('richText', texts);\n const generatedId = useId();\n const contentId = `${name ?? 'rich-text'}-${generatedId}`;\n const labelId = `${contentId}-label`;\n const errorText = translateValidationMessage(t, error);\n // lo último de afuera, sin rearmar el editor cada vez que la pantalla pinta otra función\n const latest = useRef({onChange, onBlur, onEditorReady});\n latest.current = {onChange, onBlur, onEditorReady};\n\n const editor = useEditor({\n extensions: richTextExtensionsOf({features, placeholder, maxLength, extensions}),\n content: value ?? '',\n editable: !disabled,\n // OJO: sin esto, al pintar en el servidor (Next) el editor avisa que no hay documento todavía\n immediatelyRender: false,\n editorProps: {\n attributes: {id: contentId, role: 'textbox', 'aria-multiline': 'true', 'aria-labelledby': labelId, ...(errorText && {'aria-invalid': 'true'})},\n },\n onUpdate: ({editor: current}) => latest.current.onChange(normalizedHtmlOf(current.getHTML())),\n onBlur: () => latest.current.onBlur?.(),\n onCreate: ({editor: current}) => latest.current.onEditorReady?.(current),\n }, [features.join(','), placeholder, maxLength, Boolean(errorText)]);\n\n // lo que llega de afuera (el formulario se reinició, llegó del servidor) entra sin avisar otro cambio\n useEffect(() => {\n if (editor && normalizedHtmlOf(editor.getHTML()) !== (value ?? '')) {\n editor.commands.setContent(value ?? '', {emitUpdate: false});\n }\n }, [editor, value]);\n useEffect(() => {\n editor?.setEditable(!disabled);\n }, [editor, disabled]);\n\n const characters = useEditorState({editor, selector: ({editor: current}) => current?.storage.characterCount?.characters() ?? 0});\n\n return (\n <FieldFrame inputId={contentId} labelId={labelId} label={label}>\n <div>\n <EditorRoot variant=\"outlined\" ownSx={(theme) => ({\n borderRadius: 2, overflow: 'hidden', opacity: disabled ? 0.6 : 1,\n borderColor: errorText ? 'error.main' : 'divider',\n '&:focus-within': {borderColor: errorText ? 'error.main' : 'primary.main', boxShadow: `0 0 0 1px ${(theme.vars ?? theme).palette[errorText ? 'error' : 'primary'].main}`},\n })} sx={sx}>\n <EditorToolbar role=\"toolbar\" aria-label={t('toolbar.label')} aria-controls={contentId} direction=\"row\"\n ownSx={{alignItems: 'center', flexWrap: 'wrap', gap: 0.25, px: 0.5, py: 0.5, borderBottom: 1, borderColor: 'divider'}}>\n <RichTextToolbar editor={editor} features={features} disabled={disabled} t={t} actions={toolbarActions} />\n </EditorToolbar>\n <EditorContentArea ownSx={(theme) => {\n const content = richTextContentSxOf(theme);\n return {...content, px: 2, py: 1.5, cursor: 'text', '& .tiptap': {...content['& .tiptap'], minHeight}};\n }} onClick={() => editor?.commands.focus()}>\n <EditorContent editor={editor} />\n </EditorContentArea>\n </EditorRoot>\n <EditorFooter direction=\"row\" ownSx={{justifyContent: 'space-between', gap: 2}}>\n <FormHelperText error={Boolean(errorText)}>{errorText ?? helperText}</FormHelperText>\n {maxLength && (\n <FormHelperText sx={{fontVariantNumeric: 'tabular-nums', whiteSpace: 'nowrap'}}>\n {t('counter', {count: characters, max: maxLength})}\n </FormHelperText>\n )}\n </EditorFooter>\n </div>\n </FieldFrame>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAkCA,MAAM,aAAa;AACnB,MAAM,aAAa,UAAU,YAAY,QAAQ,KAAK;AACtD,MAAM,gBAAgB,UAAU,YAAY,WAAW,KAAK;AAC5D,MAAM,oBAAoB,UAAU,YAAY,WAAW,GAAG;AAC9D,MAAM,eAAe,UAAU,YAAY,UAAU,KAAK;AAE1D,MAAM,qBAAqB;AAsB3B,SAAwB,eAAe,OAAO;AAC1C,QAAM;AAAA,IACF;AAAA,IAAM;AAAA,IAAO;AAAA,IAAO;AAAA,IAAU;AAAA,IAAQ;AAAA,IAAa;AAAA,IAAO,aAAa;AAAA,IAAK;AAAA,IAAW,WAAW;AAAA,IAA4B;AAAA,IAC9H;AAAA,IAAgB;AAAA,IAAe,YAAY;AAAA,IAAoB,WAAW;AAAA,IAAO;AAAA,IAAI;AAAA,IACrF,GAAG;AAAA,EAAA,IACH,cAAc,OAAO,UAAU;AACnC,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,YAAY,KAAK;AACnD,QAAM,cAAc,MAAA;AACpB,QAAM,YAAY,GAAG,QAAQ,WAAW,IAAI,WAAW;AACvD,QAAM,UAAU,GAAG,SAAS;AAC5B,QAAM,YAAY,2BAA2B,GAAG,KAAK;AAErD,QAAM,SAAS,OAAO,EAAC,UAAU,QAAQ,eAAc;AACvD,SAAO,UAAU,EAAC,UAAU,QAAQ,cAAA;AAEpC,QAAM,SAAS,UAAU;AAAA,IACrB,YAAY,qBAAqB,EAAC,UAAU,aAAa,WAAW,YAAW;AAAA,IAC/E,SAAS,SAAS;AAAA,IAClB,UAAU,CAAC;AAAA;AAAA,IAEX,mBAAmB;AAAA,IACnB,aAAa;AAAA,MACT,YAAY,EAAC,IAAI,WAAW,MAAM,WAAW,kBAAkB,QAAQ,mBAAmB,SAAS,GAAI,aAAa,EAAC,gBAAgB,SAAM;AAAA,IAAE;AAAA,IAEjJ,UAAU,CAAC,EAAC,QAAQ,QAAA,MAAa,OAAO,QAAQ,SAAS,iBAAiB,QAAQ,QAAA,CAAS,CAAC;AAAA,IAC5F,QAAQ,MAAM,OAAO,QAAQ,SAAA;AAAA,IAC7B,UAAU,CAAC,EAAC,QAAQ,cAAa,OAAO,QAAQ,gBAAgB,OAAO;AAAA,EAAA,GACxE,CAAC,SAAS,KAAK,GAAG,GAAG,aAAa,WAAW,QAAQ,SAAS,CAAC,CAAC;AAGnE,YAAU,MAAM;AACZ,QAAI,UAAU,iBAAiB,OAAO,SAAS,OAAO,SAAS,KAAK;AAChE,aAAO,SAAS,WAAW,SAAS,IAAI,EAAC,YAAY,OAAM;AAAA,IAC/D;AAAA,EACJ,GAAG,CAAC,QAAQ,KAAK,CAAC;AAClB,YAAU,MAAM;AACZ,YAAQ,YAAY,CAAC,QAAQ;AAAA,EACjC,GAAG,CAAC,QAAQ,QAAQ,CAAC;AAErB,QAAM,aAAa,eAAe,EAAC,QAAQ,UAAU,CAAC,EAAC,QAAQ,QAAA,MAAa,SAAS,QAAQ,gBAAgB,WAAA,KAAgB,GAAE;AAE/H,6BACK,YAAA,EAAW,SAAS,WAAW,SAAkB,OAC9C,+BAAC,OAAA,EACG,UAAA;AAAA,IAAA,qBAAC,YAAA,EAAW,SAAQ,YAAW,OAAO,CAAC,WAAW;AAAA,MAC9C,cAAc;AAAA,MAAG,UAAU;AAAA,MAAU,SAAS,WAAW,MAAM;AAAA,MAC/D,aAAa,YAAY,eAAe;AAAA,MACxC,kBAAkB,EAAC,aAAa,YAAY,eAAe,gBAAgB,WAAW,cAAc,MAAM,QAAQ,OAAO,QAAQ,YAAY,UAAU,SAAS,EAAE,IAAI,GAAA;AAAA,IAAE,IACxK,IACA,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UAAc,MAAK;AAAA,UAAU,cAAY,EAAE,eAAe;AAAA,UAAG,iBAAe;AAAA,UAAW,WAAU;AAAA,UACnF,OAAO,EAAC,YAAY,UAAU,UAAU,QAAQ,KAAK,MAAM,IAAI,KAAK,IAAI,KAAK,cAAc,GAAG,aAAa,UAAA;AAAA,UACtH,8BAAC,iBAAA,EAAgB,QAAgB,UAAoB,UAAoB,GAAM,SAAS,eAAA,CAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,MAE5G,oBAAC,mBAAA,EAAkB,OAAO,CAAC,UAAU;AACjC,cAAM,UAAU,oBAAoB,KAAK;AACzC,eAAO,EAAC,GAAG,SAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,aAAa,EAAC,GAAG,QAAQ,WAAW,GAAG,YAAS;AAAA,MACxG,GAAG,SAAS,MAAM,QAAQ,SAAS,SAC/B,UAAA,oBAAC,eAAA,EAAc,OAAA,CAAgB,EAAA,CACnC;AAAA,IAAA,GACJ;AAAA,IACA,qBAAC,cAAA,EAAa,WAAU,OAAM,OAAO,EAAC,gBAAgB,iBAAiB,KAAK,EAAA,GACxE,UAAA;AAAA,MAAA,oBAAC,kBAAe,OAAO,QAAQ,SAAS,GAAI,uBAAa,YAAW;AAAA,MACnE,aACG,oBAAC,gBAAA,EAAe,IAAI,EAAC,oBAAoB,gBAAgB,YAAY,SAAA,GAChE,UAAA,EAAE,WAAW,EAAC,OAAO,YAAY,KAAK,UAAA,CAAU,EAAA,CACrD;AAAA,IAAA,EAAA,CAER;AAAA,EAAA,EAAA,CACJ,EAAA,CACJ;AAER;"}
@@ -0,0 +1,57 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import Button from "@mui/material/Button";
5
+ import Popover from "@mui/material/Popover";
6
+ import Stack from "@mui/material/Stack";
7
+ import TextInput from "../inputs/TextInput.js";
8
+ import { linkUrlOf } from "./richTextRules.js";
9
+ function RichTextLinkPopover({ anchorElement, initialUrl, onSave, onRemove, onClose, t }) {
10
+ const [typedUrl, setTypedUrl] = useState(initialUrl);
11
+ const [isRejected, setIsRejected] = useState(false);
12
+ const save = () => {
13
+ const url = linkUrlOf(typedUrl);
14
+ if (!url) {
15
+ setIsRejected(true);
16
+ return;
17
+ }
18
+ onSave(url);
19
+ };
20
+ return /* @__PURE__ */ jsx(
21
+ Popover,
22
+ {
23
+ open: Boolean(anchorElement),
24
+ anchorEl: anchorElement,
25
+ onClose,
26
+ anchorOrigin: { vertical: "bottom", horizontal: "left" },
27
+ slotProps: { paper: { sx: { p: 2, width: 340, maxWidth: "calc(100vw - 32px)" } } },
28
+ children: /* @__PURE__ */ jsxs("form", { noValidate: true, onSubmit: (event) => {
29
+ event.preventDefault();
30
+ save();
31
+ }, children: [
32
+ /* @__PURE__ */ jsx(
33
+ TextInput,
34
+ {
35
+ label: t("linkDialog.url"),
36
+ value: typedUrl,
37
+ autoFocus: true,
38
+ placeholder: "https://",
39
+ onChange: (value) => {
40
+ setTypedUrl(value);
41
+ setIsRejected(false);
42
+ },
43
+ error: isRejected ? t("linkDialog.invalid") : void 0
44
+ }
45
+ ),
46
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", sx: { gap: 1, justifyContent: "flex-end" }, children: [
47
+ initialUrl && /* @__PURE__ */ jsx(Button, { color: "error", onClick: onRemove, children: t("linkDialog.remove") }),
48
+ /* @__PURE__ */ jsx(Button, { type: "submit", variant: "contained", children: t("linkDialog.save") })
49
+ ] })
50
+ ] })
51
+ }
52
+ );
53
+ }
54
+ export {
55
+ RichTextLinkPopover as default
56
+ };
57
+ //# sourceMappingURL=RichTextLinkPopover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RichTextLinkPopover.js","sources":["../../src/richText/RichTextLinkPopover.jsx"],"sourcesContent":["// La ventanita para poner o cambiar la liga del texto elegido: la dirección (solo https, http, mailto o tel; un dominio suelto\n// se completa con https://), «Poner la liga» y «Quitar». Una dirección que no se acepta se dice en su campo.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Button from '@mui/material/Button';\nimport Popover from '@mui/material/Popover';\nimport Stack from '@mui/material/Stack';\n\nimport TextInput from '@/inputs/TextInput.jsx';\nimport {linkUrlOf} from '@/richText/richTextRules.js';\n\n/**\n * @param {object} props\n * @param {HTMLElement|null} props.anchorElement el botón de la liga (null: cerrada)\n * @param {string} props.initialUrl la liga que ya tiene el texto ('' si no tiene)\n * @param {(url: string) => void} props.onSave recibe la dirección ya revisada\n * @param {() => void} props.onRemove\n * @param {() => void} props.onClose\n * @param {(key: string) => string} props.t el traductor del editor\n */\nexport default function RichTextLinkPopover({anchorElement, initialUrl, onSave, onRemove, onClose, t}) {\n const [typedUrl, setTypedUrl] = useState(initialUrl);\n const [isRejected, setIsRejected] = useState(false);\n\n const save = () => {\n const url = linkUrlOf(typedUrl);\n if (!url) {\n setIsRejected(true);\n return;\n }\n onSave(url);\n };\n\n return (\n <Popover open={Boolean(anchorElement)} anchorEl={anchorElement} onClose={onClose}\n anchorOrigin={{vertical: 'bottom', horizontal: 'left'}} slotProps={{paper: {sx: {p: 2, width: 340, maxWidth: 'calc(100vw - 32px)'}}}}>\n <form noValidate onSubmit={(event) => {\n event.preventDefault();\n save();\n }}>\n <TextInput label={t('linkDialog.url')} value={typedUrl} autoFocus placeholder=\"https://\"\n onChange={(value) => {\n setTypedUrl(value);\n setIsRejected(false);\n }}\n error={isRejected ? t('linkDialog.invalid') : undefined} />\n <Stack direction=\"row\" sx={{gap: 1, justifyContent: 'flex-end'}}>\n {initialUrl && <Button color=\"error\" onClick={onRemove}>{t('linkDialog.remove')}</Button>}\n <Button type=\"submit\" variant=\"contained\">{t('linkDialog.save')}</Button>\n </Stack>\n </form>\n </Popover>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AAqBA,SAAwB,oBAAoB,EAAC,eAAe,YAAY,QAAQ,UAAU,SAAS,KAAI;AACnG,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,UAAU;AACnD,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAElD,QAAM,OAAO,MAAM;AACf,UAAM,MAAM,UAAU,QAAQ;AAC9B,QAAI,CAAC,KAAK;AACN,oBAAc,IAAI;AAClB;AAAA,IACJ;AACA,WAAO,GAAG;AAAA,EACd;AAEA,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MAAQ,MAAM,QAAQ,aAAa;AAAA,MAAG,UAAU;AAAA,MAAe;AAAA,MACvD,cAAc,EAAC,UAAU,UAAU,YAAY,OAAA;AAAA,MAAS,WAAW,EAAC,OAAO,EAAC,IAAI,EAAC,GAAG,GAAG,OAAO,KAAK,UAAU,qBAAA,IAAqB;AAAA,MACvI,+BAAC,QAAA,EAAK,YAAU,MAAC,UAAU,CAAC,UAAU;AAClC,cAAM,eAAA;AACN,aAAA;AAAA,MACJ,GACI,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YAAU,OAAO,EAAE,gBAAgB;AAAA,YAAG,OAAO;AAAA,YAAU,WAAS;AAAA,YAAC,aAAY;AAAA,YACnE,UAAU,CAAC,UAAU;AACjB,0BAAY,KAAK;AACjB,4BAAc,KAAK;AAAA,YACvB;AAAA,YACA,OAAO,aAAa,EAAE,oBAAoB,IAAI;AAAA,UAAA;AAAA,QAAA;AAAA,QACzD,qBAAC,OAAA,EAAM,WAAU,OAAM,IAAI,EAAC,KAAK,GAAG,gBAAgB,WAAA,GAC/C,UAAA;AAAA,UAAA,cAAc,oBAAC,UAAO,OAAM,SAAQ,SAAS,UAAW,UAAA,EAAE,mBAAmB,EAAA,CAAE;AAAA,UAChF,oBAAC,UAAO,MAAK,UAAS,SAAQ,aAAa,UAAA,EAAE,iBAAiB,EAAA,CAAE;AAAA,QAAA,EAAA,CACpE;AAAA,MAAA,EAAA,CACJ;AAAA,IAAA;AAAA,EAAA;AAGZ;"}