@stackcraftmx/calcita 0.32.2 → 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 (336) 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/table.js +2 -0
  166. package/dist/table.js.map +1 -1
  167. package/dist/theme/components/glassComponents.js +27 -0
  168. package/dist/theme/components/glassComponents.js.map +1 -1
  169. package/dist/theme/components/minimalComponents.js +12 -0
  170. package/dist/theme/components/minimalComponents.js.map +1 -1
  171. package/dist/types/DataTable/ServerTableFilterDrawer.d.ts +21 -0
  172. package/dist/types/DataTable/filterContext.d.ts +2 -1
  173. package/dist/types/DataTable/goToPageOptions.d.ts +15 -0
  174. package/dist/types/DataTable/index.d.ts +1 -0
  175. package/dist/types/date-pickers.d.ts +10 -1
  176. package/dist/types/datePickers/DateInput.d.ts +6 -4
  177. package/dist/types/datePickers/DateTimeInput.d.ts +50 -0
  178. package/dist/types/datePickers/FormDateTimeField.d.ts +7 -0
  179. package/dist/types/datePickers/FormMonthField.d.ts +7 -0
  180. package/dist/types/datePickers/FormTimeField.d.ts +7 -0
  181. package/dist/types/datePickers/MonthInput.d.ts +39 -0
  182. package/dist/types/datePickers/PickerFrame.d.ts +22 -0
  183. package/dist/types/datePickers/TimeInput.d.ts +38 -0
  184. package/dist/types/datePickers/dateTimeRules.d.ts +31 -0
  185. package/dist/types/datePickers/pickerValues.d.ts +114 -0
  186. package/dist/types/datePickers/useCurrentMinute.d.ts +5 -0
  187. package/dist/types/datePickers/usePickerField.d.ts +24 -0
  188. package/dist/types/dictionaries/dictionaries.d.ts +6 -3
  189. package/dist/types/forms/FormAttachmentsField.d.ts +7 -0
  190. package/dist/types/forms/FormCheckboxGroupField.d.ts +7 -0
  191. package/dist/types/forms/FormFileField.d.ts +7 -0
  192. package/dist/types/forms/FormFileUploadField.d.ts +7 -0
  193. package/dist/types/forms/FormImageField.d.ts +7 -0
  194. package/dist/types/forms/FormMaskedField.d.ts +7 -0
  195. package/dist/types/forms/FormRepeatingFields.d.ts +25 -0
  196. package/dist/types/forms/FormTransferListField.d.ts +7 -0
  197. package/dist/types/forms/index.d.ts +10 -1
  198. package/dist/types/forms/listRules.d.ts +48 -0
  199. package/dist/types/forms/serverProblemFields.d.ts +13 -0
  200. package/dist/types/forms.d.ts +1 -1
  201. package/dist/types/hookForm/FormAttachmentsField.d.ts +8 -0
  202. package/dist/types/hookForm/FormCheckboxGroupField.d.ts +8 -0
  203. package/dist/types/hookForm/FormFileField.d.ts +8 -0
  204. package/dist/types/hookForm/FormFileUploadField.d.ts +8 -0
  205. package/dist/types/hookForm/FormImageField.d.ts +8 -0
  206. package/dist/types/hookForm/FormMaskedField.d.ts +9 -0
  207. package/dist/types/hookForm/FormRepeatingFields.d.ts +27 -0
  208. package/dist/types/hookForm/FormTransferListField.d.ts +8 -0
  209. package/dist/types/index.d.ts +25 -3
  210. package/dist/types/inputs/CatalogInput.d.ts +7 -1
  211. package/dist/types/inputs/CheckboxGroupInput.d.ts +39 -0
  212. package/dist/types/inputs/MaskedInput.d.ts +35 -0
  213. package/dist/types/inputs/RepeatingFields.d.ts +52 -0
  214. package/dist/types/inputs/SelectInput.d.ts +6 -1
  215. package/dist/types/inputs/TransferListInput.d.ts +43 -0
  216. package/dist/types/inputs/inputMasks.d.ts +52 -0
  217. package/dist/types/inputs/selectAllState.d.ts +11 -0
  218. package/dist/types/inputs/useRowKeys.d.ts +11 -0
  219. package/dist/types/legal/CookieNotice.d.ts +30 -0
  220. package/dist/types/legal/TermsAcceptanceDialog.d.ts +32 -0
  221. package/dist/types/legal/consentStorage.d.ts +16 -0
  222. package/dist/types/legal/useCookieConsent.d.ts +13 -0
  223. package/dist/types/locales/en.d.ts +232 -0
  224. package/dist/types/locales/es.d.ts +232 -0
  225. package/dist/types/mexico/CfdiSummary.d.ts +17 -0
  226. package/dist/types/mexico/EfirmaFields.d.ts +38 -0
  227. package/dist/types/mexico/certificateReader.d.ts +37 -0
  228. package/dist/types/mexico/cfdiReader.d.ts +95 -0
  229. package/dist/types/mexico/derReader.d.ts +54 -0
  230. package/dist/types/mexico/efirmaKey.d.ts +26 -0
  231. package/dist/types/mexico/mexicoIdentifiers.d.ts +61 -0
  232. package/dist/types/mexico/mexicoRules.d.ts +29 -0
  233. package/dist/types/mexico.d.ts +11 -0
  234. package/dist/types/react-hook-form.d.ts +10 -1
  235. package/dist/types/rich-text.d.ts +5 -0
  236. package/dist/types/richText/FormRichTextField.d.ts +7 -0
  237. package/dist/types/richText/RichTextEditor.d.ts +42 -0
  238. package/dist/types/richText/RichTextLinkPopover.d.ts +17 -0
  239. package/dist/types/richText/RichTextToolbar.d.ts +15 -0
  240. package/dist/types/richText/RichTextView.d.ts +13 -0
  241. package/dist/types/richText/richTextContentSx.d.ts +7 -0
  242. package/dist/types/richText/richTextExtensions.d.ts +15 -0
  243. package/dist/types/richText/richTextRules.d.ts +41 -0
  244. package/dist/types/table.d.ts +1 -1
  245. package/dist/types/ui/actions/ActionsMenu.d.ts +18 -3
  246. package/dist/types/ui/actions/CopyButton.d.ts +7 -4
  247. package/dist/types/ui/actions/tableRowText.d.ts +6 -0
  248. package/dist/types/ui/cards/RecordCard.d.ts +65 -0
  249. package/dist/types/ui/cards/RecordCardSkeleton.d.ts +17 -0
  250. package/dist/types/ui/countdown/Countdown.d.ts +31 -0
  251. package/dist/types/ui/countdown/countdownParts.d.ts +39 -0
  252. package/dist/types/ui/countdown/useCountdown.d.ts +14 -0
  253. package/dist/types/ui/documents/PdfViewerDialog.d.ts +21 -0
  254. package/dist/types/ui/filters/FilterDrawer.d.ts +34 -0
  255. package/dist/types/ui/filters/filterDrawerFields.d.ts +139 -0
  256. package/dist/types/ui/help/HelpButton.d.ts +15 -0
  257. package/dist/types/ui/help/HelpCarouselDialog.d.ts +35 -0
  258. package/dist/types/ui/help/useHelpCarousel.d.ts +21 -0
  259. package/dist/types/ui/index.d.ts +10 -0
  260. package/dist/types/ui/labels/IconBadge.d.ts +34 -0
  261. package/dist/types/ui/navigation/RouteTabs.d.ts +44 -0
  262. package/dist/types/ui/navigation/routeTabMatching.d.ts +27 -0
  263. package/dist/types/upload/AttachmentsInput.d.ts +62 -0
  264. package/dist/types/upload/FileChip.d.ts +18 -0
  265. package/dist/types/upload/FileDropzone.d.ts +3 -0
  266. package/dist/types/upload/FileInput.d.ts +48 -0
  267. package/dist/types/upload/FileUploadInput.d.ts +80 -0
  268. package/dist/types/upload/ImageInput.d.ts +53 -0
  269. package/dist/types/upload/TemplateDownloadButton.d.ts +39 -0
  270. package/dist/types/upload/fileAppearance.d.ts +8 -0
  271. package/dist/types/upload/fileRules.d.ts +38 -0
  272. package/dist/types/upload/transferProgress.d.ts +18 -0
  273. package/dist/types/upload/uploadMachine.d.ts +6 -2
  274. package/dist/types/upload/uploadWithProgress.d.ts +6 -2
  275. package/dist/types/upload/useFilePicker.d.ts +39 -0
  276. package/dist/ui/actions/ActionsMenu.js +98 -15
  277. package/dist/ui/actions/ActionsMenu.js.map +1 -1
  278. package/dist/ui/actions/CopyButton.js +31 -11
  279. package/dist/ui/actions/CopyButton.js.map +1 -1
  280. package/dist/ui/actions/tableRowText.js +7 -0
  281. package/dist/ui/actions/tableRowText.js.map +1 -0
  282. package/dist/ui/cards/RecordCard.js +145 -0
  283. package/dist/ui/cards/RecordCard.js.map +1 -0
  284. package/dist/ui/cards/RecordCardSkeleton.js +33 -0
  285. package/dist/ui/cards/RecordCardSkeleton.js.map +1 -0
  286. package/dist/ui/countdown/Countdown.js +38 -0
  287. package/dist/ui/countdown/Countdown.js.map +1 -0
  288. package/dist/ui/countdown/countdownParts.js +34 -0
  289. package/dist/ui/countdown/countdownParts.js.map +1 -0
  290. package/dist/ui/countdown/useCountdown.js +35 -0
  291. package/dist/ui/countdown/useCountdown.js.map +1 -0
  292. package/dist/ui/documents/PdfViewerDialog.js +81 -0
  293. package/dist/ui/documents/PdfViewerDialog.js.map +1 -0
  294. package/dist/ui/filters/FilterDrawer.js +211 -0
  295. package/dist/ui/filters/FilterDrawer.js.map +1 -0
  296. package/dist/ui/filters/filterDrawerFields.js +119 -0
  297. package/dist/ui/filters/filterDrawerFields.js.map +1 -0
  298. package/dist/ui/help/HelpButton.js +17 -0
  299. package/dist/ui/help/HelpButton.js.map +1 -0
  300. package/dist/ui/help/HelpCarouselDialog.js +154 -0
  301. package/dist/ui/help/HelpCarouselDialog.js.map +1 -0
  302. package/dist/ui/help/useHelpCarousel.js +25 -0
  303. package/dist/ui/help/useHelpCarousel.js.map +1 -0
  304. package/dist/ui/labels/IconBadge.js +82 -0
  305. package/dist/ui/labels/IconBadge.js.map +1 -0
  306. package/dist/ui/navigation/RouteTabs.js +75 -0
  307. package/dist/ui/navigation/RouteTabs.js.map +1 -0
  308. package/dist/ui/navigation/routeTabMatching.js +23 -0
  309. package/dist/ui/navigation/routeTabMatching.js.map +1 -0
  310. package/dist/upload/AttachmentsInput.js +127 -0
  311. package/dist/upload/AttachmentsInput.js.map +1 -0
  312. package/dist/upload/FileChip.js +27 -0
  313. package/dist/upload/FileChip.js.map +1 -0
  314. package/dist/upload/FileDropzone.js +19 -84
  315. package/dist/upload/FileDropzone.js.map +1 -1
  316. package/dist/upload/FileInput.js +112 -0
  317. package/dist/upload/FileInput.js.map +1 -0
  318. package/dist/upload/FileUploadInput.js +285 -0
  319. package/dist/upload/FileUploadInput.js.map +1 -0
  320. package/dist/upload/ImageInput.js +125 -0
  321. package/dist/upload/ImageInput.js.map +1 -0
  322. package/dist/upload/TemplateDownloadButton.js +67 -0
  323. package/dist/upload/TemplateDownloadButton.js.map +1 -0
  324. package/dist/upload/fileAppearance.js +21 -0
  325. package/dist/upload/fileAppearance.js.map +1 -0
  326. package/dist/upload/fileRules.js +27 -1
  327. package/dist/upload/fileRules.js.map +1 -1
  328. package/dist/upload/transferProgress.js +23 -0
  329. package/dist/upload/transferProgress.js.map +1 -0
  330. package/dist/upload/uploadMachine.js +8 -8
  331. package/dist/upload/uploadMachine.js.map +1 -1
  332. package/dist/upload/uploadWithProgress.js +1 -1
  333. package/dist/upload/uploadWithProgress.js.map +1 -1
  334. package/dist/upload/useFilePicker.js +101 -0
  335. package/dist/upload/useFilePicker.js.map +1 -0
  336. package/package.json +44 -1
