@stackcraftmx/calcita 0.32.2 → 0.51.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 (680) hide show
  1. package/README.md +426 -4
  2. package/cli/calcita.js +15 -0
  3. package/cli/checkTexts.js +209 -0
  4. package/cli/packageVersions.js +17 -3
  5. package/cli/projectFiles.js +7 -2
  6. package/cli/templates/module/__Name__Page.test.jsx.tpl +24 -0
  7. package/cli/templates/project/README.md.tpl +35 -2
  8. package/cli/templates/project/eslint.config.js.tpl +27 -0
  9. package/cli/templates/project/src/app/appRouter.jsx.tpl +5 -2
  10. package/cli/templates/project/src/app/appTexts.js.tpl +2 -1
  11. package/cli/templates/project/src/core/accountConnector.js.tpl +4 -2
  12. package/cli/templates/project/src/core/publicPaths.js.tpl +10 -2
  13. package/cli/templates/project/src/modules/auth/SignInPage.test.jsx.tpl +20 -0
  14. package/cli/templates/project/src/modules/home/HomePage.test.jsx.tpl +16 -0
  15. package/cli/templates/project/src/testing/browserGaps.js.tpl +70 -0
  16. package/cli/templates/project/src/testing/openScreen.jsx.tpl +58 -0
  17. package/cli/templates/project/src/testing/setup.js.tpl +25 -0
  18. package/cli/templates/project/vite.config.js.tpl +20 -1
  19. package/dist/DataTable/AuditTrailDialog.js +3 -2
  20. package/dist/DataTable/AuditTrailDialog.js.map +1 -1
  21. package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js +3 -2
  22. package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js.map +1 -1
  23. package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js +3 -2
  24. package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js.map +1 -1
  25. package/dist/DataTable/ColumnFilters/SortableFilterHeader.js +3 -2
  26. package/dist/DataTable/ColumnFilters/SortableFilterHeader.js.map +1 -1
  27. package/dist/DataTable/EmptyState.js +3 -2
  28. package/dist/DataTable/EmptyState.js.map +1 -1
  29. package/dist/DataTable/FilterChips.js +3 -2
  30. package/dist/DataTable/FilterChips.js.map +1 -1
  31. package/dist/DataTable/GoToPage.js +71 -14
  32. package/dist/DataTable/GoToPage.js.map +1 -1
  33. package/dist/DataTable/ServerTable.js +97 -28
  34. package/dist/DataTable/ServerTable.js.map +1 -1
  35. package/dist/DataTable/ServerTableFilterDrawer.js +57 -0
  36. package/dist/DataTable/ServerTableFilterDrawer.js.map +1 -0
  37. package/dist/DataTable/StackedCell.js +60 -0
  38. package/dist/DataTable/StackedCell.js.map +1 -0
  39. package/dist/DataTable/TableCardsView.js +88 -0
  40. package/dist/DataTable/TableCardsView.js.map +1 -0
  41. package/dist/DataTable/columnWidths.js +30 -0
  42. package/dist/DataTable/columnWidths.js.map +1 -0
  43. package/dist/DataTable/columns.js +47 -1
  44. package/dist/DataTable/columns.js.map +1 -1
  45. package/dist/DataTable/filterContext.js.map +1 -1
  46. package/dist/DataTable/fixedColumns.js +24 -0
  47. package/dist/DataTable/fixedColumns.js.map +1 -0
  48. package/dist/DataTable/goToPageOptions.js +17 -0
  49. package/dist/DataTable/goToPageOptions.js.map +1 -0
  50. package/dist/DataTable/useTableView.js +29 -0
  51. package/dist/DataTable/useTableView.js.map +1 -0
  52. package/dist/access/PermissionMatrix.js +3 -2
  53. package/dist/access/PermissionMatrix.js.map +1 -1
  54. package/dist/account/AccountProvider.js +1 -1
  55. package/dist/account/AccountSecuritySection.js +3 -2
  56. package/dist/account/AccountSecuritySection.js.map +1 -1
  57. package/dist/account/DemoTotpCodeButton.js +3 -2
  58. package/dist/account/DemoTotpCodeButton.js.map +1 -1
  59. package/dist/account/ProfileScreen.js +3 -2
  60. package/dist/account/ProfileScreen.js.map +1 -1
  61. package/dist/account/SignInScreen.js +3 -2
  62. package/dist/account/SignInScreen.js.map +1 -1
  63. package/dist/appShell/AccountMenu.js +3 -2
  64. package/dist/appShell/AccountMenu.js.map +1 -1
  65. package/dist/appShell/AppLayout.js +3 -2
  66. package/dist/appShell/AppLayout.js.map +1 -1
  67. package/dist/appShell/AppearanceSettings.js +3 -2
  68. package/dist/appShell/AppearanceSettings.js.map +1 -1
  69. package/dist/appShell/AuthLayout.js +3 -2
  70. package/dist/appShell/AuthLayout.js.map +1 -1
  71. package/dist/appShell/BarActionButton.js +11 -4
  72. package/dist/appShell/BarActionButton.js.map +1 -1
  73. package/dist/appShell/BarActions.js +3 -2
  74. package/dist/appShell/BarActions.js.map +1 -1
  75. package/dist/appShell/BarCapsule.js +3 -2
  76. package/dist/appShell/BarCapsule.js.map +1 -1
  77. package/dist/appShell/BarSearch.js +3 -2
  78. package/dist/appShell/BarSearch.js.map +1 -1
  79. package/dist/appShell/HeaderTools.js +3 -2
  80. package/dist/appShell/HeaderTools.js.map +1 -1
  81. package/dist/appShell/MobileTabBar.js +3 -2
  82. package/dist/appShell/MobileTabBar.js.map +1 -1
  83. package/dist/appShell/SettingsMenu.js +3 -2
  84. package/dist/appShell/SettingsMenu.js.map +1 -1
  85. package/dist/appShell/SideMenu.js +3 -2
  86. package/dist/appShell/SideMenu.js.map +1 -1
  87. package/dist/appShell/SideMenuEntry.js +3 -2
  88. package/dist/appShell/SideMenuEntry.js.map +1 -1
  89. package/dist/appShell/SubmenuActionsMenu.js +3 -2
  90. package/dist/appShell/SubmenuActionsMenu.js.map +1 -1
  91. package/dist/appShell/TabBarEditor.js +3 -2
  92. package/dist/appShell/TabBarEditor.js.map +1 -1
  93. package/dist/appShell/TopMenu.js +3 -2
  94. package/dist/appShell/TopMenu.js.map +1 -1
  95. package/dist/appShell/Wordmark.js +3 -2
  96. package/dist/appShell/Wordmark.js.map +1 -1
  97. package/dist/auth/PasswordChecklist.js +3 -2
  98. package/dist/auth/PasswordChecklist.js.map +1 -1
  99. package/dist/calendar/EventCalendar.js +3 -2
  100. package/dist/calendar/EventCalendar.js.map +1 -1
  101. package/dist/calendar/EventDetails.js +3 -2
  102. package/dist/calendar/EventDetails.js.map +1 -1
  103. package/dist/date-pickers.js +28 -2
  104. package/dist/date-pickers.js.map +1 -1
  105. package/dist/datePickers/DateInput.js +41 -54
  106. package/dist/datePickers/DateInput.js.map +1 -1
  107. package/dist/datePickers/DateTimeInput.js +81 -0
  108. package/dist/datePickers/DateTimeInput.js.map +1 -0
  109. package/dist/datePickers/FormDateTimeField.js +12 -0
  110. package/dist/datePickers/FormDateTimeField.js.map +1 -0
  111. package/dist/datePickers/FormMonthField.js +12 -0
  112. package/dist/datePickers/FormMonthField.js.map +1 -0
  113. package/dist/datePickers/FormTimeField.js +12 -0
  114. package/dist/datePickers/FormTimeField.js.map +1 -0
  115. package/dist/datePickers/MonthInput.js +64 -0
  116. package/dist/datePickers/MonthInput.js.map +1 -0
  117. package/dist/datePickers/PickerFrame.js +27 -0
  118. package/dist/datePickers/PickerFrame.js.map +1 -0
  119. package/dist/datePickers/TimeInput.js +61 -0
  120. package/dist/datePickers/TimeInput.js.map +1 -0
  121. package/dist/datePickers/dateTimeRules.js +24 -0
  122. package/dist/datePickers/dateTimeRules.js.map +1 -0
  123. package/dist/datePickers/pickerValues.js +106 -0
  124. package/dist/datePickers/pickerValues.js.map +1 -0
  125. package/dist/datePickers/useCurrentMinute.js +28 -0
  126. package/dist/datePickers/useCurrentMinute.js.map +1 -0
  127. package/dist/datePickers/usePickerField.js +23 -0
  128. package/dist/datePickers/usePickerField.js.map +1 -0
  129. package/dist/dictionaries/dictionaries.js +3 -1
  130. package/dist/dictionaries/dictionaries.js.map +1 -1
  131. package/dist/downloads/DownloadManager.js +3 -2
  132. package/dist/downloads/DownloadManager.js.map +1 -1
  133. package/dist/feedback/ConfirmDialog.js +3 -2
  134. package/dist/feedback/ConfirmDialog.js.map +1 -1
  135. package/dist/feedback/ModalWaiting.js +3 -2
  136. package/dist/feedback/ModalWaiting.js.map +1 -1
  137. package/dist/feedback/NewBuildNotice.js +3 -2
  138. package/dist/feedback/NewBuildNotice.js.map +1 -1
  139. package/dist/filepond/FileDropzone.js +3 -2
  140. package/dist/filepond/FileDropzone.js.map +1 -1
  141. package/dist/forms/FormAttachmentsField.js +12 -0
  142. package/dist/forms/FormAttachmentsField.js.map +1 -0
  143. package/dist/forms/FormCheckboxGroupField.js +12 -0
  144. package/dist/forms/FormCheckboxGroupField.js.map +1 -0
  145. package/dist/forms/FormFileField.js +12 -0
  146. package/dist/forms/FormFileField.js.map +1 -0
  147. package/dist/forms/FormFileUploadField.js +12 -0
  148. package/dist/forms/FormFileUploadField.js.map +1 -0
  149. package/dist/forms/FormImageField.js +12 -0
  150. package/dist/forms/FormImageField.js.map +1 -0
  151. package/dist/forms/FormMaskedField.js +12 -0
  152. package/dist/forms/FormMaskedField.js.map +1 -0
  153. package/dist/forms/FormProblemAlert.js +3 -2
  154. package/dist/forms/FormProblemAlert.js.map +1 -1
  155. package/dist/forms/FormRepeatingFields.js +54 -0
  156. package/dist/forms/FormRepeatingFields.js.map +1 -0
  157. package/dist/forms/FormTransferListField.js +12 -0
  158. package/dist/forms/FormTransferListField.js.map +1 -0
  159. package/dist/forms/SubmitButton.js +7 -2
  160. package/dist/forms/SubmitButton.js.map +1 -1
  161. package/dist/forms/applyServerProblem.js +10 -3
  162. package/dist/forms/applyServerProblem.js.map +1 -1
  163. package/dist/forms/auth/SignInForm.js +3 -2
  164. package/dist/forms/auth/SignInForm.js.map +1 -1
  165. package/dist/forms/fieldRules.js +30 -0
  166. package/dist/forms/fieldRules.js.map +1 -0
  167. package/dist/forms/listRules.js +111 -0
  168. package/dist/forms/listRules.js.map +1 -0
  169. package/dist/forms/security/SecondStepForm.js +3 -2
  170. package/dist/forms/security/SecondStepForm.js.map +1 -1
  171. package/dist/forms/security/TwoStepVerificationCard.js +3 -2
  172. package/dist/forms/security/TwoStepVerificationCard.js.map +1 -1
  173. package/dist/forms/serverProblemFields.js +17 -0
  174. package/dist/forms/serverProblemFields.js.map +1 -1
  175. package/dist/forms/useValidationText.js +18 -0
  176. package/dist/forms/useValidationText.js.map +1 -0
  177. package/dist/forms/validation.js +35 -31
  178. package/dist/forms/validation.js.map +1 -1
  179. package/dist/forms/validationMessages.js +64 -7
  180. package/dist/forms/validationMessages.js.map +1 -1
  181. package/dist/forms.js +54 -29
  182. package/dist/forms.js.map +1 -1
  183. package/dist/hookForm/FormAttachmentsField.js +12 -0
  184. package/dist/hookForm/FormAttachmentsField.js.map +1 -0
  185. package/dist/hookForm/FormCheckboxGroupField.js +12 -0
  186. package/dist/hookForm/FormCheckboxGroupField.js.map +1 -0
  187. package/dist/hookForm/FormFileField.js +12 -0
  188. package/dist/hookForm/FormFileField.js.map +1 -0
  189. package/dist/hookForm/FormFileUploadField.js +12 -0
  190. package/dist/hookForm/FormFileUploadField.js.map +1 -0
  191. package/dist/hookForm/FormImageField.js +12 -0
  192. package/dist/hookForm/FormImageField.js.map +1 -0
  193. package/dist/hookForm/FormMaskedField.js +12 -0
  194. package/dist/hookForm/FormMaskedField.js.map +1 -0
  195. package/dist/hookForm/FormProblemAlert.js +3 -2
  196. package/dist/hookForm/FormProblemAlert.js.map +1 -1
  197. package/dist/hookForm/FormRepeatingFields.js +44 -0
  198. package/dist/hookForm/FormRepeatingFields.js.map +1 -0
  199. package/dist/hookForm/FormTransferListField.js +12 -0
  200. package/dist/hookForm/FormTransferListField.js.map +1 -0
  201. package/dist/hookForm/SubmitButton.js +7 -2
  202. package/dist/hookForm/SubmitButton.js.map +1 -1
  203. package/dist/hookForm/applyServerProblem.js +8 -3
  204. package/dist/hookForm/applyServerProblem.js.map +1 -1
  205. package/dist/inbox/InboxLayout.js +3 -2
  206. package/dist/inbox/InboxLayout.js.map +1 -1
  207. package/dist/inbox/MessageList.js +3 -2
  208. package/dist/inbox/MessageList.js.map +1 -1
  209. package/dist/inbox/MessageView.js +3 -2
  210. package/dist/inbox/MessageView.js.map +1 -1
  211. package/dist/index.js +235 -124
  212. package/dist/index.js.map +1 -1
  213. package/dist/inputs/CatalogInput.js +103 -29
  214. package/dist/inputs/CatalogInput.js.map +1 -1
  215. package/dist/inputs/CheckboxGroupInput.js +103 -0
  216. package/dist/inputs/CheckboxGroupInput.js.map +1 -0
  217. package/dist/inputs/ColorInput.js +7 -4
  218. package/dist/inputs/ColorInput.js.map +1 -1
  219. package/dist/inputs/FieldFrame.js +10 -4
  220. package/dist/inputs/FieldFrame.js.map +1 -1
  221. package/dist/inputs/FormSection.js +1 -1
  222. package/dist/inputs/MaskedInput.js +87 -0
  223. package/dist/inputs/MaskedInput.js.map +1 -0
  224. package/dist/inputs/NumberInput.js +41 -25
  225. package/dist/inputs/NumberInput.js.map +1 -1
  226. package/dist/inputs/RepeatingFields.js +180 -0
  227. package/dist/inputs/RepeatingFields.js.map +1 -0
  228. package/dist/inputs/SelectInput.js +50 -9
  229. package/dist/inputs/SelectInput.js.map +1 -1
  230. package/dist/inputs/TextInput.js +5 -3
  231. package/dist/inputs/TextInput.js.map +1 -1
  232. package/dist/inputs/TransferListInput.js +218 -0
  233. package/dist/inputs/TransferListInput.js.map +1 -0
  234. package/dist/inputs/WizardLayout.js +3 -2
  235. package/dist/inputs/WizardLayout.js.map +1 -1
  236. package/dist/inputs/inputMasks.js +84 -0
  237. package/dist/inputs/inputMasks.js.map +1 -0
  238. package/dist/inputs/selectAllState.js +20 -0
  239. package/dist/inputs/selectAllState.js.map +1 -0
  240. package/dist/inputs/useRowKeys.js +26 -0
  241. package/dist/inputs/useRowKeys.js.map +1 -0
  242. package/dist/kanban/KanbanBoard.js +3 -2
  243. package/dist/kanban/KanbanBoard.js.map +1 -1
  244. package/dist/legal/CookieNotice.js +80 -0
  245. package/dist/legal/CookieNotice.js.map +1 -0
  246. package/dist/legal/TermsAcceptanceDialog.js +130 -0
  247. package/dist/legal/TermsAcceptanceDialog.js.map +1 -0
  248. package/dist/legal/consentStorage.js +18 -0
  249. package/dist/legal/consentStorage.js.map +1 -0
  250. package/dist/legal/useCookieConsent.js +17 -0
  251. package/dist/legal/useCookieConsent.js.map +1 -0
  252. package/dist/locales/en.js +257 -1
  253. package/dist/locales/en.js.map +1 -1
  254. package/dist/locales/es.js +257 -1
  255. package/dist/locales/es.js.map +1 -1
  256. package/dist/maps/MapView.js +3 -2
  257. package/dist/maps/MapView.js.map +1 -1
  258. package/dist/mexico/CfdiSummary.js +82 -0
  259. package/dist/mexico/CfdiSummary.js.map +1 -0
  260. package/dist/mexico/EfirmaFields.js +168 -0
  261. package/dist/mexico/EfirmaFields.js.map +1 -0
  262. package/dist/mexico/certificateReader.js +79 -0
  263. package/dist/mexico/certificateReader.js.map +1 -0
  264. package/dist/mexico/cfdiReader.js +81 -0
  265. package/dist/mexico/cfdiReader.js.map +1 -0
  266. package/dist/mexico/derReader.js +81 -0
  267. package/dist/mexico/derReader.js.map +1 -0
  268. package/dist/mexico/efirmaKey.js +51 -0
  269. package/dist/mexico/efirmaKey.js.map +1 -0
  270. package/dist/mexico/mexicoIdentifiers.js +91 -0
  271. package/dist/mexico/mexicoIdentifiers.js.map +1 -0
  272. package/dist/mexico/mexicoRules.js +21 -0
  273. package/dist/mexico/mexicoRules.js.map +1 -0
  274. package/dist/mexico.js +34 -0
  275. package/dist/mexico.js.map +1 -0
  276. package/dist/pwa/InstallAppSetting.js +3 -2
  277. package/dist/pwa/InstallAppSetting.js.map +1 -1
  278. package/dist/pwa/InstallInstructionsDialog.js +3 -2
  279. package/dist/pwa/InstallInstructionsDialog.js.map +1 -1
  280. package/dist/pwa/InstallPromptBanner.js +3 -2
  281. package/dist/pwa/InstallPromptBanner.js.map +1 -1
  282. package/dist/react-hook-form.js +43 -17
  283. package/dist/react-hook-form.js.map +1 -1
  284. package/dist/rich-text.js +19 -0
  285. package/dist/rich-text.js.map +1 -0
  286. package/dist/richText/FormRichTextField.js +12 -0
  287. package/dist/richText/FormRichTextField.js.map +1 -0
  288. package/dist/richText/RichTextEditor.js +111 -0
  289. package/dist/richText/RichTextEditor.js.map +1 -0
  290. package/dist/richText/RichTextLinkPopover.js +57 -0
  291. package/dist/richText/RichTextLinkPopover.js.map +1 -0
  292. package/dist/richText/RichTextToolbar.js +189 -0
  293. package/dist/richText/RichTextToolbar.js.map +1 -0
  294. package/dist/richText/RichTextView.js +27 -0
  295. package/dist/richText/RichTextView.js.map +1 -0
  296. package/dist/richText/richTextContentSx.js +42 -0
  297. package/dist/richText/richTextContentSx.js.map +1 -0
  298. package/dist/richText/richTextExtensions.js +44 -0
  299. package/dist/richText/richTextExtensions.js.map +1 -0
  300. package/dist/richText/richTextRules.js +46 -0
  301. package/dist/richText/richTextRules.js.map +1 -0
  302. package/dist/security/ActivityLog.js +3 -2
  303. package/dist/security/ActivityLog.js.map +1 -1
  304. package/dist/security/RecoveryCodesDialog.js +3 -2
  305. package/dist/security/RecoveryCodesDialog.js.map +1 -1
  306. package/dist/security/SessionsCard.js +3 -2
  307. package/dist/security/SessionsCard.js.map +1 -1
  308. package/dist/table.js +23 -2
  309. package/dist/table.js.map +1 -1
  310. package/dist/theme/components/glassComponents.js +27 -0
  311. package/dist/theme/components/glassComponents.js.map +1 -1
  312. package/dist/theme/components/minimalComponents.js +12 -0
  313. package/dist/theme/components/minimalComponents.js.map +1 -1
  314. package/dist/theme/themePieces.js +70 -4
  315. package/dist/theme/themePieces.js.map +1 -1
  316. package/dist/toolkit/ToolkitProvider.js +8 -1
  317. package/dist/toolkit/ToolkitProvider.js.map +1 -1
  318. package/dist/toolkit/browserNavigation.js +19 -4
  319. package/dist/toolkit/browserNavigation.js.map +1 -1
  320. package/dist/toolkit/combineTexts.js +32 -0
  321. package/dist/toolkit/combineTexts.js.map +1 -0
  322. package/dist/toolkit/hashNavigation.js +17 -3
  323. package/dist/toolkit/hashNavigation.js.map +1 -1
  324. package/dist/toolkit/navigationPaths.js +15 -0
  325. package/dist/toolkit/navigationPaths.js.map +1 -1
  326. package/dist/toolkit/pathIndex.js +66 -0
  327. package/dist/toolkit/pathIndex.js.map +1 -0
  328. package/dist/toolkit/toolkitSettings.js +19 -1
  329. package/dist/toolkit/toolkitSettings.js.map +1 -1
  330. package/dist/types/DataTable/AuditTrailDialog.d.ts +6 -17
  331. package/dist/types/DataTable/ColumnFilters/HeaderFilterPopover.d.ts +6 -5
  332. package/dist/types/DataTable/ColumnFilters/MultiSelectColumnFilter.d.ts +6 -9
  333. package/dist/types/DataTable/ColumnFilters/SortableFilterHeader.d.ts +6 -14
  334. package/dist/types/DataTable/EmptyState.d.ts +6 -9
  335. package/dist/types/DataTable/FilterChips.d.ts +6 -11
  336. package/dist/types/DataTable/GoToPage.d.ts +6 -9
  337. package/dist/types/DataTable/ServerTable.d.ts +16 -80
  338. package/dist/types/DataTable/ServerTableFilterDrawer.d.ts +14 -0
  339. package/dist/types/DataTable/StackedCell.d.ts +12 -0
  340. package/dist/types/DataTable/TableCardsView.d.ts +27 -0
  341. package/dist/types/DataTable/columnWidths.d.ts +21 -0
  342. package/dist/types/DataTable/columns.d.ts +111 -0
  343. package/dist/types/DataTable/filterContext.d.ts +2 -1
  344. package/dist/types/DataTable/fixedColumns.d.ts +29 -0
  345. package/dist/types/DataTable/goToPageOptions.d.ts +15 -0
  346. package/dist/types/DataTable/index.d.ts +7 -1
  347. package/dist/types/DataTable/useTableView.d.ts +22 -0
  348. package/dist/types/access/PermissionMatrix.d.ts +6 -10
  349. package/dist/types/account/AccountSecuritySection.d.ts +6 -7
  350. package/dist/types/account/DemoTotpCodeButton.d.ts +6 -5
  351. package/dist/types/account/ProfileScreen.d.ts +6 -18
  352. package/dist/types/account/SignInScreen.d.ts +6 -13
  353. package/dist/types/appShell/AccountMenu.d.ts +6 -11
  354. package/dist/types/appShell/AppLayout.d.ts +3 -40
  355. package/dist/types/appShell/AppearanceSettings.d.ts +6 -12
  356. package/dist/types/appShell/AuthLayout.d.ts +3 -11
  357. package/dist/types/appShell/BarActionButton.d.ts +6 -10
  358. package/dist/types/appShell/BarActions.d.ts +6 -15
  359. package/dist/types/appShell/BarCapsule.d.ts +6 -9
  360. package/dist/types/appShell/BarSearch.d.ts +6 -15
  361. package/dist/types/appShell/HeaderTools.d.ts +6 -16
  362. package/dist/types/appShell/MobileTabBar.d.ts +6 -13
  363. package/dist/types/appShell/SettingsMenu.d.ts +6 -10
  364. package/dist/types/appShell/SideMenu.d.ts +6 -20
  365. package/dist/types/appShell/SideMenuEntry.d.ts +6 -11
  366. package/dist/types/appShell/SubmenuActionsMenu.d.ts +6 -12
  367. package/dist/types/appShell/TabBarEditor.d.ts +6 -9
  368. package/dist/types/appShell/TopMenu.d.ts +6 -5
  369. package/dist/types/appShell/Wordmark.d.ts +6 -7
  370. package/dist/types/auth/PasswordChecklist.d.ts +6 -9
  371. package/dist/types/calendar/EventCalendar.d.ts +6 -23
  372. package/dist/types/calendar/EventDetails.d.ts +6 -10
  373. package/dist/types/date-pickers.d.ts +10 -1
  374. package/dist/types/datePickers/DateInput.d.ts +10 -23
  375. package/dist/types/datePickers/DateTimeInput.d.ts +30 -0
  376. package/dist/types/datePickers/FormDateTimeField.d.ts +7 -0
  377. package/dist/types/datePickers/FormMonthField.d.ts +7 -0
  378. package/dist/types/datePickers/FormTimeField.d.ts +7 -0
  379. package/dist/types/datePickers/MonthInput.d.ts +25 -0
  380. package/dist/types/datePickers/PickerFrame.d.ts +22 -0
  381. package/dist/types/datePickers/TimeInput.d.ts +24 -0
  382. package/dist/types/datePickers/dateTimeRules.d.ts +31 -0
  383. package/dist/types/datePickers/pickerValues.d.ts +114 -0
  384. package/dist/types/datePickers/useCurrentMinute.d.ts +5 -0
  385. package/dist/types/datePickers/usePickerField.d.ts +28 -0
  386. package/dist/types/dictionaries/dictionaries.d.ts +6 -3
  387. package/dist/types/downloads/DownloadManager.d.ts +6 -6
  388. package/dist/types/feedback/ConfirmDialog.d.ts +6 -18
  389. package/dist/types/feedback/ModalWaiting.d.ts +6 -9
  390. package/dist/types/feedback/NewBuildNotice.d.ts +6 -10
  391. package/dist/types/filepond/FileDropzone.d.ts +6 -29
  392. package/dist/types/forms/FormAttachmentsField.d.ts +7 -0
  393. package/dist/types/forms/FormCheckboxGroupField.d.ts +7 -0
  394. package/dist/types/forms/FormFileField.d.ts +7 -0
  395. package/dist/types/forms/FormFileUploadField.d.ts +7 -0
  396. package/dist/types/forms/FormImageField.d.ts +7 -0
  397. package/dist/types/forms/FormMaskedField.d.ts +7 -0
  398. package/dist/types/forms/FormProblemAlert.d.ts +6 -5
  399. package/dist/types/forms/FormRepeatingFields.d.ts +25 -0
  400. package/dist/types/forms/FormTransferListField.d.ts +7 -0
  401. package/dist/types/forms/SubmitButton.d.ts +6 -6
  402. package/dist/types/forms/auth/SignInForm.d.ts +6 -11
  403. package/dist/types/forms/fieldRules.d.ts +44 -0
  404. package/dist/types/forms/index.d.ts +11 -1
  405. package/dist/types/forms/listRules.d.ts +48 -0
  406. package/dist/types/forms/security/SecondStepForm.d.ts +6 -14
  407. package/dist/types/forms/security/TwoStepVerificationCard.d.ts +6 -21
  408. package/dist/types/forms/serverProblemFields.d.ts +13 -0
  409. package/dist/types/forms/useValidationText.d.ts +12 -0
  410. package/dist/types/forms/validation.d.ts +117 -174
  411. package/dist/types/forms/validationMessages.d.ts +54 -6
  412. package/dist/types/forms.d.ts +1 -1
  413. package/dist/types/hookForm/FormAttachmentsField.d.ts +8 -0
  414. package/dist/types/hookForm/FormCheckboxGroupField.d.ts +8 -0
  415. package/dist/types/hookForm/FormFileField.d.ts +8 -0
  416. package/dist/types/hookForm/FormFileUploadField.d.ts +8 -0
  417. package/dist/types/hookForm/FormImageField.d.ts +8 -0
  418. package/dist/types/hookForm/FormMaskedField.d.ts +9 -0
  419. package/dist/types/hookForm/FormProblemAlert.d.ts +6 -5
  420. package/dist/types/hookForm/FormRepeatingFields.d.ts +27 -0
  421. package/dist/types/hookForm/FormTransferListField.d.ts +8 -0
  422. package/dist/types/hookForm/SubmitButton.d.ts +6 -13
  423. package/dist/types/inbox/InboxLayout.d.ts +6 -17
  424. package/dist/types/inbox/MessageList.d.ts +6 -18
  425. package/dist/types/inbox/MessageView.d.ts +6 -14
  426. package/dist/types/index.d.ts +33 -4
  427. package/dist/types/inputs/CatalogInput.d.ts +10 -21
  428. package/dist/types/inputs/CheckboxGroupInput.d.ts +28 -0
  429. package/dist/types/inputs/ColorInput.d.ts +7 -16
  430. package/dist/types/inputs/FieldFrame.d.ts +6 -10
  431. package/dist/types/inputs/MaskedInput.d.ts +38 -0
  432. package/dist/types/inputs/NumberInput.d.ts +7 -20
  433. package/dist/types/inputs/RepeatingFields.d.ts +31 -0
  434. package/dist/types/inputs/SelectInput.d.ts +10 -18
  435. package/dist/types/inputs/TextInput.d.ts +3 -0
  436. package/dist/types/inputs/TransferListInput.d.ts +30 -0
  437. package/dist/types/inputs/WizardLayout.d.ts +6 -19
  438. package/dist/types/inputs/inputMasks.d.ts +52 -0
  439. package/dist/types/inputs/selectAllState.d.ts +11 -0
  440. package/dist/types/inputs/useRowKeys.d.ts +11 -0
  441. package/dist/types/kanban/KanbanBoard.d.ts +6 -25
  442. package/dist/types/legal/CookieNotice.d.ts +20 -0
  443. package/dist/types/legal/TermsAcceptanceDialog.d.ts +20 -0
  444. package/dist/types/legal/consentStorage.d.ts +16 -0
  445. package/dist/types/legal/useCookieConsent.d.ts +13 -0
  446. package/dist/types/locales/en.d.ts +256 -0
  447. package/dist/types/locales/es.d.ts +256 -0
  448. package/dist/types/maps/MapView.d.ts +6 -17
  449. package/dist/types/mexico/CfdiSummary.d.ts +12 -0
  450. package/dist/types/mexico/EfirmaFields.d.ts +28 -0
  451. package/dist/types/mexico/certificateReader.d.ts +37 -0
  452. package/dist/types/mexico/cfdiReader.d.ts +95 -0
  453. package/dist/types/mexico/derReader.d.ts +54 -0
  454. package/dist/types/mexico/efirmaKey.d.ts +26 -0
  455. package/dist/types/mexico/mexicoIdentifiers.d.ts +68 -0
  456. package/dist/types/mexico/mexicoRules.d.ts +45 -0
  457. package/dist/types/mexico.d.ts +11 -0
  458. package/dist/types/pwa/InstallAppSetting.d.ts +6 -6
  459. package/dist/types/pwa/InstallInstructionsDialog.d.ts +6 -9
  460. package/dist/types/pwa/InstallPromptBanner.d.ts +6 -11
  461. package/dist/types/react-hook-form.d.ts +11 -1
  462. package/dist/types/rich-text.d.ts +5 -0
  463. package/dist/types/richText/FormRichTextField.d.ts +7 -0
  464. package/dist/types/richText/RichTextEditor.d.ts +27 -0
  465. package/dist/types/richText/RichTextLinkPopover.d.ts +17 -0
  466. package/dist/types/richText/RichTextToolbar.d.ts +15 -0
  467. package/dist/types/richText/RichTextView.d.ts +10 -0
  468. package/dist/types/richText/richTextContentSx.d.ts +7 -0
  469. package/dist/types/richText/richTextExtensions.d.ts +15 -0
  470. package/dist/types/richText/richTextRules.d.ts +41 -0
  471. package/dist/types/security/ActivityLog.d.ts +6 -9
  472. package/dist/types/security/RecoveryCodesDialog.d.ts +6 -11
  473. package/dist/types/security/SessionsCard.d.ts +6 -11
  474. package/dist/types/table.d.ts +3 -1
  475. package/dist/types/theme/themePieces.d.ts +55 -3
  476. package/dist/types/toolkit/ToolkitProvider.d.ts +13 -1
  477. package/dist/types/toolkit/browserNavigation.d.ts +7 -3
  478. package/dist/types/toolkit/combineTexts.d.ts +6 -0
  479. package/dist/types/toolkit/hashNavigation.d.ts +4 -2
  480. package/dist/types/toolkit/navigationPaths.d.ts +35 -0
  481. package/dist/types/toolkit/pathIndex.d.ts +27 -0
  482. package/dist/types/toolkit/toolkitSettings.d.ts +7 -4
  483. package/dist/types/ui/actions/ActionsMenu.d.ts +24 -11
  484. package/dist/types/ui/actions/CopyButton.d.ts +8 -11
  485. package/dist/types/ui/actions/DownloadMenu.d.ts +6 -29
  486. package/dist/types/ui/actions/SecretField.d.ts +6 -11
  487. package/dist/types/ui/actions/SelectionActions.d.ts +6 -13
  488. package/dist/types/ui/actions/tableRowText.d.ts +6 -0
  489. package/dist/types/ui/cards/RecordCard.d.ts +40 -0
  490. package/dist/types/ui/cards/RecordCardSkeleton.d.ts +12 -0
  491. package/dist/types/ui/countdown/Countdown.d.ts +22 -0
  492. package/dist/types/ui/countdown/countdownParts.d.ts +39 -0
  493. package/dist/types/ui/countdown/useCountdown.d.ts +14 -0
  494. package/dist/types/ui/documents/PdfViewerDialog.d.ts +14 -0
  495. package/dist/types/ui/filters/DateRangeFilter.d.ts +6 -10
  496. package/dist/types/ui/filters/FilterDrawer.d.ts +23 -0
  497. package/dist/types/ui/filters/PeriodRangeSelector.d.ts +6 -13
  498. package/dist/types/ui/filters/QuickFilters.d.ts +6 -12
  499. package/dist/types/ui/filters/filterDrawerFields.d.ts +139 -0
  500. package/dist/types/ui/help/HelpButton.d.ts +11 -0
  501. package/dist/types/ui/help/HelpCarouselDialog.d.ts +27 -0
  502. package/dist/types/ui/help/useHelpCarousel.d.ts +21 -0
  503. package/dist/types/ui/index.d.ts +10 -0
  504. package/dist/types/ui/labels/IconBadge.d.ts +34 -0
  505. package/dist/types/ui/labels/MarkedText.d.ts +10 -0
  506. package/dist/types/ui/labels/Tag.d.ts +6 -12
  507. package/dist/types/ui/labels/markedTextPieces.d.ts +22 -0
  508. package/dist/types/ui/layout/CollapsibleSection.d.ts +6 -12
  509. package/dist/types/ui/layout/ContentDialog.d.ts +6 -10
  510. package/dist/types/ui/layout/DefinitionList.d.ts +6 -9
  511. package/dist/types/ui/layout/DetailHeader.d.ts +6 -10
  512. package/dist/types/ui/layout/ErrorPage.d.ts +6 -17
  513. package/dist/types/ui/layout/FullPageLoader.d.ts +6 -6
  514. package/dist/types/ui/layout/GlassPanel.d.ts +6 -8
  515. package/dist/types/ui/layout/PageHeader.d.ts +6 -10
  516. package/dist/types/ui/layout/PageHeading.d.ts +6 -11
  517. package/dist/types/ui/layout/ProfileHeader.d.ts +6 -11
  518. package/dist/types/ui/layout/ScrollableRow.d.ts +6 -13
  519. package/dist/types/ui/layout/SectionCard.d.ts +6 -8
  520. package/dist/types/ui/metrics/BarList.d.ts +6 -12
  521. package/dist/types/ui/metrics/CalendarHeatmap.d.ts +6 -19
  522. package/dist/types/ui/metrics/ChartTooltip.d.ts +6 -6
  523. package/dist/types/ui/metrics/ColumnChart.d.ts +6 -25
  524. package/dist/types/ui/metrics/LineChart.d.ts +6 -20
  525. package/dist/types/ui/metrics/MetricCard.d.ts +6 -17
  526. package/dist/types/ui/metrics/TableToggle.d.ts +6 -6
  527. package/dist/types/ui/metrics/chartParts.d.ts +15 -30
  528. package/dist/types/ui/navigation/BackButton.d.ts +6 -9
  529. package/dist/types/ui/navigation/ColorSchemeToggle.d.ts +6 -9
  530. package/dist/types/ui/navigation/FontSizeToggle.d.ts +6 -8
  531. package/dist/types/ui/navigation/LanguageToggle.d.ts +6 -8
  532. package/dist/types/ui/navigation/PageBreadcrumbs.d.ts +6 -7
  533. package/dist/types/ui/navigation/RouteTabs.d.ts +39 -0
  534. package/dist/types/ui/navigation/routeTabMatching.d.ts +27 -0
  535. package/dist/types/ui/timeline/GroupedTimeline.d.ts +6 -23
  536. package/dist/types/upload/AttachmentsInput.d.ts +72 -0
  537. package/dist/types/upload/FileChip.d.ts +18 -0
  538. package/dist/types/upload/FileDropzone.d.ts +7 -19
  539. package/dist/types/upload/FileInput.d.ts +31 -0
  540. package/dist/types/upload/FileUploadInput.d.ts +56 -0
  541. package/dist/types/upload/ImageInput.d.ts +35 -0
  542. package/dist/types/upload/TemplateDownloadButton.d.ts +27 -0
  543. package/dist/types/upload/fileAppearance.d.ts +8 -0
  544. package/dist/types/upload/fileRules.d.ts +38 -0
  545. package/dist/types/upload/transferProgress.d.ts +18 -0
  546. package/dist/types/upload/uploadMachine.d.ts +6 -2
  547. package/dist/types/upload/uploadWithProgress.d.ts +6 -2
  548. package/dist/types/upload/useFilePicker.d.ts +39 -0
  549. package/dist/ui/actions/ActionsMenu.js +109 -17
  550. package/dist/ui/actions/ActionsMenu.js.map +1 -1
  551. package/dist/ui/actions/CopyButton.js +37 -12
  552. package/dist/ui/actions/CopyButton.js.map +1 -1
  553. package/dist/ui/actions/DownloadMenu.js +3 -2
  554. package/dist/ui/actions/DownloadMenu.js.map +1 -1
  555. package/dist/ui/actions/SecretField.js +8 -3
  556. package/dist/ui/actions/SecretField.js.map +1 -1
  557. package/dist/ui/actions/SelectionActions.js +3 -2
  558. package/dist/ui/actions/SelectionActions.js.map +1 -1
  559. package/dist/ui/actions/tableRowText.js +7 -0
  560. package/dist/ui/actions/tableRowText.js.map +1 -0
  561. package/dist/ui/cards/RecordCard.js +146 -0
  562. package/dist/ui/cards/RecordCard.js.map +1 -0
  563. package/dist/ui/cards/RecordCardSkeleton.js +38 -0
  564. package/dist/ui/cards/RecordCardSkeleton.js.map +1 -0
  565. package/dist/ui/countdown/Countdown.js +39 -0
  566. package/dist/ui/countdown/Countdown.js.map +1 -0
  567. package/dist/ui/countdown/countdownParts.js +34 -0
  568. package/dist/ui/countdown/countdownParts.js.map +1 -0
  569. package/dist/ui/countdown/useCountdown.js +35 -0
  570. package/dist/ui/countdown/useCountdown.js.map +1 -0
  571. package/dist/ui/documents/PdfViewerDialog.js +82 -0
  572. package/dist/ui/documents/PdfViewerDialog.js.map +1 -0
  573. package/dist/ui/filters/DateRangeFilter.js +3 -2
  574. package/dist/ui/filters/DateRangeFilter.js.map +1 -1
  575. package/dist/ui/filters/FilterDrawer.js +212 -0
  576. package/dist/ui/filters/FilterDrawer.js.map +1 -0
  577. package/dist/ui/filters/PeriodRangeSelector.js +3 -2
  578. package/dist/ui/filters/PeriodRangeSelector.js.map +1 -1
  579. package/dist/ui/filters/QuickFilters.js +3 -2
  580. package/dist/ui/filters/QuickFilters.js.map +1 -1
  581. package/dist/ui/filters/filterDrawerFields.js +119 -0
  582. package/dist/ui/filters/filterDrawerFields.js.map +1 -0
  583. package/dist/ui/help/HelpButton.js +22 -0
  584. package/dist/ui/help/HelpButton.js.map +1 -0
  585. package/dist/ui/help/HelpCarouselDialog.js +155 -0
  586. package/dist/ui/help/HelpCarouselDialog.js.map +1 -0
  587. package/dist/ui/help/useHelpCarousel.js +25 -0
  588. package/dist/ui/help/useHelpCarousel.js.map +1 -0
  589. package/dist/ui/labels/IconBadge.js +82 -0
  590. package/dist/ui/labels/IconBadge.js.map +1 -0
  591. package/dist/ui/labels/MarkedText.js +31 -0
  592. package/dist/ui/labels/MarkedText.js.map +1 -0
  593. package/dist/ui/labels/Tag.js +3 -2
  594. package/dist/ui/labels/Tag.js.map +1 -1
  595. package/dist/ui/labels/markedTextPieces.js +64 -0
  596. package/dist/ui/labels/markedTextPieces.js.map +1 -0
  597. package/dist/ui/layout/CollapsibleSection.js +3 -2
  598. package/dist/ui/layout/CollapsibleSection.js.map +1 -1
  599. package/dist/ui/layout/ContentDialog.js +3 -2
  600. package/dist/ui/layout/ContentDialog.js.map +1 -1
  601. package/dist/ui/layout/DefinitionList.js +3 -2
  602. package/dist/ui/layout/DefinitionList.js.map +1 -1
  603. package/dist/ui/layout/DetailHeader.js +3 -2
  604. package/dist/ui/layout/DetailHeader.js.map +1 -1
  605. package/dist/ui/layout/ErrorPage.js +3 -2
  606. package/dist/ui/layout/ErrorPage.js.map +1 -1
  607. package/dist/ui/layout/FullPageLoader.js +3 -2
  608. package/dist/ui/layout/FullPageLoader.js.map +1 -1
  609. package/dist/ui/layout/GlassPanel.js +3 -2
  610. package/dist/ui/layout/GlassPanel.js.map +1 -1
  611. package/dist/ui/layout/PageHeader.js +3 -2
  612. package/dist/ui/layout/PageHeader.js.map +1 -1
  613. package/dist/ui/layout/PageHeading.js +3 -2
  614. package/dist/ui/layout/PageHeading.js.map +1 -1
  615. package/dist/ui/layout/ProfileHeader.js +3 -2
  616. package/dist/ui/layout/ProfileHeader.js.map +1 -1
  617. package/dist/ui/layout/ScrollableRow.js +3 -2
  618. package/dist/ui/layout/ScrollableRow.js.map +1 -1
  619. package/dist/ui/layout/SectionCard.js +3 -2
  620. package/dist/ui/layout/SectionCard.js.map +1 -1
  621. package/dist/ui/metrics/BarList.js +3 -2
  622. package/dist/ui/metrics/BarList.js.map +1 -1
  623. package/dist/ui/metrics/CalendarHeatmap.js +3 -2
  624. package/dist/ui/metrics/CalendarHeatmap.js.map +1 -1
  625. package/dist/ui/metrics/ChartTooltip.js +3 -2
  626. package/dist/ui/metrics/ChartTooltip.js.map +1 -1
  627. package/dist/ui/metrics/ColumnChart.js +3 -2
  628. package/dist/ui/metrics/ColumnChart.js.map +1 -1
  629. package/dist/ui/metrics/LineChart.js +3 -2
  630. package/dist/ui/metrics/LineChart.js.map +1 -1
  631. package/dist/ui/metrics/MetricCard.js +3 -2
  632. package/dist/ui/metrics/MetricCard.js.map +1 -1
  633. package/dist/ui/metrics/TableToggle.js +3 -2
  634. package/dist/ui/metrics/TableToggle.js.map +1 -1
  635. package/dist/ui/metrics/chartParts.js +7 -4
  636. package/dist/ui/metrics/chartParts.js.map +1 -1
  637. package/dist/ui/navigation/BackButton.js +7 -2
  638. package/dist/ui/navigation/BackButton.js.map +1 -1
  639. package/dist/ui/navigation/ColorSchemeToggle.js +3 -2
  640. package/dist/ui/navigation/ColorSchemeToggle.js.map +1 -1
  641. package/dist/ui/navigation/FontSizeToggle.js +3 -2
  642. package/dist/ui/navigation/FontSizeToggle.js.map +1 -1
  643. package/dist/ui/navigation/LanguageToggle.js +3 -2
  644. package/dist/ui/navigation/LanguageToggle.js.map +1 -1
  645. package/dist/ui/navigation/PageBreadcrumbs.js +3 -2
  646. package/dist/ui/navigation/PageBreadcrumbs.js.map +1 -1
  647. package/dist/ui/navigation/RouteTabs.js +79 -0
  648. package/dist/ui/navigation/RouteTabs.js.map +1 -0
  649. package/dist/ui/navigation/routeTabMatching.js +23 -0
  650. package/dist/ui/navigation/routeTabMatching.js.map +1 -0
  651. package/dist/ui/timeline/GroupedTimeline.js +3 -2
  652. package/dist/ui/timeline/GroupedTimeline.js.map +1 -1
  653. package/dist/upload/AttachmentsInput.js +130 -0
  654. package/dist/upload/AttachmentsInput.js.map +1 -0
  655. package/dist/upload/FileChip.js +28 -0
  656. package/dist/upload/FileChip.js.map +1 -0
  657. package/dist/upload/FileDropzone.js +23 -87
  658. package/dist/upload/FileDropzone.js.map +1 -1
  659. package/dist/upload/FileInput.js +115 -0
  660. package/dist/upload/FileInput.js.map +1 -0
  661. package/dist/upload/FileUploadInput.js +288 -0
  662. package/dist/upload/FileUploadInput.js.map +1 -0
  663. package/dist/upload/ImageInput.js +128 -0
  664. package/dist/upload/ImageInput.js.map +1 -0
  665. package/dist/upload/TemplateDownloadButton.js +68 -0
  666. package/dist/upload/TemplateDownloadButton.js.map +1 -0
  667. package/dist/upload/fileAppearance.js +21 -0
  668. package/dist/upload/fileAppearance.js.map +1 -0
  669. package/dist/upload/fileRules.js +27 -1
  670. package/dist/upload/fileRules.js.map +1 -1
  671. package/dist/upload/transferProgress.js +23 -0
  672. package/dist/upload/transferProgress.js.map +1 -0
  673. package/dist/upload/uploadMachine.js +8 -8
  674. package/dist/upload/uploadMachine.js.map +1 -1
  675. package/dist/upload/uploadWithProgress.js +1 -1
  676. package/dist/upload/uploadWithProgress.js.map +1 -1
  677. package/dist/upload/useFilePicker.js +101 -0
  678. package/dist/upload/useFilePicker.js.map +1 -0
  679. package/package.json +44 -1
  680. package/cli/templates/project/src/app/combineTexts.js.tpl +0 -31
@@ -1 +1 @@
1
- {"version":3,"file":"CopyButton.js","sources":["../../../src/ui/actions/CopyButton.jsx"],"sourcesContent":["// Botón para copiar un valor al portapapeles, con la palomita de «copiado» un par de segundos.\n//\n// Sin permiso de portapapeles (una página en http, dentro de un iframe) no truena: el valor sigue a la vista para copiarlo\n// a mano.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport IconButton from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport CheckIcon from '@mui/icons-material/CheckRounded';\nimport CopyIcon from '@mui/icons-material/ContentCopyOutlined';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// cuánto se queda la palomita de «copiado»\nconst COPIED_FEEDBACK_MILLISECONDS = 2000;\n\n/**\n * @param {object} props\n * @param {string} props.value lo que se copia\n * @param {string} [props.label] ya traducido; por omisión «Copiar»\n * @param {'small'|'medium'} [props.size]\n * @param {() => void} [props.onCopied]\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nexport default function CopyButton({value, label, size = 'small', onCopied, texts, ...unknownProps}) {\n warnUnknownProps('CopyButton', unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const [isCopied, setIsCopied] = useState(false);\n const buttonLabel = label ?? t('form.copy');\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(value);\n setIsCopied(true);\n onCopied?.();\n setTimeout(() => setIsCopied(false), COPIED_FEEDBACK_MILLISECONDS);\n } catch {\n // sin permiso de portapapeles: el valor está a la vista para copiarlo a mano\n }\n };\n\n return (\n <Tooltip title={isCopied ? t('form.copied') : buttonLabel}>\n <IconButton size={size} aria-label={buttonLabel} onClick={copy} color={isCopied ? 'success' : 'default'}>\n {isCopied ? <CheckIcon fontSize=\"inherit\" /> : <CopyIcon fontSize=\"inherit\" />}\n </IconButton>\n </Tooltip>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AAeA,MAAM,+BAA+B;AAUrC,SAAwB,WAAW,EAAC,OAAO,OAAO,OAAO,SAAS,UAAU,OAAO,GAAG,gBAAe;AACjG,mBAAiB,cAAc,YAAY;AAC3C,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,cAAc,SAAS,EAAE,WAAW;AAE1C,QAAM,OAAO,YAAY;AACrB,QAAI;AACA,YAAM,UAAU,UAAU,UAAU,KAAK;AACzC,kBAAY,IAAI;AAChB,iBAAA;AACA,iBAAW,MAAM,YAAY,KAAK,GAAG,4BAA4B;AAAA,IACrE,QAAQ;AAAA,IAER;AAAA,EACJ;AAEA,SACI,oBAAC,SAAA,EAAQ,OAAO,WAAW,EAAE,aAAa,IAAI,aAC1C,UAAA,oBAAC,YAAA,EAAW,MAAY,cAAY,aAAa,SAAS,MAAM,OAAO,WAAW,YAAY,WACzF,UAAA,WAAW,oBAAC,WAAA,EAAU,UAAS,UAAA,CAAU,IAAK,oBAAC,UAAA,EAAS,UAAS,UAAA,CAAU,GAChF,GACJ;AAER;"}
1
+ {"version":3,"file":"CopyButton.js","sources":["../../../src/ui/actions/CopyButton.jsx"],"sourcesContent":["// Botón para copiar al portapapeles: un ícono que pone el texto y lo confirma ahí mismo («Copiado» un par de segundos, con la\n// palomita). Va donde copiar a mano cuesta trabajo: un folio, un texto largo que en pantalla va cortado, un renglón entero\n// (con tableRowTextOf: separado por tabuladores, al pegarlo en Excel cada dato cae en su celda).\n//\n// Si el navegador no deja copiar (una página en http, dentro de un iframe, sin permiso), el botón lo dice en rojo en lugar\n// de fingir que copió, y avisa con onCopyFailed. La confirmación también se anuncia a los lectores de pantalla (el globo no\n// siempre se anuncia).\n//\n// value puede ser una función: se llama al picar (arma el renglón solo si de verdad se copia).\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaCopyButton con defaultProps, styleOverrides de\n// sus partes (button) y slots/slotProps para cambiarlas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useRef, useState} from 'react';\nimport Box from '@mui/material/Box';\nimport IconButton from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport CheckIcon from '@mui/icons-material/CheckRounded';\nimport CopyIcon from '@mui/icons-material/ContentCopyOutlined';\nimport ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';\n\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaCopyButton)\nconst THEME_NAME = 'CalcitaCopyButton';\nconst CopyButtonButton = piecePart(THEME_NAME, 'Button', IconButton);\n\n// cuánto se queda la confirmación (copiado o no se pudo) antes de regresar al ícono de copiar\nconst FEEDBACK_MILLISECONDS = 2000;\n// en qué va el botón: listo, copiado o no se pudo\nconst COPY_STATE = Object.freeze({idle: 'idle', copied: 'copied', failed: 'failed'});\nconst ICON_BY_STATE = Object.freeze({[COPY_STATE.idle]: CopyIcon, [COPY_STATE.copied]: CheckIcon, [COPY_STATE.failed]: ErrorOutlineIcon});\nconst COLOR_BY_STATE = Object.freeze({[COPY_STATE.idle]: undefined, [COPY_STATE.copied]: 'success.dark', [COPY_STATE.failed]: 'error.dark'});\n// el aviso para lectores de pantalla, escondido a la vista. OJO: '1px' en texto; en MUI un width: 1 es 100% y el texto\n// escondido ensanchaba la página\nconst VISUALLY_HIDDEN_SX = {position: 'absolute', width: '1px', height: '1px', overflow: 'hidden', clip: 'rect(0 0 0 0)', whiteSpace: 'nowrap'};\n\n/**\n * @param {object} props\n * @param {string|(() => string)} props.value lo que se copia; una función se llama al picar\n * @param {string} [props.label] ya traducido: qué copia («Copiar el folio»); por omisión «Copiar». Es el globo y el nombre\n * del botón para un lector de pantalla\n * @param {'small'|'medium'} [props.size]\n * @param {() => void} [props.onCopied]\n * @param {(error: unknown) => void} [props.onCopyFailed] el navegador no dejó copiar (el botón ya lo dice en rojo)\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction CopyButtonContent(props) {\n const {value, label, size = 'small', onCopied, onCopyFailed, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const [copyState, setCopyState] = useState(COPY_STATE.idle);\n const resetTimer = useRef(null);\n const buttonLabel = label ?? t('form.copy');\n\n // al desmontar no se queda un temporizador vivo\n useEffect(() => () => clearTimeout(resetTimer.current), []);\n\n const copy = async () => {\n clearTimeout(resetTimer.current);\n try {\n await navigator.clipboard.writeText(typeof value === 'function' ? value() : value);\n setCopyState(COPY_STATE.copied);\n onCopied?.();\n } catch (error) {\n setCopyState(COPY_STATE.failed);\n onCopyFailed?.(error);\n }\n resetTimer.current = setTimeout(() => setCopyState(COPY_STATE.idle), FEEDBACK_MILLISECONDS);\n };\n\n const feedbackText = {\n [COPY_STATE.idle]: buttonLabel,\n [COPY_STATE.copied]: t('form.copied'),\n [COPY_STATE.failed]: t('form.copyFailed'),\n }[copyState];\n const StateIcon = ICON_BY_STATE[copyState];\n\n return (\n <>\n {/* la confirmación se queda abierta mientras dura, aunque el cursor ya no esté encima; arriba y no a un lado, para no\n tapar el dato de junto */}\n <Tooltip title={feedbackText} open={copyState === COPY_STATE.idle ? undefined : true} placement=\"top\">\n <CopyButtonButton size={size} aria-label={buttonLabel} onClick={copy} sx={{color: COLOR_BY_STATE[copyState]}}>\n <StateIcon fontSize=\"inherit\" />\n </CopyButtonButton>\n </Tooltip>\n <Box component=\"span\" role=\"status\" aria-live=\"polite\" sx={VISUALLY_HIDDEN_SX}>\n {copyState === COPY_STATE.idle ? '' : feedbackText}\n </Box>\n </>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst CopyButton = withPieceSlots(CopyButtonContent, THEME_NAME);\nexport default CopyButton;\n"],"names":[],"mappings":";;;;;;;;;;;;AA2BA,MAAM,aAAa;AACnB,MAAM,mBAAmB,UAAU,YAAY,UAAU,UAAU;AAGnE,MAAM,wBAAwB;AAE9B,MAAM,aAAa,OAAO,OAAO,EAAC,MAAM,QAAQ,QAAQ,UAAU,QAAQ,UAAS;AACnF,MAAM,gBAAgB,OAAO,OAAO,EAAC,CAAC,WAAW,IAAI,GAAG,UAAU,CAAC,WAAW,MAAM,GAAG,WAAW,CAAC,WAAW,MAAM,GAAG,kBAAiB;AACxI,MAAM,iBAAiB,OAAO,OAAO,EAAC,CAAC,WAAW,IAAI,GAAG,QAAW,CAAC,WAAW,MAAM,GAAG,gBAAgB,CAAC,WAAW,MAAM,GAAG,cAAa;AAG3I,MAAM,qBAAqB,EAAC,UAAU,YAAY,OAAO,OAAO,QAAQ,OAAO,UAAU,UAAU,MAAM,iBAAiB,YAAY,SAAA;AAYtI,SAAS,kBAAkB,OAAO;AAC9B,QAAM,EAAC,OAAO,OAAO,OAAO,SAAS,UAAU,cAAc,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AACtH,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,WAAW,IAAI;AAC1D,QAAM,aAAa,OAAO,IAAI;AAC9B,QAAM,cAAc,SAAS,EAAE,WAAW;AAG1C,YAAU,MAAM,MAAM,aAAa,WAAW,OAAO,GAAG,CAAA,CAAE;AAE1D,QAAM,OAAO,YAAY;AACrB,iBAAa,WAAW,OAAO;AAC/B,QAAI;AACA,YAAM,UAAU,UAAU,UAAU,OAAO,UAAU,aAAa,MAAA,IAAU,KAAK;AACjF,mBAAa,WAAW,MAAM;AAC9B,iBAAA;AAAA,IACJ,SAAS,OAAO;AACZ,mBAAa,WAAW,MAAM;AAC9B,qBAAe,KAAK;AAAA,IACxB;AACA,eAAW,UAAU,WAAW,MAAM,aAAa,WAAW,IAAI,GAAG,qBAAqB;AAAA,EAC9F;AAEA,QAAM,eAAe;AAAA,IACjB,CAAC,WAAW,IAAI,GAAG;AAAA,IACnB,CAAC,WAAW,MAAM,GAAG,EAAE,aAAa;AAAA,IACpC,CAAC,WAAW,MAAM,GAAG,EAAE,iBAAiB;AAAA,EAAA,EAC1C,SAAS;AACX,QAAM,YAAY,cAAc,SAAS;AAEzC,SACI,qBAAA,UAAA,EAGI,UAAA;AAAA,IAAA,oBAAC,SAAA,EAAQ,OAAO,cAAc,MAAM,cAAc,WAAW,OAAO,SAAY,MAAM,WAAU,OAC5F,UAAA,oBAAC,oBAAiB,MAAY,cAAY,aAAa,SAAS,MAAM,IAAI,EAAC,OAAO,eAAe,SAAS,EAAA,GACtG,UAAA,oBAAC,WAAA,EAAU,UAAS,UAAA,CAAU,GAClC,GACJ;AAAA,IACA,oBAAC,KAAA,EAAI,WAAU,QAAO,MAAK,UAAS,aAAU,UAAS,IAAI,oBACtD,UAAA,cAAc,WAAW,OAAO,KAAK,aAAA,CAC1C;AAAA,EAAA,GACJ;AAER;AAGA,MAAM,aAAa,eAAe,mBAAmB,UAAU;"}
@@ -16,11 +16,11 @@ import { startDownload } from "../../downloads/downloadQueue.js";
16
16
  import { useFileTypes } from "../../downloads/fileTypes.js";
17
17
  import ConfirmDialog from "../../feedback/ConfirmDialog.js";
18
18
  import { useConfirmAction } from "../../feedback/useConfirmAction.js";
19
- import { piecePart, usePieceProps } from "../../theme/themePieces.js";
19
+ import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
20
20
  import { warnUnknownProps } from "../../toolkit/unknownProps.js";
21
21
  const THEME_NAME = "CalcitaDownloadMenu";
22
22
  const DownloadButton = piecePart(THEME_NAME, "Button", Button);
23
- function DownloadMenu(props) {
23
+ function DownloadMenuContent(props) {
24
24
  const {
25
25
  formats,
26
26
  download,
@@ -163,6 +163,7 @@ function DownloadMenu(props) {
163
163
  )
164
164
  ] });
165
165
  }