@@ -0,0 +1,145 @@
1
+ "use client";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import { useId, useState } from "react";
4
+ import Avatar from "@mui/material/Avatar";
5
+ import Box from "@mui/material/Box";
6
+ import Button from "@mui/material/Button";
7
+ import Collapse from "@mui/material/Collapse";
8
+ import IconButton from "@mui/material/IconButton";
9
+ import Paper from "@mui/material/Paper";
10
+ import Stack from "@mui/material/Stack";
11
+ import Tooltip from "@mui/material/Tooltip";
12
+ import Typography from "@mui/material/Typography";
13
+ import ExpandMoreRoundedIcon from "@mui/icons-material/ExpandMoreRounded";
14
+ import OpenInNewRoundedIcon from "@mui/icons-material/OpenInNewRounded";
15
+ import { initialsOf } from "../../appShell/menuItemText.js";
16
+ import { piecePart, usePieceProps } from "../../theme/themePieces.js";
17
+ import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
18
+ import { warnUnknownProps } from "../../toolkit/unknownProps.js";
19
+ import ActionsMenu from "../actions/ActionsMenu.js";
20
+ const THEME_NAME = "CalcitaRecordCard";
21
+ const RecordCardRoot = piecePart(THEME_NAME, "Root", Paper);
22
+ const RecordCardHeader = piecePart(THEME_NAME, "Header", Stack);
23
+ const RecordCardAvatar = piecePart(THEME_NAME, "Avatar", Avatar);
24
+ const RecordCardTitles = piecePart(THEME_NAME, "Titles", Box);
25
+ const RecordCardStatus = piecePart(THEME_NAME, "Status", Stack);
26
+ const RecordCardBody = piecePart(THEME_NAME, "Body", Box);
27
+ const RecordCardGroup = piecePart(THEME_NAME, "Group", Box);
28
+ const RecordCardFact = piecePart(THEME_NAME, "Fact", Box);
29
+ const RecordCardHighlight = piecePart(THEME_NAME, "Highlight", Box);
30
+ const RecordCardFooter = piecePart(THEME_NAME, "Footer", Stack);
31
+ const RecordCardDetails = piecePart(THEME_NAME, "Details", Box);
32
+ function RecordCard(props) {
33
+ const {
34
+ title,
35
+ eyebrow,
36
+ subtitle,
37
+ avatar,
38
+ status,
39
+ actions,
40
+ groups = [],
41
+ highlight,
42
+ trailing,
43
+ columns,
44
+ footer,
45
+ details,
46
+ detailsLabel,
47
+ defaultDetailsOpen = false,
48
+ onDetailsToggle,
49
+ onOpen,
50
+ openLabel,
51
+ header,
52
+ children,
53
+ sx,
54
+ texts,
55
+ ...unknownProps
56
+ } = usePieceProps(props, THEME_NAME);
57
+ warnUnknownProps(THEME_NAME, unknownProps);
58
+ const { t } = useToolkitTranslation("common", texts);
59
+ const titleId = useId();
60
+ const detailsId = useId();
61
+ const [isDetailsOpen, setIsDetailsOpen] = useState(defaultDetailsOpen);
62
+ const toggleDetails = () => {
63
+ setIsDetailsOpen((current) => !current);
64
+ onDetailsToggle?.(!isDetailsOpen);
65
+ };
66
+ const hasBody = groups.length > 0 || highlight || trailing;
67
+ const desktopColumns = columns ?? `${groups.length > 0 ? `repeat(${groups.length}, minmax(0, 1fr))` : ""}${highlight ? " auto" : ""}${trailing ? " auto" : ""}`.trim();
68
+ return /* @__PURE__ */ jsxs(RecordCardRoot, { variant: "outlined", component: "article", "aria-labelledby": titleId, ownSx: { p: { xs: 2, sm: 2.5 }, minWidth: 0, ...sx }, children: [
69
+ header ?? /* @__PURE__ */ jsxs(RecordCardHeader, { direction: "row", ownSx: { gap: 1.5, alignItems: "flex-start", flexWrap: { xs: "wrap", sm: "nowrap" } }, children: [
70
+ avatar && /* @__PURE__ */ jsx(RecordCardAvatar, { ownSx: { width: 44, height: 44, bgcolor: "action.selected", color: "text.primary", fontSize: 16, fontWeight: 600 }, children: typeof avatar === "string" ? initialsOf(avatar) : avatar }),
71
+ /* @__PURE__ */ jsxs(RecordCardTitles, { ownSx: { flex: 1, minWidth: 0, order: 1 }, children: [
72
+ eyebrow && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", component: "p", sx: { fontVariantNumeric: "tabular-nums" }, children: eyebrow }),
73
+ /* @__PURE__ */ jsx(Typography, { id: titleId, variant: "subtitle1", component: "h3", sx: { fontWeight: 600, overflowWrap: "anywhere" }, children: title }),
74
+ subtitle && /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: subtitle })
75
+ ] }),
76
+ status && /* @__PURE__ */ jsx(RecordCardStatus, { direction: "row", ownSx: {
77
+ gap: 0.75,
78
+ alignItems: "center",
79
+ flexWrap: "wrap",
80
+ order: { xs: 3, sm: 2 },
81
+ flexBasis: { xs: "100%", sm: "auto" },
82
+ justifyContent: { xs: "flex-start", sm: "flex-end" },
83
+ maxWidth: { sm: "50%" }
84
+ }, children: status }),
85
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", sx: { gap: 0.25, alignItems: "center", order: { xs: 2, sm: 3 }, flexShrink: 0 }, children: [
86
+ onOpen && /* @__PURE__ */ jsx(Tooltip, { title: openLabel ?? t("recordCard.open"), children: /* @__PURE__ */ jsx(IconButton, { size: "small", "aria-label": openLabel ?? t("recordCard.open"), onClick: onOpen, children: /* @__PURE__ */ jsx(OpenInNewRoundedIcon, { fontSize: "small" }) }) }),
87
+ actions?.length > 0 && /* @__PURE__ */ jsx(ActionsMenu, { label: t("recordCard.actions"), actions, size: "small" })
88
+ ] })
89
+ ] }),
90
+ hasBody && /* @__PURE__ */ jsxs(RecordCardBody, { ownSx: {
91
+ mt: 2,
92
+ display: "grid",
93
+ gap: { xs: 1.5, md: 3 },
94
+ alignItems: "start",
95
+ // en escritorio los grupos lado a lado y el dato principal al final; en el teléfono, uno debajo de otro
96
+ gridTemplateColumns: { xs: "1fr", md: desktopColumns }
97
+ }, children: [
98
+ groups.map((group, groupIndex) => /* @__PURE__ */ jsxs(RecordCardGroup, { ownSx: {
99
+ minWidth: 0,
100
+ pt: { xs: groupIndex > 0 ? 1.5 : 0, md: 0 },
101
+ borderTop: { xs: groupIndex > 0 ? 1 : 0, md: 0 },
102
+ borderColor: "divider"
103
+ }, children: [
104
+ group.title && /* @__PURE__ */ jsx(Typography, { variant: "overline", color: "text.secondary", component: "p", sx: { lineHeight: 1.8 }, children: group.title }),
105
+ group.content ?? /* @__PURE__ */ jsx(Box, { component: "dl", sx: { m: 0, display: "grid", gridTemplateColumns: "auto 1fr", columnGap: 1.5, rowGap: 0.5 }, children: (group.facts ?? []).map((fact, factIndex) => /* @__PURE__ */ jsxs(RecordCardFact, { ownSx: { display: "contents" }, children: [
106
+ /* @__PURE__ */ jsx(Typography, { component: "dt", variant: "body2", color: "text.secondary", children: fact.label }),
107
+ /* @__PURE__ */ jsx(Typography, { component: "dd", variant: "body2", sx: { m: 0, textAlign: "right", fontVariantNumeric: "tabular-nums", fontWeight: fact.emphasis ? 600 : 400, overflowWrap: "anywhere" }, children: fact.value })
108
+ ] }, factIndex)) })
109
+ ] }, group.key ?? groupIndex)),
110
+ highlight && /* @__PURE__ */ jsxs(RecordCardHighlight, { ownSx: {
111
+ textAlign: { xs: "left", md: "right" },
112
+ pl: { md: 3 },
113
+ borderLeft: { md: 1 },
114
+ borderTop: { xs: 1, md: 0 },
115
+ pt: { xs: 1.5, md: 0 },
116
+ borderColor: "divider"
117
+ }, children: [
118
+ /* @__PURE__ */ jsx(Typography, { variant: "overline", color: "text.secondary", component: "p", sx: { lineHeight: 1.8 }, children: highlight.label }),
119
+ /* @__PURE__ */ jsx(Typography, { variant: "h5", component: "p", sx: { fontWeight: 700, fontVariantNumeric: "tabular-nums", whiteSpace: "nowrap" }, children: highlight.value }),
120
+ highlight.caption && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", component: "p", children: highlight.caption })
121
+ ] }),
122
+ trailing && /* @__PURE__ */ jsx(Box, { sx: { minWidth: 0, alignSelf: "center", borderTop: { xs: 1, md: 0 }, pt: { xs: 1.5, md: 0 }, borderColor: "divider" }, children: trailing })
123
+ ] }),
124
+ children,
125
+ (footer || details) && /* @__PURE__ */ jsxs(RecordCardFooter, { direction: "row", ownSx: { mt: 2, gap: 1, alignItems: "center", flexWrap: "wrap" }, children: [
126
+ /* @__PURE__ */ jsx(Box, { sx: { flex: 1, minWidth: 0 }, children: footer }),
127
+ details && /* @__PURE__ */ jsx(
128
+ Button,
129
+ {
130
+ size: "small",
131
+ onClick: toggleDetails,
132
+ "aria-expanded": isDetailsOpen,
133
+ "aria-controls": detailsId,
134
+ endIcon: /* @__PURE__ */ jsx(ExpandMoreRoundedIcon, { sx: { transform: isDetailsOpen ? "rotate(180deg)" : "none", transition: "transform 200ms" } }),
135
+ children: isDetailsOpen ? t("recordCard.hideDetails") : detailsLabel ?? t("recordCard.showDetails")
136
+ }
137
+ )
138
+ ] }),
139
+ details && /* @__PURE__ */ jsx(Collapse, { in: isDetailsOpen, unmountOnExit: true, children: /* @__PURE__ */ jsx(RecordCardDetails, { id: detailsId, ownSx: { mt: 2, pt: 2, borderTop: 1, borderColor: "divider" }, children: details }) })
140
+ ] });
141
+ }
142
+ export {
143
+ RecordCard as default
144
+ };
145
+ //# sourceMappingURL=RecordCard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecordCard.js","sources":["../../../src/ui/cards/RecordCard.jsx"],"sourcesContent":["// La tarjeta de un registro (un pedido, un cliente, una solicitud) para listas donde una tabla se queda corta: cada registro\n// con su identidad arriba, sus datos agrupados en el cuerpo y lo que se puede hacer con él. Para una lista de tarjetas,\n// una debajo de otra; con RecordCardSkeleton mientras carga.\n//\n// encabezado avatar (iniciales o ícono), eyebrow (el folio), title, subtitle; a la derecha status (estatus e\n// insignias) y el menú «⋯» (actions)\n// cuerpo groups: grupos de datos {title?, facts: [{label, value}]} lado a lado en escritorio y uno debajo de otro en\n// el teléfono; highlight: el dato principal, grande (el total)\n// abajo footer (botones, una cuenta regresiva, un formulario corto) y details: lo que se despliega con «Ver\n// detalle» (una tabla, un historial), que avisa con onDetailsToggle\n//\n// El ORDEN es el que se da y nada se reacomoda solo: los grupos de izquierda a derecha (de arriba abajo en el teléfono) y\n// los datos de cada grupo en el orden de facts. Para un orden obligatorio (el de un sistema que ya existe, donde el estatus\n// va después de las fechas), trailing es la última columna del cuerpo y columns fija el ancho de cada una.\n//\n// La tarjeta NO se pica entera (la regla de la casa: una acción, un botón): para abrir el registro, onOpen pone su botón.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaRecordCard con defaultProps y\n// styleOverrides de sus partes: root, header, avatar, titles, status, body, group, fact, highlight, footer, details.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useId, useState} from 'react';\nimport Avatar from '@mui/material/Avatar';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Collapse from '@mui/material/Collapse';\nimport IconButton from '@mui/material/IconButton';\nimport Paper from '@mui/material/Paper';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport ExpandMoreRoundedIcon from '@mui/icons-material/ExpandMoreRounded';\nimport OpenInNewRoundedIcon from '@mui/icons-material/OpenInNewRounded';\n\nimport {initialsOf} from '@/appShell/menuItemText.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport ActionsMenu from '@/ui/actions/ActionsMenu.jsx';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaRecordCard)\nconst THEME_NAME = 'CalcitaRecordCard';\nconst RecordCardRoot = piecePart(THEME_NAME, 'Root', Paper);\nconst RecordCardHeader = piecePart(THEME_NAME, 'Header', Stack);\nconst RecordCardAvatar = piecePart(THEME_NAME, 'Avatar', Avatar);\nconst RecordCardTitles = piecePart(THEME_NAME, 'Titles', Box);\nconst RecordCardStatus = piecePart(THEME_NAME, 'Status', Stack);\nconst RecordCardBody = piecePart(THEME_NAME, 'Body', Box);\nconst RecordCardGroup = piecePart(THEME_NAME, 'Group', Box);\nconst RecordCardFact = piecePart(THEME_NAME, 'Fact', Box);\nconst RecordCardHighlight = piecePart(THEME_NAME, 'Highlight', Box);\nconst RecordCardFooter = piecePart(THEME_NAME, 'Footer', Stack);\nconst RecordCardDetails = piecePart(THEME_NAME, 'Details', Box);\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode} props.title el nombre del registro, ya traducido\n * @param {import('react').ReactNode} [props.eyebrow] arriba del título: el folio o el tipo\n * @param {import('react').ReactNode} [props.subtitle] abajo del título\n * @param {string|import('react').ReactNode} [props.avatar] un texto (de él salen las iniciales) o un ícono\n * @param {import('react').ReactNode} [props.status] a la derecha: StatusChip, IconBadge…\n * @param {Parameters<typeof import('@/ui/actions/ActionsMenu.jsx').default>[0]['actions']} [props.actions] el menú «⋯», con sus secciones,\n * separadores, ligas y submenús (los renglones de ActionsMenu)\n * @param {Array<{key?: string, title?: import('react').ReactNode, facts?: Array<{label: import('react').ReactNode, value: import('react').ReactNode, emphasis?: boolean}>, content?: import('react').ReactNode}>} [props.groups]\n * los datos, en grupos; emphasis los pone en negritas; content en lugar de facts para un grupo libre (una barra, unas\n * insignias, un enlace)\n * @param {import('react').ReactNode} [props.header] un encabezado propio en lugar del de la casa (avatar, títulos, estatus)\n * @param {import('react').ReactNode} [props.children] contenido libre entre el cuerpo y lo de abajo\n * @param {{label: import('react').ReactNode, value: import('react').ReactNode, caption?: import('react').ReactNode}} [props.highlight] el dato principal\n * @param {import('react').ReactNode} [props.trailing] la última columna del cuerpo, después de los grupos y del dato principal\n * (el estatus o unos botones, cuando el orden obligatorio los pone al final)\n * @param {string} [props.columns] en escritorio, el ancho de cada columna del cuerpo como en CSS ('1.2fr 1fr 1fr auto'); por\n * omisión, los grupos a partes iguales y el dato principal y trailing a su medida\n * @param {import('react').ReactNode} [props.footer] abajo, a todo lo ancho\n * @param {import('react').ReactNode} [props.details] lo que se despliega con «Ver detalle»\n * @param {string} [props.detailsLabel] ya traducido; por omisión «Ver detalle»\n * @param {boolean} [props.defaultDetailsOpen]\n * @param {(isOpen: boolean) => void} [props.onDetailsToggle]\n * @param {() => void} [props.onOpen] el botón para abrir el registro (su detalle)\n * @param {string} [props.openLabel] ya traducido: el nombre de ese botón («Abrir el pedido P-1203»)\n * @param {object} [props.sx]\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nexport default function RecordCard(props) {\n const {\n title, eyebrow, subtitle, avatar, status, actions, groups = [], highlight, trailing, columns, footer, details, detailsLabel, defaultDetailsOpen = false,\n onDetailsToggle, onOpen, openLabel, header, children, sx, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const titleId = useId();\n const detailsId = useId();\n const [isDetailsOpen, setIsDetailsOpen] = useState(defaultDetailsOpen);\n const toggleDetails = () => {\n setIsDetailsOpen((current) => !current);\n onDetailsToggle?.(!isDetailsOpen);\n };\n const hasBody = groups.length > 0 || highlight || trailing;\n // las columnas en escritorio: las que se pidan, o los grupos a partes iguales y lo demás a su medida\n const desktopColumns = columns ?? `${groups.length > 0 ? `repeat(${groups.length}, minmax(0, 1fr))` : ''}${highlight ? ' auto' : ''}${trailing ? ' auto' : ''}`.trim();\n\n return (\n <RecordCardRoot variant=\"outlined\" component=\"article\" aria-labelledby={titleId} ownSx={{p: {xs: 2, sm: 2.5}, minWidth: 0, ...sx}}>\n {/* en el teléfono el estatus baja abajo del título (si no, le quitaba medio ancho) y arriba quedan los botones */}\n {header ?? (\n <RecordCardHeader direction=\"row\" ownSx={{gap: 1.5, alignItems: 'flex-start', flexWrap: {xs: 'wrap', sm: 'nowrap'}}}>\n {avatar && (\n <RecordCardAvatar ownSx={{width: 44, height: 44, bgcolor: 'action.selected', color: 'text.primary', fontSize: 16, fontWeight: 600}}>\n {typeof avatar === 'string' ? initialsOf(avatar) : avatar}\n </RecordCardAvatar>\n )}\n <RecordCardTitles ownSx={{flex: 1, minWidth: 0, order: 1}}>\n {eyebrow && <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\" sx={{fontVariantNumeric: 'tabular-nums'}}>{eyebrow}</Typography>}\n <Typography id={titleId} variant=\"subtitle1\" component=\"h3\" sx={{fontWeight: 600, overflowWrap: 'anywhere'}}>{title}</Typography>\n {subtitle && <Typography variant=\"body2\" color=\"text.secondary\">{subtitle}</Typography>}\n </RecordCardTitles>\n {status && (\n <RecordCardStatus direction=\"row\" ownSx={{\n gap: 0.75, alignItems: 'center', flexWrap: 'wrap', order: {xs: 3, sm: 2},\n flexBasis: {xs: '100%', sm: 'auto'}, justifyContent: {xs: 'flex-start', sm: 'flex-end'}, maxWidth: {sm: '50%'},\n }}>\n {status}\n </RecordCardStatus>\n )}\n <Stack direction=\"row\" sx={{gap: 0.25, alignItems: 'center', order: {xs: 2, sm: 3}, flexShrink: 0}}>\n {onOpen && (\n <Tooltip title={openLabel ?? t('recordCard.open')}>\n <IconButton size=\"small\" aria-label={openLabel ?? t('recordCard.open')} onClick={onOpen}><OpenInNewRoundedIcon fontSize=\"small\" /></IconButton>\n </Tooltip>\n )}\n {actions?.length > 0 && <ActionsMenu label={t('recordCard.actions')} actions={actions} size=\"small\" />}\n </Stack>\n </RecordCardHeader>\n )}\n\n {hasBody && (\n <RecordCardBody ownSx={{\n mt: 2, display: 'grid', gap: {xs: 1.5, md: 3}, alignItems: 'start',\n // en escritorio los grupos lado a lado y el dato principal al final; en el teléfono, uno debajo de otro\n gridTemplateColumns: {xs: '1fr', md: desktopColumns},\n }}>\n {groups.map((group, groupIndex) => (\n <RecordCardGroup key={group.key ?? groupIndex} ownSx={{\n minWidth: 0, pt: {xs: groupIndex > 0 ? 1.5 : 0, md: 0}, borderTop: {xs: groupIndex > 0 ? 1 : 0, md: 0}, borderColor: 'divider',\n }}>\n {group.title && <Typography variant=\"overline\" color=\"text.secondary\" component=\"p\" sx={{lineHeight: 1.8}}>{group.title}</Typography>}\n {group.content ?? (\n <Box component=\"dl\" sx={{m: 0, display: 'grid', gridTemplateColumns: 'auto 1fr', columnGap: 1.5, rowGap: 0.5}}>\n {(group.facts ?? []).map((fact, factIndex) => (\n <RecordCardFact key={factIndex} ownSx={{display: 'contents'}}>\n <Typography component=\"dt\" variant=\"body2\" color=\"text.secondary\">{fact.label}</Typography>\n <Typography component=\"dd\" variant=\"body2\" sx={{m: 0, textAlign: 'right', fontVariantNumeric: 'tabular-nums', fontWeight: fact.emphasis ? 600 : 400, overflowWrap: 'anywhere'}}>\n {fact.value}\n </Typography>\n </RecordCardFact>\n ))}\n </Box>\n )}\n </RecordCardGroup>\n ))}\n {highlight && (\n <RecordCardHighlight ownSx={{\n textAlign: {xs: 'left', md: 'right'}, pl: {md: 3}, borderLeft: {md: 1}, borderTop: {xs: 1, md: 0}, pt: {xs: 1.5, md: 0}, borderColor: 'divider',\n }}>\n <Typography variant=\"overline\" color=\"text.secondary\" component=\"p\" sx={{lineHeight: 1.8}}>{highlight.label}</Typography>\n <Typography variant=\"h5\" component=\"p\" sx={{fontWeight: 700, fontVariantNumeric: 'tabular-nums', whiteSpace: 'nowrap'}}>{highlight.value}</Typography>\n {highlight.caption && <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">{highlight.caption}</Typography>}\n </RecordCardHighlight>\n )}\n {trailing && (\n <Box sx={{minWidth: 0, alignSelf: 'center', borderTop: {xs: 1, md: 0}, pt: {xs: 1.5, md: 0}, borderColor: 'divider'}}>{trailing}</Box>\n )}\n </RecordCardBody>\n )}\n\n {children}\n {(footer || details) && (\n <RecordCardFooter direction=\"row\" ownSx={{mt: 2, gap: 1, alignItems: 'center', flexWrap: 'wrap'}}>\n <Box sx={{flex: 1, minWidth: 0}}>{footer}</Box>\n {details && (\n <Button size=\"small\" onClick={toggleDetails} aria-expanded={isDetailsOpen} aria-controls={detailsId}\n endIcon={<ExpandMoreRoundedIcon sx={{transform: isDetailsOpen ? 'rotate(180deg)' : 'none', transition: 'transform 200ms'}} />}>\n {isDetailsOpen ? t('recordCard.hideDetails') : (detailsLabel ?? t('recordCard.showDetails'))}\n </Button>\n )}\n </RecordCardFooter>\n )}\n {details && (\n <Collapse in={isDetailsOpen} unmountOnExit>\n <RecordCardDetails id={detailsId} ownSx={{mt: 2, pt: 2, borderTop: 1, borderColor: 'divider'}}>{details}</RecordCardDetails>\n </Collapse>\n )}\n </RecordCardRoot>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ "use client";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import Box from "@mui/material/Box";
4
+ import Paper from "@mui/material/Paper";
5
+ import Skeleton from "@mui/material/Skeleton";
6
+ import Stack from "@mui/material/Stack";
7
+ import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
8
+ import { warnUnknownProps } from "../../toolkit/unknownProps.js";
9
+ function RecordCardSkeleton({ groups = 2, factsPerGroup = 3, withAvatar = true, withHighlight = true, sx, texts, ...unknownProps }) {
10
+ warnUnknownProps("RecordCardSkeleton", unknownProps);
11
+ const { t } = useToolkitTranslation("common", texts);
12
+ return /* @__PURE__ */ jsxs(Paper, { variant: "outlined", role: "status", "aria-label": t("recordCard.loading"), sx: { p: { xs: 2, sm: 2.5 }, ...sx }, children: [
13
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", sx: { gap: 1.5, alignItems: "center" }, children: [
14
+ withAvatar && /* @__PURE__ */ jsx(Skeleton, { variant: "circular", width: 44, height: 44 }),
15
+ /* @__PURE__ */ jsxs(Box, { sx: { flex: 1 }, children: [
16
+ /* @__PURE__ */ jsx(Skeleton, { width: "20%" }),
17
+ /* @__PURE__ */ jsx(Skeleton, { width: "45%", height: 28 })
18
+ ] }),
19
+ /* @__PURE__ */ jsx(Skeleton, { variant: "rounded", width: 88, height: 24 })
20
+ ] }),
21
+ /* @__PURE__ */ jsxs(Box, { sx: { mt: 2, display: "grid", gap: 3, gridTemplateColumns: { xs: "1fr", md: `repeat(${groups}, 1fr)${withHighlight ? " 140px" : ""}` } }, children: [
22
+ Array.from({ length: groups }, (unused, groupIndex) => /* @__PURE__ */ jsx(Box, { children: Array.from({ length: factsPerGroup }, (unusedFact, factIndex) => /* @__PURE__ */ jsx(Skeleton, {}, factIndex)) }, groupIndex)),
23
+ withHighlight && /* @__PURE__ */ jsxs(Box, { children: [
24
+ /* @__PURE__ */ jsx(Skeleton, { width: "60%" }),
25
+ /* @__PURE__ */ jsx(Skeleton, { height: 36 })
26
+ ] })
27
+ ] })
28
+ ] });
29
+ }
30
+ export {
31
+ RecordCardSkeleton as default
32
+ };
33
+ //# sourceMappingURL=RecordCardSkeleton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecordCardSkeleton.js","sources":["../../../src/ui/cards/RecordCardSkeleton.jsx"],"sourcesContent":["// El esqueleto de RecordCard mientras llega la lista: la misma forma (avatar, títulos, grupos de datos y dato principal),\n// así la página no brinca cuando aparecen las tarjetas de verdad. Para un lector de pantalla dice «Cargando».\n//\n// Genérico del paquete: function (regla de la casa).\nimport Box from '@mui/material/Box';\nimport Paper from '@mui/material/Paper';\nimport Skeleton from '@mui/material/Skeleton';\nimport Stack from '@mui/material/Stack';\n\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n/**\n * @param {object} props\n * @param {number} [props.groups] cuántos grupos de datos (como los de la tarjeta)\n * @param {number} [props.factsPerGroup]\n * @param {boolean} [props.withAvatar]\n * @param {boolean} [props.withHighlight]\n * @param {object} [props.sx]\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nexport default function RecordCardSkeleton({groups = 2, factsPerGroup = 3, withAvatar = true, withHighlight = true, sx, texts, ...unknownProps}) {\n warnUnknownProps('RecordCardSkeleton', unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n return (\n <Paper variant=\"outlined\" role=\"status\" aria-label={t('recordCard.loading')} sx={{p: {xs: 2, sm: 2.5}, ...sx}}>\n <Stack direction=\"row\" sx={{gap: 1.5, alignItems: 'center'}}>\n {withAvatar && <Skeleton variant=\"circular\" width={44} height={44} />}\n <Box sx={{flex: 1}}>\n <Skeleton width=\"20%\" />\n <Skeleton width=\"45%\" height={28} />\n </Box>\n <Skeleton variant=\"rounded\" width={88} height={24} />\n </Stack>\n <Box sx={{mt: 2, display: 'grid', gap: 3, gridTemplateColumns: {xs: '1fr', md: `repeat(${groups}, 1fr)${withHighlight ? ' 140px' : ''}`}}}>\n {Array.from({length: groups}, (unused, groupIndex) => (\n <Box key={groupIndex}>\n {Array.from({length: factsPerGroup}, (unusedFact, factIndex) => <Skeleton key={factIndex} />)}\n </Box>\n ))}\n {withHighlight && <Box><Skeleton width=\"60%\" /><Skeleton height={36} /></Box>}\n </Box>\n </Paper>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AAqBA,SAAwB,mBAAmB,EAAC,SAAS,GAAG,gBAAgB,GAAG,aAAa,MAAM,gBAAgB,MAAM,IAAI,OAAO,GAAG,gBAAe;AAC7I,mBAAiB,sBAAsB,YAAY;AACnD,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,SACI,qBAAC,SAAM,SAAQ,YAAW,MAAK,UAAS,cAAY,EAAE,oBAAoB,GAAG,IAAI,EAAC,GAAG,EAAC,IAAI,GAAG,IAAI,OAAM,GAAG,GAAA,GACtG,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAM,WAAU,OAAM,IAAI,EAAC,KAAK,KAAK,YAAY,SAAA,GAC7C,UAAA;AAAA,MAAA,kCAAe,UAAA,EAAS,SAAQ,YAAW,OAAO,IAAI,QAAQ,IAAI;AAAA,2BAClE,KAAA,EAAI,IAAI,EAAC,MAAM,KACZ,UAAA;AAAA,QAAA,oBAAC,UAAA,EAAS,OAAM,MAAA,CAAM;AAAA,QACtB,oBAAC,UAAA,EAAS,OAAM,OAAM,QAAQ,GAAA,CAAI;AAAA,MAAA,GACtC;AAAA,0BACC,UAAA,EAAS,SAAQ,WAAU,OAAO,IAAI,QAAQ,GAAA,CAAI;AAAA,IAAA,GACvD;AAAA,IACA,qBAAC,OAAI,IAAI,EAAC,IAAI,GAAG,SAAS,QAAQ,KAAK,GAAG,qBAAqB,EAAC,IAAI,OAAO,IAAI,UAAU,MAAM,SAAS,gBAAgB,WAAW,EAAE,GAAA,EAAE,GAClI,UAAA;AAAA,MAAA,MAAM,KAAK,EAAC,QAAQ,OAAA,GAAS,CAAC,QAAQ,eACnC,oBAAC,KAAA,EACI,UAAA,MAAM,KAAK,EAAC,QAAQ,cAAA,GAAgB,CAAC,YAAY,cAAc,oBAAC,UAAA,CAAA,GAAc,SAAW,CAAE,EAAA,GADtF,UAEV,CACH;AAAA,MACA,sCAAkB,KAAA,EAAI,UAAA;AAAA,QAAA,oBAAC,UAAA,EAAS,OAAM,MAAA,CAAM;AAAA,QAAE,oBAAC,UAAA,EAAS,QAAQ,GAAA,CAAI;AAAA,MAAA,EAAA,CAAE;AAAA,IAAA,EAAA,CAC3E;AAAA,EAAA,GACJ;AAER;"}
@@ -0,0 +1,38 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import Typography from "@mui/material/Typography";
4
+ import { piecePart, usePieceProps } from "../../theme/themePieces.js";
5
+ import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
6
+ import { warnUnknownProps } from "../../toolkit/unknownProps.js";
7
+ import { countdownClockOf } from "./countdownParts.js";
8
+ import { useCountdown } from "./useCountdown.js";
9
+ const THEME_NAME = "CalcitaCountdown";
10
+ const CountdownRoot = piecePart(THEME_NAME, "Root", Typography);
11
+ function Countdown(props) {
12
+ const {
13
+ until,
14
+ label,
15
+ onComplete,
16
+ completedText,
17
+ showSeconds = true,
18
+ children,
19
+ variant = "body1",
20
+ sx,
21
+ texts,
22
+ ...unknownProps
23
+ } = usePieceProps(props, THEME_NAME);
24
+ warnUnknownProps(THEME_NAME, unknownProps);
25
+ const { t } = useToolkitTranslation("common", texts);
26
+ const { parts, isOver } = useCountdown(until, { onComplete });
27
+ if (typeof children === "function") {
28
+ return children(parts);
29
+ }
30
+ if (isOver) {
31
+ return /* @__PURE__ */ jsx(CountdownRoot, { variant, role: "status", ownSx: { fontVariantNumeric: "tabular-nums" }, sx, children: completedText ?? t("countdown.done") });
32
+ }
33
+ return /* @__PURE__ */ jsx(CountdownRoot, { variant, role: "timer", "aria-label": label, ownSx: { fontVariantNumeric: "tabular-nums" }, sx, children: countdownClockOf(parts, { daysLabel: t("countdown.daysShort"), showSeconds }) });
34
+ }
35
+ export {
36
+ Countdown as default
37
+ };
38
+ //# sourceMappingURL=Countdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Countdown.js","sources":["../../../src/ui/countdown/Countdown.jsx"],"sourcesContent":["// La cuenta regresiva ya pintada: «02:14:30» hasta un momento (el cierre de unas inscripciones, el inicio de una cita, el fin de\n// una oferta), con días cuando faltan («3 d 02:14:30»), y lo que dice al llegar a cero («Ya terminó»). Avisa con onComplete\n// una sola vez.\n//\n// Para un lector de pantalla es un temporizador (role=\"timer\"): no anuncia cada segundo, sí el final (role=\"status\").\n// Con children como función se pinta a su manera: children(parts) recibe {days, hours, minutes, seconds, isOver}.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaCountdown con defaultProps y\n// styleOverrides de su parte root.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Typography from '@mui/material/Typography';\n\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {countdownClockOf} from '@/ui/countdown/countdownParts.js';\nimport {useCountdown} from '@/ui/countdown/useCountdown.js';\n\n// el nombre de la pieza en el tema y su parte (theme.components.CalcitaCountdown)\nconst THEME_NAME = 'CalcitaCountdown';\nconst CountdownRoot = piecePart(THEME_NAME, 'Root', Typography);\n\n/**\n * @param {object} props\n * @param {string|number|Date} props.until el momento: un instante en texto, un Date o milisegundos\n * @param {string} [props.label] ya traducido: qué se cuenta («Tiempo para que cierren las inscripciones»), para un lector de pantalla\n * @param {() => void} [props.onComplete] al llegar a cero (una vez)\n * @param {import('react').ReactNode} [props.completedText] lo que dice al terminar; por omisión «Ya terminó»\n * @param {boolean} [props.showSeconds] por omisión, sí\n * @param {(parts: {days: number, hours: number, minutes: number, seconds: number, totalSeconds: number, isOver: boolean}) => import('react').ReactNode} [props.children]\n * para pintarla a su manera\n * @param {import('@mui/material/Typography').TypographyProps['variant']} [props.variant] por omisión body1\n * @param {object} [props.sx]\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nexport default function Countdown(props) {\n const {\n until, label, onComplete, completedText, showSeconds = true, children, variant = 'body1', sx, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const {parts, isOver} = useCountdown(until, {onComplete});\n\n if (typeof children === 'function') {\n return children(parts);\n }\n if (isOver) {\n return (\n <CountdownRoot variant={variant} role=\"status\" ownSx={{fontVariantNumeric: 'tabular-nums'}} sx={sx}>\n {completedText ?? t('countdown.done')}\n </CountdownRoot>\n );\n }\n return (\n <CountdownRoot variant={variant} role=\"timer\" aria-label={label} ownSx={{fontVariantNumeric: 'tabular-nums'}} sx={sx}>\n {countdownClockOf(parts, {daysLabel: t('countdown.daysShort'), showSeconds})}\n </CountdownRoot>\n );\n}\n"],"names":[],"mappings":";;;;;;;;AAoBA,MAAM,aAAa;AACnB,MAAM,gBAAgB,UAAU,YAAY,QAAQ,UAAU;AAe9D,SAAwB,UAAU,OAAO;AACrC,QAAM;AAAA,IACF;AAAA,IAAO;AAAA,IAAO;AAAA,IAAY;AAAA,IAAe,cAAc;AAAA,IAAM;AAAA,IAAU,UAAU;AAAA,IAAS;AAAA,IAAI;AAAA,IAC9F,GAAG;AAAA,EAAA,IACH,cAAc,OAAO,UAAU;AACnC,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,QAAM,EAAC,OAAO,OAAA,IAAU,aAAa,OAAO,EAAC,YAAW;AAExD,MAAI,OAAO,aAAa,YAAY;AAChC,WAAO,SAAS,KAAK;AAAA,EACzB;AACA,MAAI,QAAQ;AACR,WACI,oBAAC,eAAA,EAAc,SAAkB,MAAK,UAAS,OAAO,EAAC,oBAAoB,eAAA,GAAiB,IACvF,UAAA,iBAAiB,EAAE,gBAAgB,GACxC;AAAA,EAER;AACA,SACI,oBAAC,iBAAc,SAAkB,MAAK,SAAQ,cAAY,OAAO,OAAO,EAAC,oBAAoB,kBAAiB,IACzG,UAAA,iBAAiB,OAAO,EAAC,WAAW,EAAE,qBAAqB,GAAG,YAAA,CAAY,GAC/E;AAER;"}
@@ -0,0 +1,34 @@
1
+ const MILLISECONDS_PER_SECOND = 1e3;
2
+ const SECONDS_PER_MINUTE = 60;
3
+ const SECONDS_PER_HOUR = 3600;
4
+ const SECONDS_PER_DAY = 86400;
5
+ const TWO_DIGITS = 2;
6
+ function instantMillisecondsOf(until) {
7
+ if (until instanceof Date) {
8
+ return until.getTime();
9
+ }
10
+ return typeof until === "number" ? until : Date.parse(until);
11
+ }
12
+ function countdownPartsOf(until, now) {
13
+ const remainingMilliseconds = instantMillisecondsOf(until) - now;
14
+ const totalSeconds = Number.isFinite(remainingMilliseconds) && remainingMilliseconds > 0 ? Math.ceil(remainingMilliseconds / MILLISECONDS_PER_SECOND) : 0;
15
+ return {
16
+ days: Math.floor(totalSeconds / SECONDS_PER_DAY),
17
+ hours: Math.floor(totalSeconds % SECONDS_PER_DAY / SECONDS_PER_HOUR),
18
+ minutes: Math.floor(totalSeconds % SECONDS_PER_HOUR / SECONDS_PER_MINUTE),
19
+ seconds: totalSeconds % SECONDS_PER_MINUTE,
20
+ totalSeconds,
21
+ isOver: totalSeconds === 0
22
+ };
23
+ }
24
+ function countdownClockOf({ days, hours, minutes, seconds }, { daysLabel = "d", showSeconds = true } = {}) {
25
+ const twoDigits = (value) => String(value).padStart(TWO_DIGITS, "0");
26
+ const clock = [hours, minutes, ...showSeconds ? [seconds] : []].map(twoDigits).join(":");
27
+ return days > 0 ? `${days} ${daysLabel} ${clock}` : clock;
28
+ }
29
+ export {
30
+ countdownClockOf,
31
+ countdownPartsOf,
32
+ instantMillisecondsOf
33
+ };
34
+ //# sourceMappingURL=countdownParts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"countdownParts.js","sources":["../../../src/ui/countdown/countdownParts.js"],"sourcesContent":["// Cuánto falta para un momento (el cierre de unas inscripciones, el inicio de una cita, el fin de una oferta), en días, horas,\n// minutos y segundos, y cómo se escribe como reloj. Lo usan useCountdown y Countdown.\n//\n// Puro (sin React): se prueba con node (countdownParts.test.js).\n//\n// Genérico del paquete: function (regla de la casa).\n\nconst MILLISECONDS_PER_SECOND = 1000;\nconst SECONDS_PER_MINUTE = 60;\nconst SECONDS_PER_HOUR = 3600;\nconst SECONDS_PER_DAY = 86_400;\nconst TWO_DIGITS = 2;\n\n/**\n * El momento en milisegundos: un instante en texto ('2026-11-01T18:30:00Z'), un Date o milisegundos.\n *\n * @param {string|number|Date} until\n * @returns {number} NaN si no se entiende\n */\nexport function instantMillisecondsOf(until) {\n if (until instanceof Date) {\n return until.getTime();\n }\n return typeof until === 'number' ? until : Date.parse(until);\n}\n\n/**\n * Lo que falta, partido. Ya pasado (o un momento que no se entiende) es todo en cero con isOver.\n *\n * @param {string|number|Date} until\n * @param {number} now milisegundos de ahora (Date.now())\n * @returns {{days: number, hours: number, minutes: number, seconds: number, totalSeconds: number, isOver: boolean}}\n */\nexport function countdownPartsOf(until, now) {\n const remainingMilliseconds = instantMillisecondsOf(until) - now;\n // se redondea hacia arriba: con 0.4 s por delante todavía dice 00:00:01 y no «ya terminó» antes de tiempo\n const totalSeconds = Number.isFinite(remainingMilliseconds) && remainingMilliseconds > 0\n ? Math.ceil(remainingMilliseconds / MILLISECONDS_PER_SECOND)\n : 0;\n return {\n days: Math.floor(totalSeconds / SECONDS_PER_DAY),\n hours: Math.floor((totalSeconds % SECONDS_PER_DAY) / SECONDS_PER_HOUR),\n minutes: Math.floor((totalSeconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE),\n seconds: totalSeconds % SECONDS_PER_MINUTE,\n totalSeconds,\n isOver: totalSeconds === 0,\n };\n}\n\n/**\n * Lo que falta como reloj: «02:14:30»; con días, «3 d 02:14:30» (la letra del día la da el idioma); sin segundos,\n * «02:14».\n *\n * @param {{days: number, hours: number, minutes: number, seconds: number}} parts\n * @param {{daysLabel?: string, showSeconds?: boolean}} [options] daysLabel: la abreviatura de días ya traducida ('d')\n * @returns {string}\n */\nexport function countdownClockOf({days, hours, minutes, seconds}, {daysLabel = 'd', showSeconds = true} = {}) {\n const twoDigits = (value) => String(value).padStart(TWO_DIGITS, '0');\n const clock = [hours, minutes, ...(showSeconds ? [seconds] : [])].map(twoDigits).join(':');\n return days > 0 ? `${days} ${daysLabel} ${clock}` : clock;\n}\n"],"names":[],"mappings":"AAOA,MAAM,0BAA0B;AAChC,MAAM,qBAAqB;AAC3B,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AACxB,MAAM,aAAa;AAQZ,SAAS,sBAAsB,OAAO;AACzC,MAAI,iBAAiB,MAAM;AACvB,WAAO,MAAM,QAAO;AAAA,EACxB;AACA,SAAO,OAAO,UAAU,WAAW,QAAQ,KAAK,MAAM,KAAK;AAC/D;AASO,SAAS,iBAAiB,OAAO,KAAK;AACzC,QAAM,wBAAwB,sBAAsB,KAAK,IAAI;AAE7D,QAAM,eAAe,OAAO,SAAS,qBAAqB,KAAK,wBAAwB,IACjF,KAAK,KAAK,wBAAwB,uBAAuB,IACzD;AACN,SAAO;AAAA,IACH,MAAM,KAAK,MAAM,eAAe,eAAe;AAAA,IAC/C,OAAO,KAAK,MAAO,eAAe,kBAAmB,gBAAgB;AAAA,IACrE,SAAS,KAAK,MAAO,eAAe,mBAAoB,kBAAkB;AAAA,IAC1E,SAAS,eAAe;AAAA,IACxB;AAAA,IACA,QAAQ,iBAAiB;AAAA,EACjC;AACA;AAUO,SAAS,iBAAiB,EAAC,MAAM,OAAO,SAAS,QAAO,GAAG,EAAC,YAAY,KAAK,cAAc,KAAI,IAAI,CAAA,GAAI;AAC1G,QAAM,YAAY,CAAC,UAAU,OAAO,KAAK,EAAE,SAAS,YAAY,GAAG;AACnE,QAAM,QAAQ,CAAC,OAAO,SAAS,GAAI,cAAc,CAAC,OAAO,IAAI,CAAA,CAAG,EAAE,IAAI,SAAS,EAAE,KAAK,GAAG;AACzF,SAAO,OAAO,IAAI,GAAG,IAAI,IAAI,SAAS,IAAI,KAAK,KAAK;AACxD;"}
@@ -0,0 +1,35 @@
1
+ "use client";
2
+ import { useState, useRef, useEffect } from "react";
3
+ import { countdownPartsOf } from "./countdownParts.js";
4
+ const TICK_MILLISECONDS = 1e3;
5
+ function useCountdown(until, { onComplete, now = Date.now } = {}) {
6
+ const [parts, setParts] = useState(() => countdownPartsOf(until, now()));
7
+ const latest = useRef({ onComplete, now });
8
+ latest.current = { onComplete, now };
9
+ useEffect(() => {
10
+ let hasCompleted = false;
11
+ const tick = () => {
12
+ const current = countdownPartsOf(until, latest.current.now());
13
+ setParts(current);
14
+ if (current.isOver && !hasCompleted) {
15
+ hasCompleted = true;
16
+ latest.current.onComplete?.();
17
+ }
18
+ return current.isOver;
19
+ };
20
+ if (tick()) {
21
+ return void 0;
22
+ }
23
+ const timer = setInterval(() => {
24
+ if (tick()) {
25
+ clearInterval(timer);
26
+ }
27
+ }, TICK_MILLISECONDS);
28
+ return () => clearInterval(timer);
29
+ }, [until]);
30
+ return { parts, isOver: parts.isOver };
31
+ }
32
+ export {
33
+ useCountdown
34
+ };
35
+ //# sourceMappingURL=useCountdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCountdown.js","sources":["../../../src/ui/countdown/useCountdown.js"],"sourcesContent":["// Cuánto falta para un momento, al día cada segundo, y avisar una sola vez al llegar a cero (onComplete). Para pintar la\n// cuenta a su manera; Countdown es la que ya viene pintada.\n//\n// const {parts, isOver} = useCountdown(registration.closes_at, {onComplete: reloadRegistration});\n//\n// Mientras ya terminó no corre ningún reloj de fondo, y al desmontar se apaga.\n//\n// Hook genérico: function (regla de la casa).\nimport {useEffect, useRef, useState} from 'react';\n\nimport {countdownPartsOf} from '@/ui/countdown/countdownParts.js';\n\nconst TICK_MILLISECONDS = 1000;\n\n/**\n * @param {string|number|Date} until el momento: un instante en texto, un Date o milisegundos\n * @param {{onComplete?: () => void, now?: () => number}} [options] onComplete: al llegar a cero (una vez); now: el reloj\n * (para probar con una hora fija)\n * @returns {{parts: ReturnType<typeof countdownPartsOf>, isOver: boolean}}\n */\nexport function useCountdown(until, {onComplete, now = Date.now} = {}) {\n const [parts, setParts] = useState(() => countdownPartsOf(until, now()));\n // lo último de afuera, sin rearmar el reloj cada vez que la pantalla pinta otra función\n const latest = useRef({onComplete, now});\n latest.current = {onComplete, now};\n\n useEffect(() => {\n let hasCompleted = false;\n const tick = () => {\n const current = countdownPartsOf(until, latest.current.now());\n setParts(current);\n if (current.isOver && !hasCompleted) {\n hasCompleted = true;\n latest.current.onComplete?.();\n }\n return current.isOver;\n };\n // ya terminó al llegar: se avisa y no se arma el reloj\n if (tick()) {\n return undefined;\n }\n const timer = setInterval(() => {\n if (tick()) {\n clearInterval(timer);\n }\n }, TICK_MILLISECONDS);\n return () => clearInterval(timer);\n }, [until]);\n\n return {parts, isOver: parts.isOver};\n}\n"],"names":[],"mappings":";;;AAYA,MAAM,oBAAoB;AAQnB,SAAS,aAAa,OAAO,EAAC,YAAY,MAAM,KAAK,IAAG,IAAI,IAAI;AACnE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,MAAM,iBAAiB,OAAO,IAAG,CAAE,CAAC;AAEvE,QAAM,SAAS,OAAO,EAAC,YAAY,IAAG,CAAC;AACvC,SAAO,UAAU,EAAC,YAAY,IAAG;AAEjC,YAAU,MAAM;AACZ,QAAI,eAAe;AACnB,UAAM,OAAO,MAAM;AACf,YAAM,UAAU,iBAAiB,OAAO,OAAO,QAAQ,KAAK;AAC5D,eAAS,OAAO;AAChB,UAAI,QAAQ,UAAU,CAAC,cAAc;AACjC,uBAAe;AACf,eAAO,QAAQ,aAAU;AAAA,MAC7B;AACA,aAAO,QAAQ;AAAA,IACnB;AAEA,QAAI,KAAI,GAAI;AACR,aAAO;AAAA,IACX;AACA,UAAM,QAAQ,YAAY,MAAM;AAC5B,UAAI,KAAI,GAAI;AACR,sBAAc,KAAK;AAAA,MACvB;AAAA,IACJ,GAAG,iBAAiB;AACpB,WAAO,MAAM,cAAc,KAAK;AAAA,EACpC,GAAG,CAAC,KAAK,CAAC;AAEV,SAAO,EAAC,OAAO,QAAQ,MAAM,OAAM;AACvC;"}
@@ -0,0 +1,81 @@
1
+ "use client";
2
+ import { jsxs, jsx } from "react/jsx-runtime";
3
+ import { useState, useEffect } from "react";
4
+ import Button from "@mui/material/Button";
5
+ import Stack from "@mui/material/Stack";
6
+ import Box from "@mui/material/Box";
7
+ import FileDownloadOutlinedIcon from "@mui/icons-material/FileDownloadOutlined";
8
+ import OpenInNewRoundedIcon from "@mui/icons-material/OpenInNewRounded";
9
+ import { piecePart, usePieceProps } from "../../theme/themePieces.js";
10
+ import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
11
+ import { warnUnknownProps } from "../../toolkit/unknownProps.js";
12
+ import ContentDialog from "../layout/ContentDialog.js";
13
+ const THEME_NAME = "CalcitaPdfViewerDialog";
14
+ const ViewerActions = piecePart(THEME_NAME, "Actions", Stack);
15
+ const ViewerFrame = piecePart(THEME_NAME, "Frame", "iframe");
16
+ function usePdfUrl(src) {
17
+ const [blobUrl, setBlobUrl] = useState(null);
18
+ const isBlob = typeof Blob !== "undefined" && src instanceof Blob;
19
+ useEffect(() => {
20
+ if (!isBlob) {
21
+ setBlobUrl(null);
22
+ return void 0;
23
+ }
24
+ const url = URL.createObjectURL(src);
25
+ setBlobUrl(url);
26
+ return () => URL.revokeObjectURL(url);
27
+ }, [isBlob, src]);
28
+ if (isBlob) {
29
+ return blobUrl;
30
+ }
31
+ return typeof src === "string" && src ? src : null;
32
+ }
33
+ function PdfViewerDialog(props) {
34
+ const { open, onClose, title, src, fileName, actions, onDownload, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
35
+ warnUnknownProps(THEME_NAME, unknownProps);
36
+ const { t } = useToolkitTranslation("common", texts);
37
+ const pdfUrl = usePdfUrl(open ? src : null);
38
+ return /* @__PURE__ */ jsxs(ContentDialog, { open, onClose, title, texts, children: [
39
+ /* @__PURE__ */ jsxs(ViewerActions, { direction: "row", ownSx: { gap: 1, flexWrap: "wrap", mb: 2 }, children: [
40
+ /* @__PURE__ */ jsx(
41
+ Button,
42
+ {
43
+ size: "small",
44
+ variant: "outlined",
45
+ startIcon: /* @__PURE__ */ jsx(OpenInNewRoundedIcon, {}),
46
+ href: pdfUrl ?? void 0,
47
+ target: "_blank",
48
+ rel: "noopener noreferrer",
49
+ disabled: !pdfUrl,
50
+ children: t("pdfViewer.openInTab")
51
+ }
52
+ ),
53
+ /* @__PURE__ */ jsx(
54
+ Button,
55
+ {
56
+ size: "small",
57
+ variant: "outlined",
58
+ startIcon: /* @__PURE__ */ jsx(FileDownloadOutlinedIcon, {}),
59
+ href: pdfUrl ?? void 0,
60
+ download: fileName ?? `${title}.pdf`,
61
+ disabled: !pdfUrl,
62
+ onClick: onDownload,
63
+ children: t("pdfViewer.download")
64
+ }
65
+ ),
66
+ actions
67
+ ] }),
68
+ pdfUrl ? /* @__PURE__ */ jsx(
69
+ ViewerFrame,
70
+ {
71
+ src: pdfUrl,
72
+ title,
73
+ ownSx: { display: "block", width: "100%", height: { xs: "62vh", md: "72vh" }, border: 0, borderRadius: 1, bgcolor: "action.hover" }
74
+ }
75
+ ) : /* @__PURE__ */ jsx(Box, { sx: { height: { xs: "62vh", md: "72vh" }, borderRadius: 1, bgcolor: "action.hover" } })
76
+ ] });
77
+ }
78
+ export {
79
+ PdfViewerDialog as default
80
+ };
81
+ //# sourceMappingURL=PdfViewerDialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PdfViewerDialog.js","sources":["../../../src/ui/documents/PdfViewerDialog.jsx"],"sourcesContent":["// Un PDF en una ventana: el aviso de privacidad, un contrato, un estado de cuenta. Lo pinta el visor del navegador (sin\n// librerías: nada que descargar ni que actualizar) en la hoja de lectura de la casa (ContentDialog), con «Abrir en otra\n// pestaña» y «Descargar» arriba.\n//\n// OJO: en el iPhone el visor dentro de la página enseña solo la primera hoja y en algunos navegadores no se pinta; por eso\n// los dos botones siempre están a la vista: abrirlo aparte o bajarlo funciona en todos.\n//\n// src es la dirección del PDF o el archivo mismo (un Blob que mandó el API, un File elegido): del archivo se arma una\n// dirección en el navegador, sin subirlo, y se libera al cerrar.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaPdfViewerDialog con defaultProps y\n// styleOverrides de sus partes: actions, frame.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useState} from 'react';\nimport Button from '@mui/material/Button';\nimport Stack from '@mui/material/Stack';\nimport Box from '@mui/material/Box';\nimport FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';\nimport OpenInNewRoundedIcon from '@mui/icons-material/OpenInNewRounded';\n\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport ContentDialog from '@/ui/layout/ContentDialog.jsx';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaPdfViewerDialog)\nconst THEME_NAME = 'CalcitaPdfViewerDialog';\nconst ViewerActions = piecePart(THEME_NAME, 'Actions', Stack);\nconst ViewerFrame = piecePart(THEME_NAME, 'Frame', 'iframe');\n\n/**\n * La dirección del PDF: la que llega tal cual, o una del navegador para un archivo (se libera al cambiarlo o al cerrar).\n *\n * @param {string|Blob|null|undefined} src\n * @returns {string|null}\n */\nfunction usePdfUrl(src) {\n const [blobUrl, setBlobUrl] = useState(null);\n const isBlob = typeof Blob !== 'undefined' && src instanceof Blob;\n\n useEffect(() => {\n if (!isBlob) {\n setBlobUrl(null);\n return undefined;\n }\n const url = URL.createObjectURL(src);\n setBlobUrl(url);\n return () => URL.revokeObjectURL(url);\n }, [isBlob, src]);\n\n if (isBlob) {\n return blobUrl;\n }\n return typeof src === 'string' && src ? src : null;\n}\n\n/**\n * @param {object} props\n * @param {boolean} props.open\n * @param {() => void} props.onClose\n * @param {string} props.title ya traducido: qué documento es\n * @param {string|Blob|null} props.src la dirección del PDF o el archivo (Blob o File)\n * @param {string} [props.fileName] con qué nombre se descarga (por omisión, el título con .pdf)\n * @param {import('react').ReactNode} [props.actions] botones suyos junto a «Abrir en otra pestaña» y «Descargar»\n * @param {() => void} [props.onDownload] al descargar (para registrarlo, por ejemplo)\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nexport default function PdfViewerDialog(props) {\n const {open, onClose, title, src, fileName, actions, onDownload, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const pdfUrl = usePdfUrl(open ? src : null);\n\n return (\n <ContentDialog open={open} onClose={onClose} title={title} texts={texts}>\n <ViewerActions direction=\"row\" ownSx={{gap: 1, flexWrap: 'wrap', mb: 2}}>\n <Button size=\"small\" variant=\"outlined\" startIcon={<OpenInNewRoundedIcon />} href={pdfUrl ?? undefined} target=\"_blank\"\n rel=\"noopener noreferrer\" disabled={!pdfUrl}>\n {t('pdfViewer.openInTab')}\n </Button>\n <Button size=\"small\" variant=\"outlined\" startIcon={<FileDownloadOutlinedIcon />} href={pdfUrl ?? undefined}\n download={fileName ?? `${title}.pdf`} disabled={!pdfUrl} onClick={onDownload}>\n {t('pdfViewer.download')}\n </Button>\n {actions}\n </ViewerActions>\n {pdfUrl ? (\n <ViewerFrame src={pdfUrl} title={title}\n ownSx={{display: 'block', width: '100%', height: {xs: '62vh', md: '72vh'}, border: 0, borderRadius: 1, bgcolor: 'action.hover'}} />\n ) : (\n <Box sx={{height: {xs: '62vh', md: '72vh'}, borderRadius: 1, bgcolor: 'action.hover'}} />\n )}\n </ContentDialog>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AA2BA,MAAM,aAAa;AACnB,MAAM,gBAAgB,UAAU,YAAY,WAAW,KAAK;AAC5D,MAAM,cAAc,UAAU,YAAY,SAAS,QAAQ;AAQ3D,SAAS,UAAU,KAAK;AACpB,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,SAAS,OAAO,SAAS,eAAe,eAAe;AAE7D,YAAU,MAAM;AACZ,QAAI,CAAC,QAAQ;AACT,iBAAW,IAAI;AACf,aAAO;AAAA,IACX;AACA,UAAM,MAAM,IAAI,gBAAgB,GAAG;AACnC,eAAW,GAAG;AACd,WAAO,MAAM,IAAI,gBAAgB,GAAG;AAAA,EACxC,GAAG,CAAC,QAAQ,GAAG,CAAC;AAEhB,MAAI,QAAQ;AACR,WAAO;AAAA,EACX;AACA,SAAO,OAAO,QAAQ,YAAY,MAAM,MAAM;AAClD;AAaA,SAAwB,gBAAgB,OAAO;AAC3C,QAAM,EAAC,MAAM,SAAS,OAAO,KAAK,UAAU,SAAS,YAAY,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AAC1H,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,QAAM,SAAS,UAAU,OAAO,MAAM,IAAI;AAE1C,SACI,qBAAC,eAAA,EAAc,MAAY,SAAkB,OAAc,OACvD,UAAA;AAAA,IAAA,qBAAC,eAAA,EAAc,WAAU,OAAM,OAAO,EAAC,KAAK,GAAG,UAAU,QAAQ,IAAI,EAAA,GACjE,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UAAO,MAAK;AAAA,UAAQ,SAAQ;AAAA,UAAW,+BAAY,sBAAA,EAAqB;AAAA,UAAI,MAAM,UAAU;AAAA,UAAW,QAAO;AAAA,UACvG,KAAI;AAAA,UAAsB,UAAU,CAAC;AAAA,UACxC,YAAE,qBAAqB;AAAA,QAAA;AAAA,MAAA;AAAA,MAE5B;AAAA,QAAC;AAAA,QAAA;AAAA,UAAO,MAAK;AAAA,UAAQ,SAAQ;AAAA,UAAW,+BAAY,0BAAA,EAAyB;AAAA,UAAI,MAAM,UAAU;AAAA,UACzF,UAAU,YAAY,GAAG,KAAK;AAAA,UAAQ,UAAU,CAAC;AAAA,UAAQ,SAAS;AAAA,UACrE,YAAE,oBAAoB;AAAA,QAAA;AAAA,MAAA;AAAA,MAE1B;AAAA,IAAA,GACL;AAAA,IACC,SACG;AAAA,MAAC;AAAA,MAAA;AAAA,QAAY,KAAK;AAAA,QAAQ;AAAA,QACb,OAAO,EAAC,SAAS,SAAS,OAAO,QAAQ,QAAQ,EAAC,IAAI,QAAQ,IAAI,UAAS,QAAQ,GAAG,cAAc,GAAG,SAAS,eAAA;AAAA,MAAc;AAAA,IAAA,IAE3I,oBAAC,KAAA,EAAI,IAAI,EAAC,QAAQ,EAAC,IAAI,QAAQ,IAAI,UAAS,cAAc,GAAG,SAAS,iBAAc,CAAG;AAAA,EAAA,GAE/F;AAER;"}