166
+ const DownloadMenu = withPieceSlots(DownloadMenuContent, THEME_NAME);
166
167
  export {
167
168
  DownloadMenu as default
168
169
  };
@@ -1 +1 @@
1
- {"version":3,"file":"DownloadMenu.js","sources":["../../../src/ui/actions/DownloadMenu.jsx"],"sourcesContent":["// \"Descargar ▾\" con los formatos de un reporte: PDF para leer o archivar, Excel o CSV para trabajar.\n//\n// Un solo botón y no tres: en la barra de una pantalla tres botones de descarga compiten con la acción principal.\n// Se acomoda a donde quedó, como BarActionButton: en una cápsula de la barra (las `actions` de PageHeading con cápsulas)\n// es solo el ícono con su nombre en el tooltip, como las demás acciones; antes salía la píldora «Descargar ▾» dentro de\n// la cápsula y se veía una cápsula dentro de otra. En el «⋯» del teléfono es un renglón que abre los formatos.\n// Quien llama pasa QUÉ descargar por formato (download(format, transferOptions) → {blob, fileName}, la forma de\n// un cliente HTTP que descarga). La descarga va al panel de descargas (startDownload, downloads): el diálogo se cierra al\n// confirmar y el avance, el aviso de \"descargado\" y el error se ven allá, mientras la persona sigue trabajando.\n//\n// Regla de tablas: una descarga pasa por un diálogo de confirmación que dice qué se va a bajar (p. ej. que la base\n// completa de clientes tarda unos minutos). Con `confirmation` el formato elegido NO se descarga de inmediato: abre\n// ConfirmDialog (máquina confirmActionMachine) y solo al confirmar se pide el archivo, una sola vez aunque haya doble clic.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaDownloadMenu con defaultProps y\n// styleOverrides de sus partes: button.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Button from '@mui/material/Button';\nimport IconButton from '@mui/material/IconButton';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport Menu from '@mui/material/Menu';\nimport MenuItem from '@mui/material/MenuItem';\nimport Tooltip from '@mui/material/Tooltip';\nimport ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';\nimport FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';\n\nimport {BAR_ACTIONS_PLACEMENT, useBarActionsPlacement, useCloseBarActionsMenu} from '@/appShell/barActionsSlot.js';\nimport {startDownload} from '@/downloads/downloadQueue.js';\nimport {useFileTypes} from '@/downloads/fileTypes.js';\nimport ConfirmDialog from '@/feedback/ConfirmDialog.jsx';\nimport {useConfirmAction} from '@/feedback/useConfirmAction.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaDownloadMenu)\nconst THEME_NAME = 'CalcitaDownloadMenu';\nconst DownloadButton = piecePart(THEME_NAME, 'Button', Button);\n\n\n/**\n * @param {object} props\n * @param {string[]} props.formats los tipos de archivo, en orden: los de la casa (xlsx, csv, pdf) y los que el proyecto declare\n * en ToolkitProvider fileTypes (zip, xml…)\n * @param {(format: string, transferOptions: {signal: AbortSignal, onDownloadProgress: (progress: {loaded: number, total?: number|null}) => void}) => Promise<{blob: Blob, fileName: string}>} props.download\n * @param {string} [props.label] ya traducido; por defecto \"Descargar\"\n * @param {string} [props.downloadLabel] ya traducido; lo que se ve en el panel de descargas antes de saber el nombre\n * del archivo\n * @param {boolean} [props.disabled]\n * @param {(format: string) => {title: string, description: import('react').ReactNode, confirmLabel?: string}} [props.confirmation]\n * @param {(format: string) => void} [props.onDownloaded] p. ej. volver a pedir la tabla (si la descarga cambia algo en\n * el servidor)\n * @param {(format: string, error: unknown) => void} [props.onFailed] cuando la descarga no se pudo (el panel ya lo dice)\n * @param {(format: string) => void} [props.onCanceled] cuando la persona la canceló desde el panel\n * @param {'button'|'icon'} [props.variant] icon = solo el icono (columna de acciones de una tabla)\n * @param {string} [props.ariaLabel] ya traducido; obligatorio en la variante icon\n * @param {(format: string) => void} [props.onChooseFormat] quien llama se encarga de confirmar y descargar\n * @param {import('react').ElementType} [props.icon] ícono del botón; por defecto el de descarga. Distingue dos descargas en la\n * misma fila\n *\n * IMPORTANTE: hay que pasar `confirmation` u `onChooseFormat`. Sin ninguno de los dos el menú no descarga nada (regla de\n * tablas: toda descarga pasa por confirmación).\n *\n * OJO onChooseFormat: dentro de una celda del DataGrid el diálogo de confirmación NO puede vivir en la celda (el grid\n * virtualiza y vuelve a pintar sus celdas; el diálogo se perdía al elegir el formato). Ahí el menú solo avisa qué formato\n * se eligió y la pantalla abre SU confirmación (useConfirmAction) fuera de la tabla.\n */\nexport default function DownloadMenu(props) {\n // lo que el proyecto puso en su tema (components.CalcitaDownloadMenu.defaultProps) y encima lo que llega aquí\n const {\n formats, download, label, downloadLabel, disabled = false, confirmation, onDownloaded, onFailed, onCanceled, variant = 'button', ariaLabel,\n onChooseFormat, icon: ButtonIcon = FileDownloadOutlinedIcon,\n ...unknownProps\n} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common');\n const fileTypes = useFileTypes();\n // de dónde sale el menú de formatos: del botón, o (desde el «⋯» del teléfono, que se cierra) de donde estaba el renglón\n const [anchorElement, setAnchorElement] = useState(null);\n const [anchorPosition, setAnchorPosition] = useState(null);\n const placement = useBarActionsPlacement();\n const closeMoreMenu = useCloseBarActionsMenu();\n const closeFormats = () => {\n setAnchorElement(null);\n setAnchorPosition(null);\n };\n\n // no se espera a que termine: la descarga sigue en el panel y el diálogo de confirmación se cierra de inmediato\n const runDownload = (format) => {\n startDownload({\n label: downloadLabel ?? label ?? ariaLabel ?? t('actions.download'),\n format,\n request: (transferOptions) => download(format, transferOptions),\n onCompleted: () => onDownloaded?.(format),\n onFailed: (error) => onFailed?.(format, error),\n onCanceled: () => onCanceled?.(format),\n });\n };\n\n const confirmedDownload = useConfirmAction({run: ({subject}) => runDownload(subject.format)});\n\n const chooseFormat = (format) => {\n closeFormats();\n if (onChooseFormat) {\n onChooseFormat(format);\n return;\n }\n if (confirmation) {\n confirmedDownload.open({format});\n return;\n }\n // Regla de tablas: nada se descarga con un solo clic. Sin confirmation ni onChooseFormat es un error de quien\n // llama, no un camino válido: lo decimos en la consola y no descargamos\n console.error('DownloadMenu: falta confirmation u onChooseFormat; toda descarga pasa por un diálogo de confirmación');\n };\n\n const buttonLabel = label ?? t('actions.download');\n const openMenu = (event) => setAnchorElement(event.currentTarget);\n // desde el «⋯»: se cierra ese menú y los formatos salen donde estaba el renglón\n const openFromMoreMenu = (event) => {\n const {bottom, right} = event.currentTarget.getBoundingClientRect();\n closeMoreMenu();\n setAnchorPosition({top: bottom, left: right});\n };\n const isFormatsOpen = Boolean(anchorElement || anchorPosition);\n const confirmationTexts = confirmedDownload.subject ? confirmation?.(confirmedDownload.subject.format) : null;\n\n return (\n <>\n {placement === BAR_ACTIONS_PLACEMENT.menu && (\n <MenuItem disabled={disabled} aria-haspopup=\"menu\" onClick={openFromMoreMenu}>\n <ListItemIcon><ButtonIcon /></ListItemIcon>\n <ListItemText>{buttonLabel}</ListItemText>\n </MenuItem>\n )}\n {placement === BAR_ACTIONS_PLACEMENT.capsule && (\n // en la cápsula, del tamaño y color de las demás acciones (BarActionButton)\n <Tooltip title={buttonLabel} describeChild>\n <span>\n <IconButton color=\"primary\" aria-label={buttonLabel} aria-haspopup=\"menu\" aria-expanded={isFormatsOpen}\n disabled={disabled} onClick={openMenu}>\n <ButtonIcon />\n </IconButton>\n </span>\n </Tooltip>\n )}\n {placement === BAR_ACTIONS_PLACEMENT.inline && (variant === 'icon' ? (\n // describeChild: el nombre accesible ya lo trae el botón; sin esto el Tooltip le pone el mismo aria-label al\n // span y un lector de pantalla (o una prueba) encuentra dos \"botones\" con el mismo nombre\n <Tooltip title={ariaLabel ?? buttonLabel} describeChild>\n {/* el span deja que el tooltip funcione con el botón inhabilitado */}\n <span>\n <IconButton size=\"small\" aria-label={ariaLabel ?? buttonLabel} aria-haspopup=\"menu\"\n disabled={disabled} onClick={openMenu}>\n <ButtonIcon fontSize=\"small\" />\n </IconButton>\n </span>\n </Tooltip>\n ) : (\n <DownloadButton variant=\"outlined\" startIcon={<ButtonIcon />} endIcon={<ArrowDropDownIcon />}\n ownSx={{flexShrink: 0}} disabled={disabled} aria-haspopup=\"menu\" onClick={openMenu}>\n {buttonLabel}\n </DownloadButton>\n ))}\n <Menu open={isFormatsOpen} onClose={closeFormats}\n anchorReference={anchorPosition ? 'anchorPosition' : 'anchorEl'} anchorEl={anchorElement} anchorPosition={anchorPosition ?? undefined}\n anchorOrigin={{vertical: 'bottom', horizontal: 'right'}} transformOrigin={{vertical: 'top', horizontal: 'right'}}>\n {formats.map((format) => {\n const fileType = fileTypes[format];\n const Icon = fileType?.Icon ?? FileDownloadOutlinedIcon;\n return (\n <MenuItem key={format} onClick={() => chooseFormat(format)}>\n <ListItemIcon><Icon fontSize=\"small\" /></ListItemIcon>\n {/* los de la casa con sus textos; los del proyecto con su label y hint (o esas llaves en sus texts) */}\n <ListItemText primary={t(`download.formats.${format}.label`, {defaultValue: fileType?.label ?? format.toUpperCase()})}\n secondary={t(`download.formats.${format}.hint`, {defaultValue: fileType?.hint ?? ''})}\n slotProps={{secondary: {variant: 'caption'}}} />\n </MenuItem>\n );\n })}\n </Menu>\n {confirmation && (\n <ConfirmDialog\n {...confirmedDownload.dialogProps}\n title={confirmationTexts?.title ?? ''}\n description={confirmationTexts?.description}\n confirmLabel={confirmationTexts?.confirmLabel ?? t('actions.download')}\n />\n )}\n </>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAuCA,MAAM,aAAa;AACnB,MAAM,iBAAiB,UAAU,YAAY,UAAU,MAAM;AA8B7D,SAAwB,aAAa,OAAO;AAExC,QAAM;AAAA,IACN;AAAA,IAAS;AAAA,IAAU;AAAA,IAAO;AAAA,IAAe,WAAW;AAAA,IAAO;AAAA,IAAc;AAAA,IAAc;AAAA,IAAU;AAAA,IAAY,UAAU;AAAA,IAAU;AAAA,IACjI;AAAA,IAAgB,MAAM,aAAa;AAAA,IACnC,GAAG;AAAA,EAAA,IACH,cAAc,OAAO,UAAU;AAC/B,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,QAAQ;AAC1C,QAAM,YAAY,aAAA;AAElB,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,IAAI;AACvD,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,IAAI;AACzD,QAAM,YAAY,uBAAA;AAClB,QAAM,gBAAgB,uBAAA;AACtB,QAAM,eAAe,MAAM;AACvB,qBAAiB,IAAI;AACrB,sBAAkB,IAAI;AAAA,EAC1B;AAGA,QAAM,cAAc,CAAC,WAAW;AAC5B,kBAAc;AAAA,MACV,OAAO,iBAAiB,SAAS,aAAa,EAAE,kBAAkB;AAAA,MAClE;AAAA,MACA,SAAS,CAAC,oBAAoB,SAAS,QAAQ,eAAe;AAAA,MAC9D,aAAa,MAAM,eAAe,MAAM;AAAA,MACxC,UAAU,CAAC,UAAU,WAAW,QAAQ,KAAK;AAAA,MAC7C,YAAY,MAAM,aAAa,MAAM;AAAA,IAAA,CACxC;AAAA,EACL;AAEA,QAAM,oBAAoB,iBAAiB,EAAC,KAAK,CAAC,EAAC,QAAA,MAAa,YAAY,QAAQ,MAAM,GAAE;AAE5F,QAAM,eAAe,CAAC,WAAW;AAC7B,iBAAA;AACA,QAAI,gBAAgB;AAChB,qBAAe,MAAM;AACrB;AAAA,IACJ;AACA,QAAI,cAAc;AACd,wBAAkB,KAAK,EAAC,QAAO;AAC/B;AAAA,IACJ;AAGA,YAAQ,MAAM,sGAAsG;AAAA,EACxH;AAEA,QAAM,cAAc,SAAS,EAAE,kBAAkB;AACjD,QAAM,WAAW,CAAC,UAAU,iBAAiB,MAAM,aAAa;AAEhE,QAAM,mBAAmB,CAAC,UAAU;AAChC,UAAM,EAAC,QAAQ,MAAA,IAAS,MAAM,cAAc,sBAAA;AAC5C,kBAAA;AACA,sBAAkB,EAAC,KAAK,QAAQ,MAAM,OAAM;AAAA,EAChD;AACA,QAAM,gBAAgB,QAAQ,iBAAiB,cAAc;AAC7D,QAAM,oBAAoB,kBAAkB,UAAU,eAAe,kBAAkB,QAAQ,MAAM,IAAI;AAEzG,SACI,qBAAA,UAAA,EACK,UAAA;AAAA,IAAA,cAAc,sBAAsB,QACjC,qBAAC,UAAA,EAAS,UAAoB,iBAAc,QAAO,SAAS,kBACxD,UAAA;AAAA,MAAA,oBAAC,cAAA,EAAa,UAAA,oBAAC,YAAA,CAAA,CAAW,GAAE;AAAA,MAC5B,oBAAC,gBAAc,UAAA,YAAA,CAAY;AAAA,IAAA,GAC/B;AAAA,IAEH,cAAc,sBAAsB;AAAA,wBAEhC,SAAA,EAAQ,OAAO,aAAa,eAAa,MACtC,8BAAC,QAAA,EACG,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QAAW,OAAM;AAAA,QAAU,cAAY;AAAA,QAAa,iBAAc;AAAA,QAAO,iBAAe;AAAA,QAC7E;AAAA,QAAoB,SAAS;AAAA,QACrC,8BAAC,YAAA,CAAA,CAAW;AAAA,MAAA;AAAA,IAAA,GAEpB,EAAA,CACJ;AAAA,IAEH,cAAc,sBAAsB,WAAW,YAAY;AAAA;AAAA;AAAA,MAGxD,oBAAC,WAAQ,OAAO,aAAa,aAAa,eAAa,MAEnD,8BAAC,QAAA,EACG,UAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UAAW,MAAK;AAAA,UAAQ,cAAY,aAAa;AAAA,UAAa,iBAAc;AAAA,UACjE;AAAA,UAAoB,SAAS;AAAA,UACrC,UAAA,oBAAC,YAAA,EAAW,UAAS,QAAA,CAAQ;AAAA,QAAA;AAAA,MAAA,GAErC,EAAA,CACJ;AAAA,QAEA;AAAA,MAAC;AAAA,MAAA;AAAA,QAAe,SAAQ;AAAA,QAAW,+BAAY,YAAA,EAAW;AAAA,QAAI,6BAAU,mBAAA,EAAkB;AAAA,QAClF,OAAO,EAAC,YAAY,EAAA;AAAA,QAAI;AAAA,QAAoB,iBAAc;AAAA,QAAO,SAAS;AAAA,QAC7E,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAGT;AAAA,MAAC;AAAA,MAAA;AAAA,QAAK,MAAM;AAAA,QAAe,SAAS;AAAA,QAC9B,iBAAiB,iBAAiB,mBAAmB;AAAA,QAAY,UAAU;AAAA,QAAe,gBAAgB,kBAAkB;AAAA,QAC5H,cAAc,EAAC,UAAU,UAAU,YAAY,QAAA;AAAA,QAAU,iBAAiB,EAAC,UAAU,OAAO,YAAY,QAAA;AAAA,QACzG,UAAA,QAAQ,IAAI,CAAC,WAAW;AACrB,gBAAM,WAAW,UAAU,MAAM;AACjC,gBAAM,OAAO,UAAU,QAAQ;AAC/B,sCACK,UAAA,EAAsB,SAAS,MAAM,aAAa,MAAM,GACrD,UAAA;AAAA,YAAA,oBAAC,cAAA,EAAa,UAAA,oBAAC,MAAA,EAAK,UAAS,SAAQ,GAAE;AAAA,YAEvC;AAAA,cAAC;AAAA,cAAA;AAAA,gBAAa,SAAS,EAAE,oBAAoB,MAAM,UAAU,EAAC,cAAc,UAAU,SAAS,OAAO,YAAA,EAAY,CAAE;AAAA,gBACtG,WAAW,EAAE,oBAAoB,MAAM,SAAS,EAAC,cAAc,UAAU,QAAQ,GAAA,CAAG;AAAA,gBACpF,WAAW,EAAC,WAAW,EAAC,SAAS,YAAS;AAAA,cAAC;AAAA,YAAA;AAAA,UAAG,EAAA,GALjD,MAMf;AAAA,QAER,CAAC;AAAA,MAAA;AAAA,IAAA;AAAA,IAEJ,gBACG;AAAA,MAAC;AAAA,MAAA;AAAA,QACI,GAAG,kBAAkB;AAAA,QACtB,OAAO,mBAAmB,SAAS;AAAA,QACnC,aAAa,mBAAmB;AAAA,QAChC,cAAc,mBAAmB,gBAAgB,EAAE,kBAAkB;AAAA,MAAA;AAAA,IAAA;AAAA,EACzE,GAER;AAER;"}
1
+ {"version":3,"file":"DownloadMenu.js","sources":["../../../src/ui/actions/DownloadMenu.jsx"],"sourcesContent":["// \"Descargar ▾\" con los formatos de un reporte: PDF para leer o archivar, Excel o CSV para trabajar.\n//\n// Un solo botón y no tres: en la barra de una pantalla tres botones de descarga compiten con la acción principal.\n// Se acomoda a donde quedó, como BarActionButton: en una cápsula de la barra (las `actions` de PageHeading con cápsulas)\n// es solo el ícono con su nombre en el tooltip, como las demás acciones; antes salía la píldora «Descargar ▾» dentro de\n// la cápsula y se veía una cápsula dentro de otra. En el «⋯» del teléfono es un renglón que abre los formatos.\n// Quien llama pasa QUÉ descargar por formato (download(format, transferOptions) → {blob, fileName}, la forma de\n// un cliente HTTP que descarga). La descarga va al panel de descargas (startDownload, downloads): el diálogo se cierra al\n// confirmar y el avance, el aviso de \"descargado\" y el error se ven allá, mientras la persona sigue trabajando.\n//\n// Regla de tablas: una descarga pasa por un diálogo de confirmación que dice qué se va a bajar (p. ej. que la base\n// completa de clientes tarda unos minutos). Con `confirmation` el formato elegido NO se descarga de inmediato: abre\n// ConfirmDialog (máquina confirmActionMachine) y solo al confirmar se pide el archivo, una sola vez aunque haya doble clic.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaDownloadMenu con defaultProps y\n// styleOverrides de sus partes: button.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Button from '@mui/material/Button';\nimport IconButton from '@mui/material/IconButton';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport Menu from '@mui/material/Menu';\nimport MenuItem from '@mui/material/MenuItem';\nimport Tooltip from '@mui/material/Tooltip';\nimport ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';\nimport FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';\n\nimport {BAR_ACTIONS_PLACEMENT, useBarActionsPlacement, useCloseBarActionsMenu} from '@/appShell/barActionsSlot.js';\nimport {startDownload} from '@/downloads/downloadQueue.js';\nimport {useFileTypes} from '@/downloads/fileTypes.js';\nimport ConfirmDialog from '@/feedback/ConfirmDialog.jsx';\nimport {useConfirmAction} from '@/feedback/useConfirmAction.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaDownloadMenu)\nconst THEME_NAME = 'CalcitaDownloadMenu';\nconst DownloadButton = piecePart(THEME_NAME, 'Button', Button);\n\n\n/**\n * @param {object} props\n * @param {string[]} props.formats los tipos de archivo, en orden: los de la casa (xlsx, csv, pdf) y los que el proyecto declare\n * en ToolkitProvider fileTypes (zip, xml…)\n * @param {(format: string, transferOptions: {signal: AbortSignal, onDownloadProgress: (progress: {loaded: number, total?: number|null}) => void}) => Promise<{blob: Blob, fileName: string}>} props.download\n * @param {string} [props.label] ya traducido; por defecto \"Descargar\"\n * @param {string} [props.downloadLabel] ya traducido; lo que se ve en el panel de descargas antes de saber el nombre\n * del archivo\n * @param {boolean} [props.disabled]\n * @param {(format: string) => {title: string, description: import('react').ReactNode, confirmLabel?: string}} [props.confirmation]\n * @param {(format: string) => void} [props.onDownloaded] p. ej. volver a pedir la tabla (si la descarga cambia algo en\n * el servidor)\n * @param {(format: string, error: unknown) => void} [props.onFailed] cuando la descarga no se pudo (el panel ya lo dice)\n * @param {(format: string) => void} [props.onCanceled] cuando la persona la canceló desde el panel\n * @param {'button'|'icon'} [props.variant] icon = solo el icono (columna de acciones de una tabla)\n * @param {string} [props.ariaLabel] ya traducido; obligatorio en la variante icon\n * @param {(format: string) => void} [props.onChooseFormat] quien llama se encarga de confirmar y descargar\n * @param {import('react').ElementType} [props.icon] ícono del botón; por defecto el de descarga. Distingue dos descargas en la\n * misma fila\n *\n * IMPORTANTE: hay que pasar `confirmation` u `onChooseFormat`. Sin ninguno de los dos el menú no descarga nada (regla de\n * tablas: toda descarga pasa por confirmación).\n *\n * OJO onChooseFormat: dentro de una celda del DataGrid el diálogo de confirmación NO puede vivir en la celda (el grid\n * virtualiza y vuelve a pintar sus celdas; el diálogo se perdía al elegir el formato). Ahí el menú solo avisa qué formato\n * se eligió y la pantalla abre SU confirmación (useConfirmAction) fuera de la tabla.\n */\nfunction DownloadMenuContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaDownloadMenu.defaultProps) y encima lo que llega aquí\n const {\n formats, download, label, downloadLabel, disabled = false, confirmation, onDownloaded, onFailed, onCanceled, variant = 'button', ariaLabel,\n onChooseFormat, icon: ButtonIcon = FileDownloadOutlinedIcon,\n ...unknownProps\n} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common');\n const fileTypes = useFileTypes();\n // de dónde sale el menú de formatos: del botón, o (desde el «⋯» del teléfono, que se cierra) de donde estaba el renglón\n const [anchorElement, setAnchorElement] = useState(null);\n const [anchorPosition, setAnchorPosition] = useState(null);\n const placement = useBarActionsPlacement();\n const closeMoreMenu = useCloseBarActionsMenu();\n const closeFormats = () => {\n setAnchorElement(null);\n setAnchorPosition(null);\n };\n\n // no se espera a que termine: la descarga sigue en el panel y el diálogo de confirmación se cierra de inmediato\n const runDownload = (format) => {\n startDownload({\n label: downloadLabel ?? label ?? ariaLabel ?? t('actions.download'),\n format,\n request: (transferOptions) => download(format, transferOptions),\n onCompleted: () => onDownloaded?.(format),\n onFailed: (error) => onFailed?.(format, error),\n onCanceled: () => onCanceled?.(format),\n });\n };\n\n const confirmedDownload = useConfirmAction({run: ({subject}) => runDownload(subject.format)});\n\n const chooseFormat = (format) => {\n closeFormats();\n if (onChooseFormat) {\n onChooseFormat(format);\n return;\n }\n if (confirmation) {\n confirmedDownload.open({format});\n return;\n }\n // Regla de tablas: nada se descarga con un solo clic. Sin confirmation ni onChooseFormat es un error de quien\n // llama, no un camino válido: lo decimos en la consola y no descargamos\n console.error('DownloadMenu: falta confirmation u onChooseFormat; toda descarga pasa por un diálogo de confirmación');\n };\n\n const buttonLabel = label ?? t('actions.download');\n const openMenu = (event) => setAnchorElement(event.currentTarget);\n // desde el «⋯»: se cierra ese menú y los formatos salen donde estaba el renglón\n const openFromMoreMenu = (event) => {\n const {bottom, right} = event.currentTarget.getBoundingClientRect();\n closeMoreMenu();\n setAnchorPosition({top: bottom, left: right});\n };\n const isFormatsOpen = Boolean(anchorElement || anchorPosition);\n const confirmationTexts = confirmedDownload.subject ? confirmation?.(confirmedDownload.subject.format) : null;\n\n return (\n <>\n {placement === BAR_ACTIONS_PLACEMENT.menu && (\n <MenuItem disabled={disabled} aria-haspopup=\"menu\" onClick={openFromMoreMenu}>\n <ListItemIcon><ButtonIcon /></ListItemIcon>\n <ListItemText>{buttonLabel}</ListItemText>\n </MenuItem>\n )}\n {placement === BAR_ACTIONS_PLACEMENT.capsule && (\n // en la cápsula, del tamaño y color de las demás acciones (BarActionButton)\n <Tooltip title={buttonLabel} describeChild>\n <span>\n <IconButton color=\"primary\" aria-label={buttonLabel} aria-haspopup=\"menu\" aria-expanded={isFormatsOpen}\n disabled={disabled} onClick={openMenu}>\n <ButtonIcon />\n </IconButton>\n </span>\n </Tooltip>\n )}\n {placement === BAR_ACTIONS_PLACEMENT.inline && (variant === 'icon' ? (\n // describeChild: el nombre accesible ya lo trae el botón; sin esto el Tooltip le pone el mismo aria-label al\n // span y un lector de pantalla (o una prueba) encuentra dos \"botones\" con el mismo nombre\n <Tooltip title={ariaLabel ?? buttonLabel} describeChild>\n {/* el span deja que el tooltip funcione con el botón inhabilitado */}\n <span>\n <IconButton size=\"small\" aria-label={ariaLabel ?? buttonLabel} aria-haspopup=\"menu\"\n disabled={disabled} onClick={openMenu}>\n <ButtonIcon fontSize=\"small\" />\n </IconButton>\n </span>\n </Tooltip>\n ) : (\n <DownloadButton variant=\"outlined\" startIcon={<ButtonIcon />} endIcon={<ArrowDropDownIcon />}\n ownSx={{flexShrink: 0}} disabled={disabled} aria-haspopup=\"menu\" onClick={openMenu}>\n {buttonLabel}\n </DownloadButton>\n ))}\n <Menu open={isFormatsOpen} onClose={closeFormats}\n anchorReference={anchorPosition ? 'anchorPosition' : 'anchorEl'} anchorEl={anchorElement} anchorPosition={anchorPosition ?? undefined}\n anchorOrigin={{vertical: 'bottom', horizontal: 'right'}} transformOrigin={{vertical: 'top', horizontal: 'right'}}>\n {formats.map((format) => {\n const fileType = fileTypes[format];\n const Icon = fileType?.Icon ?? FileDownloadOutlinedIcon;\n return (\n <MenuItem key={format} onClick={() => chooseFormat(format)}>\n <ListItemIcon><Icon fontSize=\"small\" /></ListItemIcon>\n {/* los de la casa con sus textos; los del proyecto con su label y hint (o esas llaves en sus texts) */}\n <ListItemText primary={t(`download.formats.${format}.label`, {defaultValue: fileType?.label ?? format.toUpperCase()})}\n secondary={t(`download.formats.${format}.hint`, {defaultValue: fileType?.hint ?? ''})}\n slotProps={{secondary: {variant: 'caption'}}} />\n </MenuItem>\n );\n })}\n </Menu>\n {confirmation && (\n <ConfirmDialog\n {...confirmedDownload.dialogProps}\n title={confirmationTexts?.title ?? ''}\n description={confirmationTexts?.description}\n confirmLabel={confirmationTexts?.confirmLabel ?? t('actions.download')}\n />\n )}\n </>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst DownloadMenu = withPieceSlots(DownloadMenuContent, THEME_NAME);\nexport default DownloadMenu;\n"],"names":[],"mappings":"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"}
@@ -12,10 +12,14 @@ import VisibilityOffOutlinedIcon from "@mui/icons-material/VisibilityOffOutlined
12
12
  import VisibilityOutlinedIcon from "@mui/icons-material/VisibilityOutlined";
13
13
  import FieldFrame from "../../inputs/FieldFrame.js";
14
14
  import { warnUnknownProps } from "../../toolkit/unknownProps.js";
15
+ import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
16
+ const THEME_NAME = "CalcitaSecretField";
17
+ const SecretFieldField = piecePart(THEME_NAME, "Field", TextField);
15
18
  const COPIED_FEEDBACK_MILLISECONDS = 2e3;
16
19
  const MONOSPACE_FONT = "ui-monospace, SFMono-Regular, Menlo, monospace";
17
- function SecretField({ value, label, helperText = " ", onCopied, onRevealChange, texts, ...unknownProps }) {
18
- warnUnknownProps("SecretField", unknownProps);
20
+ function SecretFieldContent(props) {
21
+ const { value, label, helperText = " ", onCopied, onRevealChange, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
22
+ warnUnknownProps(THEME_NAME, unknownProps);
19
23
  const { t } = useToolkitTranslation("common", texts);
20
24
  const generatedId = useId();
21
25
  const inputId = `secret-${generatedId}`;
@@ -37,7 +41,7 @@ function SecretField({ value, label, helperText = " ", onCopied, onRevealChange,
37
41
  }
38
42
  };
39
43
  return /* @__PURE__ */ jsx(FieldFrame, { inputId, label, children: /* @__PURE__ */ jsx(
40
- TextField,
44
+ SecretFieldField,
41
45
  {
42
46
  id: inputId,
43
47
  fullWidth: true,
@@ -57,6 +61,7 @@ function SecretField({ value, label, helperText = " ", onCopied, onRevealChange,
57
61
  }
58
62
  ) });
59
63
  }
64
+ const SecretField = withPieceSlots(SecretFieldContent, THEME_NAME);
60
65
  export {
61
66
  SecretField as default
62
67
  };
@@ -1 +1 @@
1
- {"version":3,"file":"SecretField.js","sources":["../../../src/ui/actions/SecretField.jsx"],"sourcesContent":["// Un secreto que se enseña UNA vez (una clave de acceso, un token recién creado): tapado por omisión, con el ojo para verlo\n// y el botón para copiarlo.\n//\n// Tapado porque la pantalla se comparte, se graba o la ve quien pasa por atrás; el botón de copiar evita seleccionarlo a\n// mano y dejar un carácter afuera. Si el navegador no deja copiar, se destapa para copiarlo a mano.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useId, useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport IconButton from '@mui/material/IconButton';\nimport InputAdornment from '@mui/material/InputAdornment';\nimport TextField from '@mui/material/TextField';\nimport Tooltip from '@mui/material/Tooltip';\nimport CheckIcon from '@mui/icons-material/CheckRounded';\nimport CopyIcon from '@mui/icons-material/ContentCopyOutlined';\nimport VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';\nimport VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';\n\nimport FieldFrame from '@/inputs/FieldFrame.jsx';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\nconst COPIED_FEEDBACK_MILLISECONDS = 2000;\nconst MONOSPACE_FONT = 'ui-monospace, SFMono-Regular, Menlo, monospace';\n\n/**\n * @param {object} props\n * @param {string} props.value el secreto\n * @param {string} props.label ya traducido\n * @param {string} [props.helperText] p. ej. «Guárdela: no se vuelve a enseñar»\n * @param {() => void} [props.onCopied]\n * @param {(isRevealed: boolean) => void} [props.onRevealChange] se destapó o se tapó (para registrar quién vio el secreto)\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nexport default function SecretField({value, label, helperText = ' ', onCopied, onRevealChange, texts, ...unknownProps}) {\n warnUnknownProps('SecretField', unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const generatedId = useId();\n const inputId = `secret-${generatedId}`;\n const [isRevealed, setIsRevealedState] = useState(false);\n const setIsRevealed = (nextIsRevealed) => {\n setIsRevealedState(nextIsRevealed);\n onRevealChange?.(nextIsRevealed);\n };\n const [isCopied, setIsCopied] = useState(false);\n const revealLabel = isRevealed ? t('form.hidePassword') : t('form.showPassword');\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(value);\n setIsCopied(true);\n onCopied?.();\n setTimeout(() => setIsCopied(false), COPIED_FEEDBACK_MILLISECONDS);\n } catch {\n // sin permiso de portapapeles: se destapa para copiarlo a mano\n setIsRevealed(true);\n }\n };\n\n return (\n <FieldFrame inputId={inputId} label={label}>\n <TextField\n id={inputId}\n fullWidth\n size=\"small\"\n value={value}\n helperText={helperText}\n type={isRevealed ? 'text' : 'password'}\n slotProps={{\n htmlInput: {readOnly: true, spellCheck: false, autoComplete: 'off', style: {fontFamily: MONOSPACE_FONT}},\n input: {\n endAdornment: (\n <InputAdornment position=\"end\">\n <Tooltip title={revealLabel}>\n <IconButton size=\"small\" aria-label={revealLabel} onClick={() => setIsRevealed(!isRevealed)}>\n {isRevealed ? <VisibilityOffOutlinedIcon fontSize=\"small\" /> : <VisibilityOutlinedIcon fontSize=\"small\" />}\n </IconButton>\n </Tooltip>\n <Tooltip title={isCopied ? t('form.copied') : t('form.copy')}>\n <IconButton size=\"small\" aria-label={t('form.copy')} onClick={copy} color={isCopied ? 'success' : 'default'}>\n {isCopied ? <CheckIcon fontSize=\"small\" /> : <CopyIcon fontSize=\"small\" />}\n </IconButton>\n </Tooltip>\n </InputAdornment>\n ),\n },\n }}\n />\n </FieldFrame>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;AAqBA,MAAM,+BAA+B;AACrC,MAAM,iBAAiB;AAWvB,SAAwB,YAAY,EAAC,OAAO,OAAO,aAAa,KAAK,UAAU,gBAAgB,OAAO,GAAG,gBAAe;AACpH,mBAAiB,eAAe,YAAY;AAC5C,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,QAAM,cAAc,MAAA;AACpB,QAAM,UAAU,UAAU,WAAW;AACrC,QAAM,CAAC,YAAY,kBAAkB,IAAI,SAAS,KAAK;AACvD,QAAM,gBAAgB,CAAC,mBAAmB;AACtC,uBAAmB,cAAc;AACjC,qBAAiB,cAAc;AAAA,EACnC;AACA,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,cAAc,aAAa,EAAE,mBAAmB,IAAI,EAAE,mBAAmB;AAE/E,QAAM,OAAO,YAAY;AACrB,QAAI;AACA,YAAM,UAAU,UAAU,UAAU,KAAK;AACzC,kBAAY,IAAI;AAChB,iBAAA;AACA,iBAAW,MAAM,YAAY,KAAK,GAAG,4BAA4B;AAAA,IACrE,QAAQ;AAEJ,oBAAc,IAAI;AAAA,IACtB;AAAA,EACJ;AAEA,SACI,oBAAC,YAAA,EAAW,SAAkB,OAC1B,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,IAAI;AAAA,MACJ,WAAS;AAAA,MACT,MAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,MAAM,aAAa,SAAS;AAAA,MAC5B,WAAW;AAAA,QACP,WAAW,EAAC,UAAU,MAAM,YAAY,OAAO,cAAc,OAAO,OAAO,EAAC,YAAY,eAAA,EAAc;AAAA,QACtG,OAAO;AAAA,UACH,cACI,qBAAC,gBAAA,EAAe,UAAS,OACrB,UAAA;AAAA,YAAA,oBAAC,SAAA,EAAQ,OAAO,aACZ,UAAA,oBAAC,YAAA,EAAW,MAAK,SAAQ,cAAY,aAAa,SAAS,MAAM,cAAc,CAAC,UAAU,GACrF,UAAA,aAAa,oBAAC,2BAAA,EAA0B,UAAS,QAAA,CAAQ,IAAK,oBAAC,wBAAA,EAAuB,UAAS,QAAA,CAAQ,EAAA,CAC5G,GACJ;AAAA,YACA,oBAAC,SAAA,EAAQ,OAAO,WAAW,EAAE,aAAa,IAAI,EAAE,WAAW,GACvD,UAAA,oBAAC,YAAA,EAAW,MAAK,SAAQ,cAAY,EAAE,WAAW,GAAG,SAAS,MAAM,OAAO,WAAW,YAAY,WAC7F,qBAAW,oBAAC,WAAA,EAAU,UAAS,QAAA,CAAQ,IAAK,oBAAC,UAAA,EAAS,UAAS,QAAA,CAAQ,GAC5E,EAAA,CACJ;AAAA,UAAA,EAAA,CACJ;AAAA,QAAA;AAAA,MAER;AAAA,IACJ;AAAA,EAAA,GAER;AAER;"}
1
+ {"version":3,"file":"SecretField.js","sources":["../../../src/ui/actions/SecretField.jsx"],"sourcesContent":["// Un secreto que se enseña UNA vez (una clave de acceso, un token recién creado): tapado por omisión, con el ojo para verlo\n// y el botón para copiarlo.\n//\n// Tapado porque la pantalla se comparte, se graba o la ve quien pasa por atrás; el botón de copiar evita seleccionarlo a\n// mano y dejar un carácter afuera. Si el navegador no deja copiar, se destapa para copiarlo a mano.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaSecretField con defaultProps, styleOverrides de\n// sus partes (field) y slots/slotProps para cambiarlas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useId, useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport IconButton from '@mui/material/IconButton';\nimport InputAdornment from '@mui/material/InputAdornment';\nimport TextField from '@mui/material/TextField';\nimport Tooltip from '@mui/material/Tooltip';\nimport CheckIcon from '@mui/icons-material/CheckRounded';\nimport CopyIcon from '@mui/icons-material/ContentCopyOutlined';\nimport VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';\nimport VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';\n\nimport FieldFrame from '@/inputs/FieldFrame.jsx';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaSecretField)\nconst THEME_NAME = 'CalcitaSecretField';\nconst SecretFieldField = piecePart(THEME_NAME, 'Field', TextField);\n\nconst COPIED_FEEDBACK_MILLISECONDS = 2000;\nconst MONOSPACE_FONT = 'ui-monospace, SFMono-Regular, Menlo, monospace';\n\n/**\n * @param {object} props\n * @param {string} props.value el secreto\n * @param {string} props.label ya traducido\n * @param {string} [props.helperText] p. ej. «Guárdela: no se vuelve a enseñar»\n * @param {() => void} [props.onCopied]\n * @param {(isRevealed: boolean) => void} [props.onRevealChange] se destapó o se tapó (para registrar quién vio el secreto)\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction SecretFieldContent(props) {\n const {value, label, helperText = ' ', onCopied, onRevealChange, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const generatedId = useId();\n const inputId = `secret-${generatedId}`;\n const [isRevealed, setIsRevealedState] = useState(false);\n const setIsRevealed = (nextIsRevealed) => {\n setIsRevealedState(nextIsRevealed);\n onRevealChange?.(nextIsRevealed);\n };\n const [isCopied, setIsCopied] = useState(false);\n const revealLabel = isRevealed ? t('form.hidePassword') : t('form.showPassword');\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(value);\n setIsCopied(true);\n onCopied?.();\n setTimeout(() => setIsCopied(false), COPIED_FEEDBACK_MILLISECONDS);\n } catch {\n // sin permiso de portapapeles: se destapa para copiarlo a mano\n setIsRevealed(true);\n }\n };\n\n return (\n <FieldFrame inputId={inputId} label={label}>\n <SecretFieldField\n id={inputId}\n fullWidth\n size=\"small\"\n value={value}\n helperText={helperText}\n type={isRevealed ? 'text' : 'password'}\n slotProps={{\n htmlInput: {readOnly: true, spellCheck: false, autoComplete: 'off', style: {fontFamily: MONOSPACE_FONT}},\n input: {\n endAdornment: (\n <InputAdornment position=\"end\">\n <Tooltip title={revealLabel}>\n <IconButton size=\"small\" aria-label={revealLabel} onClick={() => setIsRevealed(!isRevealed)}>\n {isRevealed ? <VisibilityOffOutlinedIcon fontSize=\"small\" /> : <VisibilityOutlinedIcon fontSize=\"small\" />}\n </IconButton>\n </Tooltip>\n <Tooltip title={isCopied ? t('form.copied') : t('form.copy')}>\n <IconButton size=\"small\" aria-label={t('form.copy')} onClick={copy} color={isCopied ? 'success' : 'default'}>\n {isCopied ? <CheckIcon fontSize=\"small\" /> : <CopyIcon fontSize=\"small\" />}\n </IconButton>\n </Tooltip>\n </InputAdornment>\n ),\n },\n }}\n />\n </FieldFrame>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst SecretField = withPieceSlots(SecretFieldContent, THEME_NAME);\nexport default SecretField;\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AA0BA,MAAM,aAAa;AACnB,MAAM,mBAAmB,UAAU,YAAY,SAAS,SAAS;AAEjE,MAAM,+BAA+B;AACrC,MAAM,iBAAiB;AAWvB,SAAS,mBAAmB,OAAO;AAC/B,QAAM,EAAC,OAAO,OAAO,aAAa,KAAK,UAAU,gBAAgB,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AAC1H,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,QAAM,cAAc,MAAA;AACpB,QAAM,UAAU,UAAU,WAAW;AACrC,QAAM,CAAC,YAAY,kBAAkB,IAAI,SAAS,KAAK;AACvD,QAAM,gBAAgB,CAAC,mBAAmB;AACtC,uBAAmB,cAAc;AACjC,qBAAiB,cAAc;AAAA,EACnC;AACA,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,cAAc,aAAa,EAAE,mBAAmB,IAAI,EAAE,mBAAmB;AAE/E,QAAM,OAAO,YAAY;AACrB,QAAI;AACA,YAAM,UAAU,UAAU,UAAU,KAAK;AACzC,kBAAY,IAAI;AAChB,iBAAA;AACA,iBAAW,MAAM,YAAY,KAAK,GAAG,4BAA4B;AAAA,IACrE,QAAQ;AAEJ,oBAAc,IAAI;AAAA,IACtB;AAAA,EACJ;AAEA,SACI,oBAAC,YAAA,EAAW,SAAkB,OAC1B,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,IAAI;AAAA,MACJ,WAAS;AAAA,MACT,MAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,MAAM,aAAa,SAAS;AAAA,MAC5B,WAAW;AAAA,QACP,WAAW,EAAC,UAAU,MAAM,YAAY,OAAO,cAAc,OAAO,OAAO,EAAC,YAAY,eAAA,EAAc;AAAA,QACtG,OAAO;AAAA,UACH,cACI,qBAAC,gBAAA,EAAe,UAAS,OACrB,UAAA;AAAA,YAAA,oBAAC,SAAA,EAAQ,OAAO,aACZ,UAAA,oBAAC,YAAA,EAAW,MAAK,SAAQ,cAAY,aAAa,SAAS,MAAM,cAAc,CAAC,UAAU,GACrF,UAAA,aAAa,oBAAC,2BAAA,EAA0B,UAAS,QAAA,CAAQ,IAAK,oBAAC,wBAAA,EAAuB,UAAS,QAAA,CAAQ,EAAA,CAC5G,GACJ;AAAA,YACA,oBAAC,SAAA,EAAQ,OAAO,WAAW,EAAE,aAAa,IAAI,EAAE,WAAW,GACvD,UAAA,oBAAC,YAAA,EAAW,MAAK,SAAQ,cAAY,EAAE,WAAW,GAAG,SAAS,MAAM,OAAO,WAAW,YAAY,WAC7F,qBAAW,oBAAC,WAAA,EAAU,UAAS,QAAA,CAAQ,IAAK,oBAAC,UAAA,EAAS,UAAS,QAAA,CAAQ,GAC5E,EAAA,CACJ;AAAA,UAAA,EAAA,CACJ;AAAA,QAAA;AAAA,MAER;AAAA,IACJ;AAAA,EAAA,GAER;AAER;AAGA,MAAM,cAAc,eAAe,oBAAoB,UAAU;"}
@@ -18,7 +18,7 @@ import { usesMobileTabBar } from "../../appShell/tabBarRule.js";
18
18
  import { minimalFloatingStylesOf } from "../../theme/components/minimalComponents.js";
19
19
  import { isGlassTheme, glassStylesOf } from "../../theme/glassSurface.js";
20
20
  import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
21
- import { piecePart, usePieceProps } from "../../theme/themePieces.js";
21
+ import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
22
22
  import { warnUnknownProps } from "../../toolkit/unknownProps.js";
23
23
  const THEME_NAME = "CalcitaSelectionActions";
24
24
  const SelectionBar = piecePart(THEME_NAME, "Bar", Stack);
@@ -49,7 +49,7 @@ function bottomCapsuleSxOf(theme) {
49
49
  ...aboveMobileTabBarOf(FLOATING_GAP_PIXELS)
50
50
  };
51
51
  }
52
- function SelectionActions(props) {
52
+ function SelectionActionsContent(props) {
53
53
  const { countText, actions = [], onClear, phoneLayout = SELECTION_PHONE_LAYOUT.top, texts, sx, ...unknownProps } = usePieceProps(props, THEME_NAME);
54
54
  warnUnknownProps(THEME_NAME, unknownProps);
55
55
  const theme = useTheme();
@@ -144,6 +144,7 @@ function SelectionActions(props) {
144
144
  ] })
145
145
  ] });
146
146
  }
147
+ const SelectionActions = withPieceSlots(SelectionActionsContent, THEME_NAME);
147
148
  export {
148
149
  SELECTION_PHONE_LAYOUT,
149
150
  SelectionActions as default,
@@ -1 +1 @@
1
- {"version":3,"file":"SelectionActions.js","sources":["../../../src/ui/actions/SelectionActions.jsx"],"sourcesContent":["// Las acciones de lo elegido en una lista («5 pedidos elegidos · Cancelar · Borrar · Quitar selección»), en el lugar que le\n// toca según el equipo. Una sola pieza para que cada lista con casillas (la tabla de servidor, una propia) no repita dónde\n// va cada cosa:\n// - escritorio, y el teléfono sin barra de pestañas abajo (el tema de MUI sin vidrio): un renglón donde se pone la pieza,\n// cada acción como botón con su texto;\n// - teléfono con vidrio, o minimalista con cápsulas (usesMobileTabBar), según phoneLayout (SELECTION_PHONE_LAYOUT):\n// top (por omisión): arriba, en la barra flotante, «5 elegidos ✕» y las acciones como íconos en su propia cápsula,\n// como Apple separa los grupos; las que no caben, al «⋯» (BarActions);\n// en los dos, mientras hay algo elegido, el renglón de arriba queda solo para lo elegido (BarActions exclusive): las\n// demás cápsulas de la pantalla y la lupa se esconden, como el modo de edición del iPhone;\n// split: como iOS en modo de edición (Fotos, Mail, Archivos): arriba «5 elegidos ✕» y abajo, encima de las pestañas,\n// una cápsula fija con las acciones, donde llega el pulgar. Mientras se ve, pide su alto al marco\n// (FLOATING_BOTTOM_SPACE_CSS_VARIABLE) para no tapar el final de la página.\n// Lo pidió el autor: en el teléfono, configurable, y por omisión todo arriba.\n//\n// Con vidrio, la cápsula de arriba deja sus botones del color del texto (BarCapsule: la regla de la barra); abajo, una acción\n// destructiva (color: 'error') conserva su rojo, como pide la guía de Apple para lo que borra.\n//\n// Cada acción puede regresar una promesa: mientras corre, las demás se apagan (nadie cancela dos veces lo mismo).\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaSelectionActions con defaultProps y\n// styleOverrides de sus partes: bar, count, clear, phoneCount, phoneActions.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport GlobalStyles from '@mui/material/GlobalStyles';\nimport IconButton from '@mui/material/IconButton';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport {useTheme} from '@mui/material/styles';\nimport CloseRoundedIcon from '@mui/icons-material/CloseRounded';\n\nimport BarActionButton from '@/appShell/BarActionButton.jsx';\nimport BarActions from '@/appShell/BarActions.jsx';\nimport BarCapsule from '@/appShell/BarCapsule.jsx';\nimport {\n FLOATING_BOTTOM_SPACE_CSS_VARIABLE, GLASS_PANEL_GAP_PIXELS, PHONE_MEDIA_QUERY, aboveMobileTabBarOf,\n} from '@/appShell/shellSizes.js';\nimport {usesMobileTabBar} from '@/appShell/tabBarRule.js';\nimport {minimalFloatingStylesOf} from '@/theme/components/minimalComponents.js';\nimport {glassStylesOf, isGlassTheme} from '@/theme/glassSurface.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaSelectionActions)\nconst THEME_NAME = 'CalcitaSelectionActions';\nconst SelectionBar = piecePart(THEME_NAME, 'Bar', Stack);\nconst SelectionCount = piecePart(THEME_NAME, 'Count', Typography);\nconst SelectionClear = piecePart(THEME_NAME, 'Clear', Button);\nconst SelectionPhoneCount = piecePart(THEME_NAME, 'PhoneCount', Typography);\nconst SelectionPhoneActions = piecePart(THEME_NAME, 'PhoneActions', Box);\n\n/** Dónde van las acciones de lo elegido en el teléfono con barra de pestañas abajo: todo arriba o divididas (iOS). */\nexport const SELECTION_PHONE_LAYOUT = Object.freeze({top: 'top', split: 'split'});\n\n// lo que se separa la cápsula de abajo de la barra de pestañas (px), lo mismo que el aviso de versión nueva\nconst FLOATING_GAP_PIXELS = 8;\n// lo que pide al marco mientras flota abajo: su alto (48) y su separación, con aire\nconst FLOATING_BOTTOM_SPACE_PIXELS = 64;\n// lo que solo se ve en el teléfono\nconst PHONE_ONLY_SX = {display: 'none', [PHONE_MEDIA_QUERY]: {display: 'flex'}};\n\n/**\n * ¿En el teléfono lo elegido sale de su renglón (arriba o abajo)? La misma regla que la barra de pestañas de abajo: con ella,\n * el renglón de la pantalla se queda con lo suyo (el conteo de la tabla) y las acciones flotan.\n *\n * @param {object} theme\n * @returns {boolean}\n */\nexport function selectionFloatsOnPhone(theme) {\n return usesMobileTabBar(theme);\n}\n\n/**\n * La cápsula fija abajo, centrada en la ventana, encima de la barra de pestañas.\n *\n * @param {object} theme\n * @returns {object}\n */\nfunction bottomCapsuleSxOf(theme) {\n return {\n ...(isGlassTheme(theme) ? glassStylesOf(theme) : minimalFloatingStylesOf(theme)),\n position: 'fixed',\n left: '50%',\n transform: 'translateX(-50%)',\n zIndex: theme.zIndex.appBar,\n alignItems: 'center',\n gap: 0.5,\n width: 'max-content',\n maxWidth: `calc(100% - ${GLASS_PANEL_GAP_PIXELS * 2}px)`,\n borderRadius: '999px',\n p: 0.5,\n ...aboveMobileTabBarOf(FLOATING_GAP_PIXELS),\n };\n}\n\n/**\n * @param {object} props\n * @param {string} props.countText «5 pedidos elegidos», ya traducido. La pieza se pinta mientras la pantalla la ponga: con\n * nada elegido, no la ponga\n * @param {Array<{key: string, label: string, icon?: import('react').ReactNode, color?: 'inherit'|'primary'|'secondary'|'error'|'info'|'success'|'warning', disabled?: boolean, onClick: () => unknown}>} [props.actions]\n * label ya traducido; en el teléfono se ve el ícono (sin él, el texto). onClick puede regresar una promesa\n * @param {() => void} props.onClear quitar la selección\n * @param {'top'|'split'} [props.phoneLayout] SELECTION_PHONE_LAYOUT; por omisión todo arriba\n * @param {object} [props.texts] los textos que cambian, con la forma de `common`: {selection: {clear, actionsLabel, summaryLabel}}\n * @param {object} [props.sx] estilos del renglón\n */\nexport default function SelectionActions(props) {\n // lo que el proyecto puso en su tema (components.CalcitaSelectionActions.defaultProps) y encima lo que llega aquí\n const {countText, actions = [], onClear, phoneLayout = SELECTION_PHONE_LAYOUT.top, texts, sx, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const theme = useTheme();\n const {t} = useToolkitTranslation('common', texts);\n const [runningActionKey, setRunningActionKey] = useState(null);\n const floatsOnPhone = selectionFloatsOnPhone(theme);\n const extraSx = Array.isArray(sx) ? sx : [sx];\n\n const runAction = async (action) => {\n setRunningActionKey(action.key);\n try {\n await action.onClick();\n } finally {\n setRunningActionKey(null);\n }\n };\n const isDisabledOf = (action) => runningActionKey !== null || Boolean(action.disabled);\n\n const clearButton = (\n <Tooltip title={t('selection.clear')}>\n <IconButton aria-label={t('selection.clear')} onClick={onClear}>\n <CloseRoundedIcon />\n </IconButton>\n </Tooltip>\n );\n\n // el renglón: escritorio siempre; en el teléfono, solo si ahí no flota\n const row = (\n <SelectionBar role=\"toolbar\" aria-label={t('selection.actionsLabel')} direction=\"row\" spacing={1} useFlexGap\n ownSx={[{flexGrow: 1, alignItems: 'center', flexWrap: 'wrap', minHeight: 32},\n floatsOnPhone && {[PHONE_MEDIA_QUERY]: {display: 'none'}}, ...extraSx]}>\n <SelectionCount variant=\"body2\" ownSx={{fontWeight: 600, mr: 1}}>{countText}</SelectionCount>\n {actions.map((action) => (\n <Button key={action.key} size=\"small\" color={action.color ?? 'primary'} startIcon={action.icon}\n disabled={isDisabledOf(action)} onClick={() => runAction(action)}>\n {action.label}\n </Button>\n ))}\n <SelectionClear size=\"small\" color=\"inherit\" startIcon={<CloseRoundedIcon />} onClick={onClear} ownSx={{ml: 'auto'}}>\n {t('selection.clear')}\n </SelectionClear>\n </SelectionBar>\n );\n\n if (!floatsOnPhone) {\n return row;\n }\n\n const showsBottomCapsule = phoneLayout === SELECTION_PHONE_LAYOUT.split && actions.length > 0;\n\n return (\n <>\n {row}\n {/* arriba: con las demás cápsulas flotantes de la pantalla (BarActions), antes que ellas. Sin label en BarActions:\n el nombre ya lo lleva la cápsula (dos grupos anidados con el mismo nombre se leen dos veces) */}\n <BarActions bare exclusive order={-2} sx={PHONE_ONLY_SX} inlineSx={PHONE_ONLY_SX}>\n <BarCapsule aria-label={t('selection.summaryLabel')} sx={{pl: 2}}>\n <SelectionPhoneCount variant=\"body2\" role=\"status\" aria-live=\"polite\" ownSx={{fontWeight: 600, whiteSpace: 'nowrap', mr: 0.5}}>\n {countText}\n </SelectionPhoneCount>\n {clearButton}\n </BarCapsule>\n </BarActions>\n {phoneLayout === SELECTION_PHONE_LAYOUT.top && actions.length > 0 && (\n <BarActions label={t('selection.actionsLabel')} exclusive order={-1} sx={PHONE_ONLY_SX} inlineSx={PHONE_ONLY_SX}>\n {actions.map((action) => (\n <BarActionButton key={action.key} label={action.label} icon={action.icon} color={action.color}\n disabled={isDisabledOf(action)} onClick={() => runAction(action)} />\n ))}\n </BarActions>\n )}\n {showsBottomCapsule && (\n <>\n <GlobalStyles styles={{':root': {[FLOATING_BOTTOM_SPACE_CSS_VARIABLE]: `${FLOATING_BOTTOM_SPACE_PIXELS}px`}}} />\n <SelectionPhoneActions role=\"toolbar\" aria-label={t('selection.actionsLabel')} ownSx={[bottomCapsuleSxOf, PHONE_ONLY_SX]}>\n {actions.map((action) => (action.icon ? (\n <Tooltip key={action.key} title={action.label}>\n {/* el span deja ver el tooltip aunque el botón esté apagado */}\n <span>\n <IconButton aria-label={action.label} color={action.color ?? 'default'} disabled={isDisabledOf(action)}\n onClick={() => runAction(action)}>\n {action.icon}\n </IconButton>\n </span>\n </Tooltip>\n ) : (\n <Button key={action.key} size=\"small\" color={action.color ?? 'primary'} disabled={isDisabledOf(action)}\n onClick={() => runAction(action)}>\n {action.label}\n </Button>\n )))}\n </SelectionPhoneActions>\n </>\n )}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SelectionActions.js","sources":["../../../src/ui/actions/SelectionActions.jsx"],"sourcesContent":["// Las acciones de lo elegido en una lista («5 pedidos elegidos · Cancelar · Borrar · Quitar selección»), en el lugar que le\n// toca según el equipo. Una sola pieza para que cada lista con casillas (la tabla de servidor, una propia) no repita dónde\n// va cada cosa:\n// - escritorio, y el teléfono sin barra de pestañas abajo (el tema de MUI sin vidrio): un renglón donde se pone la pieza,\n// cada acción como botón con su texto;\n// - teléfono con vidrio, o minimalista con cápsulas (usesMobileTabBar), según phoneLayout (SELECTION_PHONE_LAYOUT):\n// top (por omisión): arriba, en la barra flotante, «5 elegidos ✕» y las acciones como íconos en su propia cápsula,\n// como Apple separa los grupos; las que no caben, al «⋯» (BarActions);\n// en los dos, mientras hay algo elegido, el renglón de arriba queda solo para lo elegido (BarActions exclusive): las\n// demás cápsulas de la pantalla y la lupa se esconden, como el modo de edición del iPhone;\n// split: como iOS en modo de edición (Fotos, Mail, Archivos): arriba «5 elegidos ✕» y abajo, encima de las pestañas,\n// una cápsula fija con las acciones, donde llega el pulgar. Mientras se ve, pide su alto al marco\n// (FLOATING_BOTTOM_SPACE_CSS_VARIABLE) para no tapar el final de la página.\n// Lo pidió el autor: en el teléfono, configurable, y por omisión todo arriba.\n//\n// Con vidrio, la cápsula de arriba deja sus botones del color del texto (BarCapsule: la regla de la barra); abajo, una acción\n// destructiva (color: 'error') conserva su rojo, como pide la guía de Apple para lo que borra.\n//\n// Cada acción puede regresar una promesa: mientras corre, las demás se apagan (nadie cancela dos veces lo mismo).\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaSelectionActions con defaultProps y\n// styleOverrides de sus partes: bar, count, clear, phoneCount, phoneActions.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport GlobalStyles from '@mui/material/GlobalStyles';\nimport IconButton from '@mui/material/IconButton';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport {useTheme} from '@mui/material/styles';\nimport CloseRoundedIcon from '@mui/icons-material/CloseRounded';\n\nimport BarActionButton from '@/appShell/BarActionButton.jsx';\nimport BarActions from '@/appShell/BarActions.jsx';\nimport BarCapsule from '@/appShell/BarCapsule.jsx';\nimport {\n FLOATING_BOTTOM_SPACE_CSS_VARIABLE, GLASS_PANEL_GAP_PIXELS, PHONE_MEDIA_QUERY, aboveMobileTabBarOf,\n} from '@/appShell/shellSizes.js';\nimport {usesMobileTabBar} from '@/appShell/tabBarRule.js';\nimport {minimalFloatingStylesOf} from '@/theme/components/minimalComponents.js';\nimport {glassStylesOf, isGlassTheme} from '@/theme/glassSurface.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaSelectionActions)\nconst THEME_NAME = 'CalcitaSelectionActions';\nconst SelectionBar = piecePart(THEME_NAME, 'Bar', Stack);\nconst SelectionCount = piecePart(THEME_NAME, 'Count', Typography);\nconst SelectionClear = piecePart(THEME_NAME, 'Clear', Button);\nconst SelectionPhoneCount = piecePart(THEME_NAME, 'PhoneCount', Typography);\nconst SelectionPhoneActions = piecePart(THEME_NAME, 'PhoneActions', Box);\n\n/** Dónde van las acciones de lo elegido en el teléfono con barra de pestañas abajo: todo arriba o divididas (iOS). */\nexport const SELECTION_PHONE_LAYOUT = Object.freeze({top: 'top', split: 'split'});\n\n// lo que se separa la cápsula de abajo de la barra de pestañas (px), lo mismo que el aviso de versión nueva\nconst FLOATING_GAP_PIXELS = 8;\n// lo que pide al marco mientras flota abajo: su alto (48) y su separación, con aire\nconst FLOATING_BOTTOM_SPACE_PIXELS = 64;\n// lo que solo se ve en el teléfono\nconst PHONE_ONLY_SX = {display: 'none', [PHONE_MEDIA_QUERY]: {display: 'flex'}};\n\n/**\n * ¿En el teléfono lo elegido sale de su renglón (arriba o abajo)? La misma regla que la barra de pestañas de abajo: con ella,\n * el renglón de la pantalla se queda con lo suyo (el conteo de la tabla) y las acciones flotan.\n *\n * @param {object} theme\n * @returns {boolean}\n */\nexport function selectionFloatsOnPhone(theme) {\n return usesMobileTabBar(theme);\n}\n\n/**\n * La cápsula fija abajo, centrada en la ventana, encima de la barra de pestañas.\n *\n * @param {object} theme\n * @returns {object}\n */\nfunction bottomCapsuleSxOf(theme) {\n return {\n ...(isGlassTheme(theme) ? glassStylesOf(theme) : minimalFloatingStylesOf(theme)),\n position: 'fixed',\n left: '50%',\n transform: 'translateX(-50%)',\n zIndex: theme.zIndex.appBar,\n alignItems: 'center',\n gap: 0.5,\n width: 'max-content',\n maxWidth: `calc(100% - ${GLASS_PANEL_GAP_PIXELS * 2}px)`,\n borderRadius: '999px',\n p: 0.5,\n ...aboveMobileTabBarOf(FLOATING_GAP_PIXELS),\n };\n}\n\n/**\n * @param {object} props\n * @param {string} props.countText «5 pedidos elegidos», ya traducido. La pieza se pinta mientras la pantalla la ponga: con\n * nada elegido, no la ponga\n * @param {Array<{key: string, label: string, icon?: import('react').ReactNode, color?: 'inherit'|'primary'|'secondary'|'error'|'info'|'success'|'warning', disabled?: boolean, onClick: () => unknown}>} [props.actions]\n * label ya traducido; en el teléfono se ve el ícono (sin él, el texto). onClick puede regresar una promesa\n * @param {() => void} props.onClear quitar la selección\n * @param {'top'|'split'} [props.phoneLayout] SELECTION_PHONE_LAYOUT; por omisión todo arriba\n * @param {object} [props.texts] los textos que cambian, con la forma de `common`: {selection: {clear, actionsLabel, summaryLabel}}\n * @param {object} [props.sx] estilos del renglón\n */\nfunction SelectionActionsContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaSelectionActions.defaultProps) y encima lo que llega aquí\n const {countText, actions = [], onClear, phoneLayout = SELECTION_PHONE_LAYOUT.top, texts, sx, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const theme = useTheme();\n const {t} = useToolkitTranslation('common', texts);\n const [runningActionKey, setRunningActionKey] = useState(null);\n const floatsOnPhone = selectionFloatsOnPhone(theme);\n const extraSx = Array.isArray(sx) ? sx : [sx];\n\n const runAction = async (action) => {\n setRunningActionKey(action.key);\n try {\n await action.onClick();\n } finally {\n setRunningActionKey(null);\n }\n };\n const isDisabledOf = (action) => runningActionKey !== null || Boolean(action.disabled);\n\n const clearButton = (\n <Tooltip title={t('selection.clear')}>\n <IconButton aria-label={t('selection.clear')} onClick={onClear}>\n <CloseRoundedIcon />\n </IconButton>\n </Tooltip>\n );\n\n // el renglón: escritorio siempre; en el teléfono, solo si ahí no flota\n const row = (\n <SelectionBar role=\"toolbar\" aria-label={t('selection.actionsLabel')} direction=\"row\" spacing={1} useFlexGap\n ownSx={[{flexGrow: 1, alignItems: 'center', flexWrap: 'wrap', minHeight: 32},\n floatsOnPhone && {[PHONE_MEDIA_QUERY]: {display: 'none'}}, ...extraSx]}>\n <SelectionCount variant=\"body2\" ownSx={{fontWeight: 600, mr: 1}}>{countText}</SelectionCount>\n {actions.map((action) => (\n <Button key={action.key} size=\"small\" color={action.color ?? 'primary'} startIcon={action.icon}\n disabled={isDisabledOf(action)} onClick={() => runAction(action)}>\n {action.label}\n </Button>\n ))}\n <SelectionClear size=\"small\" color=\"inherit\" startIcon={<CloseRoundedIcon />} onClick={onClear} ownSx={{ml: 'auto'}}>\n {t('selection.clear')}\n </SelectionClear>\n </SelectionBar>\n );\n\n if (!floatsOnPhone) {\n return row;\n }\n\n const showsBottomCapsule = phoneLayout === SELECTION_PHONE_LAYOUT.split && actions.length > 0;\n\n return (\n <>\n {row}\n {/* arriba: con las demás cápsulas flotantes de la pantalla (BarActions), antes que ellas. Sin label en BarActions:\n el nombre ya lo lleva la cápsula (dos grupos anidados con el mismo nombre se leen dos veces) */}\n <BarActions bare exclusive order={-2} sx={PHONE_ONLY_SX} inlineSx={PHONE_ONLY_SX}>\n <BarCapsule aria-label={t('selection.summaryLabel')} sx={{pl: 2}}>\n <SelectionPhoneCount variant=\"body2\" role=\"status\" aria-live=\"polite\" ownSx={{fontWeight: 600, whiteSpace: 'nowrap', mr: 0.5}}>\n {countText}\n </SelectionPhoneCount>\n {clearButton}\n </BarCapsule>\n </BarActions>\n {phoneLayout === SELECTION_PHONE_LAYOUT.top && actions.length > 0 && (\n <BarActions label={t('selection.actionsLabel')} exclusive order={-1} sx={PHONE_ONLY_SX} inlineSx={PHONE_ONLY_SX}>\n {actions.map((action) => (\n <BarActionButton key={action.key} label={action.label} icon={action.icon} color={action.color}\n disabled={isDisabledOf(action)} onClick={() => runAction(action)} />\n ))}\n </BarActions>\n )}\n {showsBottomCapsule && (\n <>\n <GlobalStyles styles={{':root': {[FLOATING_BOTTOM_SPACE_CSS_VARIABLE]: `${FLOATING_BOTTOM_SPACE_PIXELS}px`}}} />\n <SelectionPhoneActions role=\"toolbar\" aria-label={t('selection.actionsLabel')} ownSx={[bottomCapsuleSxOf, PHONE_ONLY_SX]}>\n {actions.map((action) => (action.icon ? (\n <Tooltip key={action.key} title={action.label}>\n {/* el span deja ver el tooltip aunque el botón esté apagado */}\n <span>\n <IconButton aria-label={action.label} color={action.color ?? 'default'} disabled={isDisabledOf(action)}\n onClick={() => runAction(action)}>\n {action.icon}\n </IconButton>\n </span>\n </Tooltip>\n ) : (\n <Button key={action.key} size=\"small\" color={action.color ?? 'primary'} disabled={isDisabledOf(action)}\n onClick={() => runAction(action)}>\n {action.label}\n </Button>\n )))}\n </SelectionPhoneActions>\n </>\n )}\n </>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst SelectionActions = withPieceSlots(SelectionActionsContent, THEME_NAME);\nexport default SelectionActions;\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ function tableRowTextOf(cells) {
2
+ return cells.map((cell) => (cell === null || cell === void 0 ? "" : String(cell)).replace(/[\t\r\n]+/g, " ")).join(" ");
3
+ }
4
+ export {
5
+ tableRowTextOf
6
+ };
7
+ //# sourceMappingURL=tableRowText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tableRowText.js","sources":["../../../src/ui/actions/tableRowText.js"],"sourcesContent":["// Un renglón de tabla como texto para el portapapeles: sus celdas separadas por tabulador, como copian Excel y las tablas de\n// datos. Al pegarlo en una hoja cada dato cae en su celda; en un correo se lee como una línea. Va con CopyButton:\n//\n// <CopyButton label=\"Copiar el pedido\" value={() => tableRowTextOf([order.folio, order.customer, formatCurrency(order.total)])} />\n//\n// Puro (sin React): se prueba con node (tableRowText.test.js).\n//\n// Genérico del paquete: function (regla de la casa).\n\n/**\n * @param {Array<string|number|null|undefined>} cells las celdas en el orden de las columnas, ya formateadas\n * @returns {string} las celdas unidas con tabulador; una vacía o nula queda vacía. Un tabulador o un salto de renglón dentro\n * de una celda se cambia por un espacio: partirían el renglón al pegarlo\n */\nexport function tableRowTextOf(cells) {\n return cells\n .map((cell) => (cell === null || cell === undefined ? '' : String(cell)).replace(/[\\t\\r\\n]+/g, ' '))\n .join('\\t');\n}\n"],"names":[],"mappings":"AAcO,SAAS,eAAe,OAAO;AAClC,SAAO,MACF,IAAI,CAAC,UAAU,SAAS,QAAQ,SAAS,SAAY,KAAK,OAAO,IAAI,GAAG,QAAQ,cAAc,GAAG,CAAC,EAClG,KAAK,GAAI;AAClB;"}
@@ -0,0 +1,146 @@
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, withPieceSlots, 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 RecordCardContent(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
+ const RecordCard = withPieceSlots(RecordCardContent, THEME_NAME);
143
+ export {
144
+ RecordCard as default
145
+ };
146
+ //# 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, withPieceSlots} 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 */\nfunction RecordCardContent(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={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\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst RecordCard = withPieceSlots(RecordCardContent, THEME_NAME);\nexport default RecordCard;\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
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 { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
8
+ import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
9
+ import { warnUnknownProps } from "../../toolkit/unknownProps.js";
10
+ const THEME_NAME = "CalcitaRecordCardSkeleton";
11
+ const RecordCardSkeletonRoot = piecePart(THEME_NAME, "Root", Paper);
12
+ function RecordCardSkeletonContent(props) {
13
+ const { groups = 2, factsPerGroup = 3, withAvatar = true, withHighlight = true, sx, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
14
+ warnUnknownProps(THEME_NAME, unknownProps);
15
+ const { t } = useToolkitTranslation("common", texts);
16
+ return /* @__PURE__ */ jsxs(RecordCardSkeletonRoot, { variant: "outlined", role: "status", "aria-label": t("recordCard.loading"), ownSx: { p: { xs: 2, sm: 2.5 } }, sx, children: [
17
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", sx: { gap: 1.5, alignItems: "center" }, children: [
18
+ withAvatar && /* @__PURE__ */ jsx(Skeleton, { variant: "circular", width: 44, height: 44 }),
19
+ /* @__PURE__ */ jsxs(Box, { sx: { flex: 1 }, children: [
20
+ /* @__PURE__ */ jsx(Skeleton, { width: "20%" }),
21
+ /* @__PURE__ */ jsx(Skeleton, { width: "45%", height: 28 })
22
+ ] }),
23
+ /* @__PURE__ */ jsx(Skeleton, { variant: "rounded", width: 88, height: 24 })
24
+ ] }),
25
+ /* @__PURE__ */ jsxs(Box, { sx: { mt: 2, display: "grid", gap: 3, gridTemplateColumns: { xs: "1fr", md: `repeat(${groups}, 1fr)${withHighlight ? " 140px" : ""}` } }, children: [
26
+ Array.from({ length: groups }, (unused, groupIndex) => /* @__PURE__ */ jsx(Box, { children: Array.from({ length: factsPerGroup }, (unusedFact, factIndex) => /* @__PURE__ */ jsx(Skeleton, {}, factIndex)) }, groupIndex)),
27
+ withHighlight && /* @__PURE__ */ jsxs(Box, { children: [
28
+ /* @__PURE__ */ jsx(Skeleton, { width: "60%" }),
29
+ /* @__PURE__ */ jsx(Skeleton, { height: 36 })
30
+ ] })
31
+ ] })
32
+ ] });
33
+ }
34
+ const RecordCardSkeleton = withPieceSlots(RecordCardSkeletonContent, THEME_NAME);
35
+ export {
36
+ RecordCardSkeleton as default
37
+ };
38
+ //# 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// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaRecordCardSkeleton con defaultProps (p. ej.\n// {groups: 3}), styleOverrides de su parte root y slots/slotProps.\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 {piecePart, usePieceProps, withPieceSlots} 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 su parte (theme.components.CalcitaRecordCardSkeleton)\nconst THEME_NAME = 'CalcitaRecordCardSkeleton';\nconst RecordCardSkeletonRoot = piecePart(THEME_NAME, 'Root', Paper);\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 */\nfunction RecordCardSkeletonContent(props) {\n const {groups = 2, factsPerGroup = 3, withAvatar = true, withHighlight = true, sx, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n return (\n <RecordCardSkeletonRoot variant=\"outlined\" role=\"status\" aria-label={t('recordCard.loading')} ownSx={{p: {xs: 2, sm: 2.5}}} sx={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 </RecordCardSkeletonRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst RecordCardSkeleton = withPieceSlots(RecordCardSkeletonContent, THEME_NAME);\nexport default RecordCardSkeleton;\n"],"names":[],"mappings":";;;;;;;;;AAiBA,MAAM,aAAa;AACnB,MAAM,yBAAyB,UAAU,YAAY,QAAQ,KAAK;AAWlE,SAAS,0BAA0B,OAAO;AACtC,QAAM,EAAC,SAAS,GAAG,gBAAgB,GAAG,aAAa,MAAM,gBAAgB,MAAM,IAAI,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AAC5I,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,SACI,qBAAC,0BAAuB,SAAQ,YAAW,MAAK,UAAS,cAAY,EAAE,oBAAoB,GAAG,OAAO,EAAC,GAAG,EAAC,IAAI,GAAG,IAAI,IAAA,EAAG,GAAI,IACxH,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;AAGA,MAAM,qBAAqB,eAAe,2BAA2B,UAAU;"}