@stackcraftmx/calcita 0.47.0 → 0.52.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 (501) hide show
  1. package/README.md +192 -13
  2. package/cli/calcita.js +17 -0
  3. package/cli/checkTexts.js +266 -0
  4. package/cli/packageVersions.js +6 -1
  5. package/cli/projectFiles.js +4 -2
  6. package/cli/templates/project/README.md.tpl +21 -1
  7. package/cli/templates/project/eslint.config.js.tpl +27 -0
  8. package/cli/templates/project/src/app/appTexts.js.tpl +2 -1
  9. package/cli/templates/project/src/core/publicPaths.js.tpl +10 -2
  10. package/cli/templates/project/vite.config.js.tpl +8 -1
  11. package/dist/DataTable/AuditTrailDialog.js +3 -2
  12. package/dist/DataTable/AuditTrailDialog.js.map +1 -1
  13. package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js +3 -2
  14. package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js.map +1 -1
  15. package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js +3 -2
  16. package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js.map +1 -1
  17. package/dist/DataTable/ColumnFilters/SortableFilterHeader.js +3 -2
  18. package/dist/DataTable/ColumnFilters/SortableFilterHeader.js.map +1 -1
  19. package/dist/DataTable/EmptyState.js +3 -2
  20. package/dist/DataTable/EmptyState.js.map +1 -1
  21. package/dist/DataTable/FilterChips.js +3 -2
  22. package/dist/DataTable/FilterChips.js.map +1 -1
  23. package/dist/DataTable/GoToPage.js +3 -2
  24. package/dist/DataTable/GoToPage.js.map +1 -1
  25. package/dist/DataTable/ServerTable.js +95 -28
  26. package/dist/DataTable/ServerTable.js.map +1 -1
  27. package/dist/DataTable/ServerTableFilterDrawer.js +8 -3
  28. package/dist/DataTable/ServerTableFilterDrawer.js.map +1 -1
  29. package/dist/DataTable/StackedCell.js +60 -0
  30. package/dist/DataTable/StackedCell.js.map +1 -0
  31. package/dist/DataTable/TableCardsView.js +88 -0
  32. package/dist/DataTable/TableCardsView.js.map +1 -0
  33. package/dist/DataTable/columnWidths.js +30 -0
  34. package/dist/DataTable/columnWidths.js.map +1 -0
  35. package/dist/DataTable/columns.js +47 -1
  36. package/dist/DataTable/columns.js.map +1 -1
  37. package/dist/DataTable/fixedColumns.js +24 -0
  38. package/dist/DataTable/fixedColumns.js.map +1 -0
  39. package/dist/DataTable/useTableView.js +29 -0
  40. package/dist/DataTable/useTableView.js.map +1 -0
  41. package/dist/access/PermissionMatrix.js +3 -2
  42. package/dist/access/PermissionMatrix.js.map +1 -1
  43. package/dist/account/AccountProvider.js +1 -1
  44. package/dist/account/AccountSecuritySection.js +3 -2
  45. package/dist/account/AccountSecuritySection.js.map +1 -1
  46. package/dist/account/DemoTotpCodeButton.js +3 -2
  47. package/dist/account/DemoTotpCodeButton.js.map +1 -1
  48. package/dist/account/ProfileScreen.js +3 -2
  49. package/dist/account/ProfileScreen.js.map +1 -1
  50. package/dist/account/SignInScreen.js +3 -2
  51. package/dist/account/SignInScreen.js.map +1 -1
  52. package/dist/appShell/AccountMenu.js +3 -2
  53. package/dist/appShell/AccountMenu.js.map +1 -1
  54. package/dist/appShell/AppLayout.js +3 -2
  55. package/dist/appShell/AppLayout.js.map +1 -1
  56. package/dist/appShell/AppearanceSettings.js +3 -2
  57. package/dist/appShell/AppearanceSettings.js.map +1 -1
  58. package/dist/appShell/AuthLayout.js +3 -2
  59. package/dist/appShell/AuthLayout.js.map +1 -1
  60. package/dist/appShell/BarActionButton.js +11 -4
  61. package/dist/appShell/BarActionButton.js.map +1 -1
  62. package/dist/appShell/BarActions.js +3 -2
  63. package/dist/appShell/BarActions.js.map +1 -1
  64. package/dist/appShell/BarCapsule.js +3 -2
  65. package/dist/appShell/BarCapsule.js.map +1 -1
  66. package/dist/appShell/BarSearch.js +3 -2
  67. package/dist/appShell/BarSearch.js.map +1 -1
  68. package/dist/appShell/HeaderTools.js +3 -2
  69. package/dist/appShell/HeaderTools.js.map +1 -1
  70. package/dist/appShell/MobileTabBar.js +3 -2
  71. package/dist/appShell/MobileTabBar.js.map +1 -1
  72. package/dist/appShell/SettingsMenu.js +3 -2
  73. package/dist/appShell/SettingsMenu.js.map +1 -1
  74. package/dist/appShell/SideMenu.js +3 -2
  75. package/dist/appShell/SideMenu.js.map +1 -1
  76. package/dist/appShell/SideMenuEntry.js +3 -2
  77. package/dist/appShell/SideMenuEntry.js.map +1 -1
  78. package/dist/appShell/SubmenuActionsMenu.js +3 -2
  79. package/dist/appShell/SubmenuActionsMenu.js.map +1 -1
  80. package/dist/appShell/TabBarEditor.js +3 -2
  81. package/dist/appShell/TabBarEditor.js.map +1 -1
  82. package/dist/appShell/TopMenu.js +3 -2
  83. package/dist/appShell/TopMenu.js.map +1 -1
  84. package/dist/appShell/Wordmark.js +3 -2
  85. package/dist/appShell/Wordmark.js.map +1 -1
  86. package/dist/auth/PasswordChecklist.js +3 -2
  87. package/dist/auth/PasswordChecklist.js.map +1 -1
  88. package/dist/calendar/EventCalendar.js +3 -2
  89. package/dist/calendar/EventCalendar.js.map +1 -1
  90. package/dist/calendar/EventDetails.js +3 -2
  91. package/dist/calendar/EventDetails.js.map +1 -1
  92. package/dist/datePickers/DateInput.js +28 -22
  93. package/dist/datePickers/DateInput.js.map +1 -1
  94. package/dist/datePickers/DateTimeInput.js +33 -27
  95. package/dist/datePickers/DateTimeInput.js.map +1 -1
  96. package/dist/datePickers/MonthInput.js +27 -21
  97. package/dist/datePickers/MonthInput.js.map +1 -1
  98. package/dist/datePickers/TimeInput.js +26 -20
  99. package/dist/datePickers/TimeInput.js.map +1 -1
  100. package/dist/datePickers/usePickerField.js +5 -4
  101. package/dist/datePickers/usePickerField.js.map +1 -1
  102. package/dist/downloads/DownloadManager.js +3 -2
  103. package/dist/downloads/DownloadManager.js.map +1 -1
  104. package/dist/feedback/ConfirmDialog.js +3 -2
  105. package/dist/feedback/ConfirmDialog.js.map +1 -1
  106. package/dist/feedback/ModalWaiting.js +3 -2
  107. package/dist/feedback/ModalWaiting.js.map +1 -1
  108. package/dist/feedback/NewBuildNotice.js +3 -2
  109. package/dist/feedback/NewBuildNotice.js.map +1 -1
  110. package/dist/filepond/FileDropzone.js +3 -2
  111. package/dist/filepond/FileDropzone.js.map +1 -1
  112. package/dist/forms/FormProblemAlert.js +3 -2
  113. package/dist/forms/FormProblemAlert.js.map +1 -1
  114. package/dist/forms/FormWizard.js +21 -6
  115. package/dist/forms/FormWizard.js.map +1 -1
  116. package/dist/forms/SubmitButton.js +7 -2
  117. package/dist/forms/SubmitButton.js.map +1 -1
  118. package/dist/forms/auth/SignInForm.js +3 -2
  119. package/dist/forms/auth/SignInForm.js.map +1 -1
  120. package/dist/forms/fieldRules.js +30 -0
  121. package/dist/forms/fieldRules.js.map +1 -0
  122. package/dist/forms/security/SecondStepForm.js +3 -2
  123. package/dist/forms/security/SecondStepForm.js.map +1 -1
  124. package/dist/forms/security/TwoStepVerificationCard.js +3 -2
  125. package/dist/forms/security/TwoStepVerificationCard.js.map +1 -1
  126. package/dist/forms/useValidationText.js +18 -0
  127. package/dist/forms/useValidationText.js.map +1 -0
  128. package/dist/forms/validation.js +35 -31
  129. package/dist/forms/validation.js.map +1 -1
  130. package/dist/forms/validationMessages.js +64 -7
  131. package/dist/forms/validationMessages.js.map +1 -1
  132. package/dist/forms.js +3 -0
  133. package/dist/forms.js.map +1 -1
  134. package/dist/hookForm/FormProblemAlert.js +3 -2
  135. package/dist/hookForm/FormProblemAlert.js.map +1 -1
  136. package/dist/hookForm/FormWizard.js +19 -5
  137. package/dist/hookForm/FormWizard.js.map +1 -1
  138. package/dist/hookForm/SubmitButton.js +7 -2
  139. package/dist/hookForm/SubmitButton.js.map +1 -1
  140. package/dist/inbox/InboxLayout.js +3 -2
  141. package/dist/inbox/InboxLayout.js.map +1 -1
  142. package/dist/inbox/MessageList.js +3 -2
  143. package/dist/inbox/MessageList.js.map +1 -1
  144. package/dist/inbox/MessageView.js +3 -2
  145. package/dist/inbox/MessageView.js.map +1 -1
  146. package/dist/index.js +193 -163
  147. package/dist/index.js.map +1 -1
  148. package/dist/inputs/CatalogInput.js +32 -25
  149. package/dist/inputs/CatalogInput.js.map +1 -1
  150. package/dist/inputs/CheckboxGroupInput.js +8 -5
  151. package/dist/inputs/CheckboxGroupInput.js.map +1 -1
  152. package/dist/inputs/ColorInput.js +7 -4
  153. package/dist/inputs/ColorInput.js.map +1 -1
  154. package/dist/inputs/FieldFrame.js +10 -4
  155. package/dist/inputs/FieldFrame.js.map +1 -1
  156. package/dist/inputs/FormSection.js +1 -1
  157. package/dist/inputs/MaskedInput.js +1 -0
  158. package/dist/inputs/MaskedInput.js.map +1 -1
  159. package/dist/inputs/NumberInput.js +29 -24
  160. package/dist/inputs/NumberInput.js.map +1 -1
  161. package/dist/inputs/RepeatingFields.js +8 -5
  162. package/dist/inputs/RepeatingFields.js.map +1 -1
  163. package/dist/inputs/SelectInput.js +8 -5
  164. package/dist/inputs/SelectInput.js.map +1 -1
  165. package/dist/inputs/TextInput.js +5 -3
  166. package/dist/inputs/TextInput.js.map +1 -1
  167. package/dist/inputs/TransferListInput.js +8 -5
  168. package/dist/inputs/TransferListInput.js.map +1 -1
  169. package/dist/inputs/WizardLayout.js +48 -19
  170. package/dist/inputs/WizardLayout.js.map +1 -1
  171. package/dist/inputs/useWizardSteps.js +36 -0
  172. package/dist/inputs/useWizardSteps.js.map +1 -0
  173. package/dist/inputs/wizardSteps.js +32 -0
  174. package/dist/inputs/wizardSteps.js.map +1 -0
  175. package/dist/kanban/KanbanBoard.js +3 -2
  176. package/dist/kanban/KanbanBoard.js.map +1 -1
  177. package/dist/legal/CookieNotice.js +3 -2
  178. package/dist/legal/CookieNotice.js.map +1 -1
  179. package/dist/legal/TermsAcceptanceDialog.js +3 -2
  180. package/dist/legal/TermsAcceptanceDialog.js.map +1 -1
  181. package/dist/locales/en.js +24 -0
  182. package/dist/locales/en.js.map +1 -1
  183. package/dist/locales/es.js +24 -0
  184. package/dist/locales/es.js.map +1 -1
  185. package/dist/maps/MapView.js +3 -2
  186. package/dist/maps/MapView.js.map +1 -1
  187. package/dist/mexico/CfdiSummary.js +3 -2
  188. package/dist/mexico/CfdiSummary.js.map +1 -1
  189. package/dist/mexico/EfirmaFields.js +3 -2
  190. package/dist/mexico/EfirmaFields.js.map +1 -1
  191. package/dist/mexico/mexicoIdentifiers.js +5 -0
  192. package/dist/mexico/mexicoIdentifiers.js.map +1 -1
  193. package/dist/mexico/mexicoRules.js +9 -4
  194. package/dist/mexico/mexicoRules.js.map +1 -1
  195. package/dist/mexico.js +4 -2
  196. package/dist/pwa/InstallAppSetting.js +3 -2
  197. package/dist/pwa/InstallAppSetting.js.map +1 -1
  198. package/dist/pwa/InstallInstructionsDialog.js +3 -2
  199. package/dist/pwa/InstallInstructionsDialog.js.map +1 -1
  200. package/dist/pwa/InstallPromptBanner.js +3 -2
  201. package/dist/pwa/InstallPromptBanner.js.map +1 -1
  202. package/dist/react-hook-form.js +3 -0
  203. package/dist/react-hook-form.js.map +1 -1
  204. package/dist/richText/RichTextEditor.js +7 -4
  205. package/dist/richText/RichTextEditor.js.map +1 -1
  206. package/dist/richText/RichTextView.js +3 -2
  207. package/dist/richText/RichTextView.js.map +1 -1
  208. package/dist/security/ActivityLog.js +3 -2
  209. package/dist/security/ActivityLog.js.map +1 -1
  210. package/dist/security/RecoveryCodesDialog.js +3 -2
  211. package/dist/security/RecoveryCodesDialog.js.map +1 -1
  212. package/dist/security/SessionsCard.js +3 -2
  213. package/dist/security/SessionsCard.js.map +1 -1
  214. package/dist/table.js +21 -2
  215. package/dist/table.js.map +1 -1
  216. package/dist/theme/themePieces.js +70 -4
  217. package/dist/theme/themePieces.js.map +1 -1
  218. package/dist/toolkit/ToolkitProvider.js +8 -1
  219. package/dist/toolkit/ToolkitProvider.js.map +1 -1
  220. package/dist/toolkit/browserNavigation.js +19 -4
  221. package/dist/toolkit/browserNavigation.js.map +1 -1
  222. package/dist/toolkit/combineTexts.js +32 -0
  223. package/dist/toolkit/combineTexts.js.map +1 -0
  224. package/dist/toolkit/hashNavigation.js +17 -3
  225. package/dist/toolkit/hashNavigation.js.map +1 -1
  226. package/dist/toolkit/navigationPaths.js +15 -0
  227. package/dist/toolkit/navigationPaths.js.map +1 -1
  228. package/dist/toolkit/pathIndex.js +66 -0
  229. package/dist/toolkit/pathIndex.js.map +1 -0
  230. package/dist/toolkit/toolkitSettings.js +19 -1
  231. package/dist/toolkit/toolkitSettings.js.map +1 -1
  232. package/dist/types/DataTable/AuditTrailDialog.d.ts +6 -17
  233. package/dist/types/DataTable/ColumnFilters/HeaderFilterPopover.d.ts +6 -5
  234. package/dist/types/DataTable/ColumnFilters/MultiSelectColumnFilter.d.ts +6 -9
  235. package/dist/types/DataTable/ColumnFilters/SortableFilterHeader.d.ts +6 -14
  236. package/dist/types/DataTable/EmptyState.d.ts +6 -9
  237. package/dist/types/DataTable/FilterChips.d.ts +6 -11
  238. package/dist/types/DataTable/GoToPage.d.ts +6 -9
  239. package/dist/types/DataTable/ServerTable.d.ts +16 -80
  240. package/dist/types/DataTable/ServerTableFilterDrawer.d.ts +6 -13
  241. package/dist/types/DataTable/StackedCell.d.ts +12 -0
  242. package/dist/types/DataTable/TableCardsView.d.ts +27 -0
  243. package/dist/types/DataTable/columnWidths.d.ts +21 -0
  244. package/dist/types/DataTable/columns.d.ts +111 -0
  245. package/dist/types/DataTable/fixedColumns.d.ts +29 -0
  246. package/dist/types/DataTable/index.d.ts +6 -1
  247. package/dist/types/DataTable/useTableView.d.ts +22 -0
  248. package/dist/types/access/PermissionMatrix.d.ts +6 -10
  249. package/dist/types/account/AccountSecuritySection.d.ts +6 -7
  250. package/dist/types/account/DemoTotpCodeButton.d.ts +6 -5
  251. package/dist/types/account/ProfileScreen.d.ts +6 -18
  252. package/dist/types/account/SignInScreen.d.ts +6 -13
  253. package/dist/types/appShell/AccountMenu.d.ts +6 -11
  254. package/dist/types/appShell/AppLayout.d.ts +3 -40
  255. package/dist/types/appShell/AppearanceSettings.d.ts +6 -12
  256. package/dist/types/appShell/AuthLayout.d.ts +3 -11
  257. package/dist/types/appShell/BarActionButton.d.ts +7 -10
  258. package/dist/types/appShell/BarActions.d.ts +6 -15
  259. package/dist/types/appShell/BarCapsule.d.ts +6 -9
  260. package/dist/types/appShell/BarSearch.d.ts +6 -15
  261. package/dist/types/appShell/HeaderTools.d.ts +6 -16
  262. package/dist/types/appShell/MobileTabBar.d.ts +6 -13
  263. package/dist/types/appShell/SettingsMenu.d.ts +6 -10
  264. package/dist/types/appShell/SideMenu.d.ts +6 -20
  265. package/dist/types/appShell/SideMenuEntry.d.ts +6 -11
  266. package/dist/types/appShell/SubmenuActionsMenu.d.ts +6 -12
  267. package/dist/types/appShell/TabBarEditor.d.ts +6 -9
  268. package/dist/types/appShell/TopMenu.d.ts +6 -5
  269. package/dist/types/appShell/Wordmark.d.ts +6 -7
  270. package/dist/types/auth/PasswordChecklist.d.ts +6 -9
  271. package/dist/types/calendar/EventCalendar.d.ts +6 -23
  272. package/dist/types/calendar/EventDetails.d.ts +6 -10
  273. package/dist/types/datePickers/DateInput.d.ts +7 -22
  274. package/dist/types/datePickers/DateTimeInput.d.ts +7 -27
  275. package/dist/types/datePickers/MonthInput.d.ts +7 -21
  276. package/dist/types/datePickers/TimeInput.d.ts +7 -21
  277. package/dist/types/datePickers/usePickerField.d.ts +5 -1
  278. package/dist/types/downloads/DownloadManager.d.ts +6 -6
  279. package/dist/types/feedback/ConfirmDialog.d.ts +6 -18
  280. package/dist/types/feedback/ModalWaiting.d.ts +6 -9
  281. package/dist/types/feedback/NewBuildNotice.d.ts +6 -10
  282. package/dist/types/filepond/FileDropzone.d.ts +6 -29
  283. package/dist/types/forms/FormProblemAlert.d.ts +6 -5
  284. package/dist/types/forms/FormWizard.d.ts +12 -1
  285. package/dist/types/forms/SubmitButton.d.ts +6 -6
  286. package/dist/types/forms/auth/SignInForm.d.ts +6 -11
  287. package/dist/types/forms/fieldRules.d.ts +44 -0
  288. package/dist/types/forms/index.d.ts +1 -0
  289. package/dist/types/forms/security/SecondStepForm.d.ts +6 -14
  290. package/dist/types/forms/security/TwoStepVerificationCard.d.ts +6 -21
  291. package/dist/types/forms/useValidationText.d.ts +12 -0
  292. package/dist/types/forms/validation.d.ts +117 -174
  293. package/dist/types/forms/validationMessages.d.ts +54 -6
  294. package/dist/types/forms.d.ts +1 -1
  295. package/dist/types/hookForm/FormProblemAlert.d.ts +6 -5
  296. package/dist/types/hookForm/FormWizard.d.ts +12 -1
  297. package/dist/types/hookForm/SubmitButton.d.ts +6 -13
  298. package/dist/types/inbox/InboxLayout.d.ts +6 -17
  299. package/dist/types/inbox/MessageList.d.ts +6 -18
  300. package/dist/types/inbox/MessageView.d.ts +6 -14
  301. package/dist/types/index.d.ts +10 -2
  302. package/dist/types/inputs/CatalogInput.d.ts +7 -24
  303. package/dist/types/inputs/CheckboxGroupInput.d.ts +7 -18
  304. package/dist/types/inputs/ColorInput.d.ts +7 -16
  305. package/dist/types/inputs/FieldFrame.d.ts +6 -10
  306. package/dist/types/inputs/MaskedInput.d.ts +3 -0
  307. package/dist/types/inputs/NumberInput.d.ts +7 -20
  308. package/dist/types/inputs/RepeatingFields.d.ts +7 -28
  309. package/dist/types/inputs/SelectInput.d.ts +7 -20
  310. package/dist/types/inputs/TextInput.d.ts +3 -0
  311. package/dist/types/inputs/TransferListInput.d.ts +7 -20
  312. package/dist/types/inputs/WizardLayout.d.ts +11 -21
  313. package/dist/types/inputs/useWizardSteps.d.ts +23 -0
  314. package/dist/types/inputs/wizardSteps.d.ts +65 -0
  315. package/dist/types/kanban/KanbanBoard.d.ts +6 -25
  316. package/dist/types/legal/CookieNotice.d.ts +6 -16
  317. package/dist/types/legal/TermsAcceptanceDialog.d.ts +6 -18
  318. package/dist/types/locales/en.d.ts +24 -0
  319. package/dist/types/locales/es.d.ts +24 -0
  320. package/dist/types/maps/MapView.d.ts +6 -17
  321. package/dist/types/mexico/CfdiSummary.d.ts +6 -11
  322. package/dist/types/mexico/EfirmaFields.d.ts +6 -16
  323. package/dist/types/mexico/mexicoIdentifiers.d.ts +7 -0
  324. package/dist/types/mexico/mexicoRules.d.ts +19 -3
  325. package/dist/types/mexico.d.ts +2 -2
  326. package/dist/types/pwa/InstallAppSetting.d.ts +6 -6
  327. package/dist/types/pwa/InstallInstructionsDialog.d.ts +6 -9
  328. package/dist/types/pwa/InstallPromptBanner.d.ts +6 -11
  329. package/dist/types/react-hook-form.d.ts +1 -0
  330. package/dist/types/richText/RichTextEditor.d.ts +7 -22
  331. package/dist/types/richText/RichTextView.d.ts +6 -9
  332. package/dist/types/security/ActivityLog.d.ts +6 -9
  333. package/dist/types/security/RecoveryCodesDialog.d.ts +6 -11
  334. package/dist/types/security/SessionsCard.d.ts +6 -11
  335. package/dist/types/table.d.ts +3 -1
  336. package/dist/types/theme/themePieces.d.ts +55 -3
  337. package/dist/types/toolkit/ToolkitProvider.d.ts +13 -1
  338. package/dist/types/toolkit/browserNavigation.d.ts +7 -3
  339. package/dist/types/toolkit/combineTexts.d.ts +6 -0
  340. package/dist/types/toolkit/hashNavigation.d.ts +4 -2
  341. package/dist/types/toolkit/navigationPaths.d.ts +35 -0
  342. package/dist/types/toolkit/pathIndex.d.ts +27 -0
  343. package/dist/types/toolkit/toolkitSettings.d.ts +7 -4
  344. package/dist/types/ui/actions/ActionsMenu.d.ts +9 -11
  345. package/dist/types/ui/actions/CopyButton.d.ts +6 -12
  346. package/dist/types/ui/actions/DownloadMenu.d.ts +6 -29
  347. package/dist/types/ui/actions/SecretField.d.ts +6 -11
  348. package/dist/types/ui/actions/SelectionActions.d.ts +6 -13
  349. package/dist/types/ui/cards/RecordCard.d.ts +16 -29
  350. package/dist/types/ui/cards/RecordCardSkeleton.d.ts +6 -11
  351. package/dist/types/ui/countdown/Countdown.d.ts +6 -15
  352. package/dist/types/ui/documents/PdfViewerDialog.d.ts +6 -13
  353. package/dist/types/ui/filters/DateRangeFilter.d.ts +6 -10
  354. package/dist/types/ui/filters/FilterDrawer.d.ts +6 -17
  355. package/dist/types/ui/filters/PeriodRangeSelector.d.ts +6 -13
  356. package/dist/types/ui/filters/QuickFilters.d.ts +6 -12
  357. package/dist/types/ui/help/HelpButton.d.ts +6 -10
  358. package/dist/types/ui/help/HelpCarouselDialog.d.ts +6 -14
  359. package/dist/types/ui/index.d.ts +1 -1
  360. package/dist/types/ui/labels/MarkedText.d.ts +10 -0
  361. package/dist/types/ui/labels/Tag.d.ts +6 -12
  362. package/dist/types/ui/labels/markedTextPieces.d.ts +22 -0
  363. package/dist/types/ui/layout/CollapsibleSection.d.ts +6 -12
  364. package/dist/types/ui/layout/ContentDialog.d.ts +6 -10
  365. package/dist/types/ui/layout/DefinitionList.d.ts +6 -9
  366. package/dist/types/ui/layout/DetailHeader.d.ts +6 -10
  367. package/dist/types/ui/layout/ErrorPage.d.ts +6 -17
  368. package/dist/types/ui/layout/FullPageLoader.d.ts +6 -6
  369. package/dist/types/ui/layout/GlassPanel.d.ts +6 -8
  370. package/dist/types/ui/layout/PageHeader.d.ts +6 -10
  371. package/dist/types/ui/layout/PageHeading.d.ts +6 -11
  372. package/dist/types/ui/layout/ProfileHeader.d.ts +6 -11
  373. package/dist/types/ui/layout/ScrollableRow.d.ts +6 -13
  374. package/dist/types/ui/layout/SectionCard.d.ts +6 -8
  375. package/dist/types/ui/metrics/BarList.d.ts +6 -12
  376. package/dist/types/ui/metrics/CalendarHeatmap.d.ts +6 -19
  377. package/dist/types/ui/metrics/ChartTooltip.d.ts +6 -6
  378. package/dist/types/ui/metrics/ColumnChart.d.ts +6 -25
  379. package/dist/types/ui/metrics/LineChart.d.ts +6 -20
  380. package/dist/types/ui/metrics/MetricCard.d.ts +6 -17
  381. package/dist/types/ui/metrics/TableToggle.d.ts +6 -6
  382. package/dist/types/ui/metrics/chartParts.d.ts +15 -30
  383. package/dist/types/ui/navigation/BackButton.d.ts +7 -9
  384. package/dist/types/ui/navigation/ColorSchemeToggle.d.ts +6 -9
  385. package/dist/types/ui/navigation/FontSizeToggle.d.ts +6 -8
  386. package/dist/types/ui/navigation/LanguageToggle.d.ts +6 -8
  387. package/dist/types/ui/navigation/PageBreadcrumbs.d.ts +6 -7
  388. package/dist/types/ui/navigation/RouteTabs.d.ts +7 -12
  389. package/dist/types/ui/timeline/GroupedTimeline.d.ts +6 -23
  390. package/dist/types/upload/AttachmentsInput.d.ts +11 -1
  391. package/dist/types/upload/FileDropzone.d.ts +6 -21
  392. package/dist/types/upload/FileInput.d.ts +7 -24
  393. package/dist/types/upload/FileUploadInput.d.ts +7 -31
  394. package/dist/types/upload/ImageInput.d.ts +7 -25
  395. package/dist/types/upload/TemplateDownloadButton.d.ts +6 -18
  396. package/dist/ui/actions/ActionsMenu.js +14 -5
  397. package/dist/ui/actions/ActionsMenu.js.map +1 -1
  398. package/dist/ui/actions/CopyButton.js +8 -3
  399. package/dist/ui/actions/CopyButton.js.map +1 -1
  400. package/dist/ui/actions/DownloadMenu.js +3 -2
  401. package/dist/ui/actions/DownloadMenu.js.map +1 -1
  402. package/dist/ui/actions/SecretField.js +8 -3
  403. package/dist/ui/actions/SecretField.js.map +1 -1
  404. package/dist/ui/actions/SelectionActions.js +3 -2
  405. package/dist/ui/actions/SelectionActions.js.map +1 -1
  406. package/dist/ui/cards/RecordCard.js +10 -5
  407. package/dist/ui/cards/RecordCard.js.map +1 -1
  408. package/dist/ui/cards/RecordCardSkeleton.js +8 -3
  409. package/dist/ui/cards/RecordCardSkeleton.js.map +1 -1
  410. package/dist/ui/countdown/Countdown.js +3 -2
  411. package/dist/ui/countdown/Countdown.js.map +1 -1
  412. package/dist/ui/documents/PdfViewerDialog.js +3 -2
  413. package/dist/ui/documents/PdfViewerDialog.js.map +1 -1
  414. package/dist/ui/filters/DateRangeFilter.js +3 -2
  415. package/dist/ui/filters/DateRangeFilter.js.map +1 -1
  416. package/dist/ui/filters/FilterDrawer.js +3 -2
  417. package/dist/ui/filters/FilterDrawer.js.map +1 -1
  418. package/dist/ui/filters/PeriodRangeSelector.js +3 -2
  419. package/dist/ui/filters/PeriodRangeSelector.js.map +1 -1
  420. package/dist/ui/filters/QuickFilters.js +3 -2
  421. package/dist/ui/filters/QuickFilters.js.map +1 -1
  422. package/dist/ui/help/HelpButton.js +8 -3
  423. package/dist/ui/help/HelpButton.js.map +1 -1
  424. package/dist/ui/help/HelpCarouselDialog.js +3 -2
  425. package/dist/ui/help/HelpCarouselDialog.js.map +1 -1
  426. package/dist/ui/labels/MarkedText.js +31 -0
  427. package/dist/ui/labels/MarkedText.js.map +1 -0
  428. package/dist/ui/labels/Tag.js +3 -2
  429. package/dist/ui/labels/Tag.js.map +1 -1
  430. package/dist/ui/labels/markedTextPieces.js +64 -0
  431. package/dist/ui/labels/markedTextPieces.js.map +1 -0
  432. package/dist/ui/layout/CollapsibleSection.js +3 -2
  433. package/dist/ui/layout/CollapsibleSection.js.map +1 -1
  434. package/dist/ui/layout/ContentDialog.js +3 -2
  435. package/dist/ui/layout/ContentDialog.js.map +1 -1
  436. package/dist/ui/layout/DefinitionList.js +3 -2
  437. package/dist/ui/layout/DefinitionList.js.map +1 -1
  438. package/dist/ui/layout/DetailHeader.js +3 -2
  439. package/dist/ui/layout/DetailHeader.js.map +1 -1
  440. package/dist/ui/layout/ErrorPage.js +3 -2
  441. package/dist/ui/layout/ErrorPage.js.map +1 -1
  442. package/dist/ui/layout/FullPageLoader.js +3 -2
  443. package/dist/ui/layout/FullPageLoader.js.map +1 -1
  444. package/dist/ui/layout/GlassPanel.js +3 -2
  445. package/dist/ui/layout/GlassPanel.js.map +1 -1
  446. package/dist/ui/layout/PageHeader.js +3 -2
  447. package/dist/ui/layout/PageHeader.js.map +1 -1
  448. package/dist/ui/layout/PageHeading.js +3 -2
  449. package/dist/ui/layout/PageHeading.js.map +1 -1
  450. package/dist/ui/layout/ProfileHeader.js +3 -2
  451. package/dist/ui/layout/ProfileHeader.js.map +1 -1
  452. package/dist/ui/layout/ScrollableRow.js +3 -2
  453. package/dist/ui/layout/ScrollableRow.js.map +1 -1
  454. package/dist/ui/layout/SectionCard.js +3 -2
  455. package/dist/ui/layout/SectionCard.js.map +1 -1
  456. package/dist/ui/metrics/BarList.js +3 -2
  457. package/dist/ui/metrics/BarList.js.map +1 -1
  458. package/dist/ui/metrics/CalendarHeatmap.js +3 -2
  459. package/dist/ui/metrics/CalendarHeatmap.js.map +1 -1
  460. package/dist/ui/metrics/ChartTooltip.js +3 -2
  461. package/dist/ui/metrics/ChartTooltip.js.map +1 -1
  462. package/dist/ui/metrics/ColumnChart.js +3 -2
  463. package/dist/ui/metrics/ColumnChart.js.map +1 -1
  464. package/dist/ui/metrics/LineChart.js +3 -2
  465. package/dist/ui/metrics/LineChart.js.map +1 -1
  466. package/dist/ui/metrics/MetricCard.js +3 -2
  467. package/dist/ui/metrics/MetricCard.js.map +1 -1
  468. package/dist/ui/metrics/TableToggle.js +3 -2
  469. package/dist/ui/metrics/TableToggle.js.map +1 -1
  470. package/dist/ui/metrics/chartParts.js +7 -4
  471. package/dist/ui/metrics/chartParts.js.map +1 -1
  472. package/dist/ui/navigation/BackButton.js +7 -2
  473. package/dist/ui/navigation/BackButton.js.map +1 -1
  474. package/dist/ui/navigation/ColorSchemeToggle.js +3 -2
  475. package/dist/ui/navigation/ColorSchemeToggle.js.map +1 -1
  476. package/dist/ui/navigation/FontSizeToggle.js +3 -2
  477. package/dist/ui/navigation/FontSizeToggle.js.map +1 -1
  478. package/dist/ui/navigation/LanguageToggle.js +3 -2
  479. package/dist/ui/navigation/LanguageToggle.js.map +1 -1
  480. package/dist/ui/navigation/PageBreadcrumbs.js +3 -2
  481. package/dist/ui/navigation/PageBreadcrumbs.js.map +1 -1
  482. package/dist/ui/navigation/RouteTabs.js +8 -4
  483. package/dist/ui/navigation/RouteTabs.js.map +1 -1
  484. package/dist/ui/timeline/GroupedTimeline.js +3 -2
  485. package/dist/ui/timeline/GroupedTimeline.js.map +1 -1
  486. package/dist/upload/AttachmentsInput.js +9 -6
  487. package/dist/upload/AttachmentsInput.js.map +1 -1
  488. package/dist/upload/FileChip.js +2 -1
  489. package/dist/upload/FileChip.js.map +1 -1
  490. package/dist/upload/FileDropzone.js +5 -4
  491. package/dist/upload/FileDropzone.js.map +1 -1
  492. package/dist/upload/FileInput.js +9 -6
  493. package/dist/upload/FileInput.js.map +1 -1
  494. package/dist/upload/FileUploadInput.js +9 -6
  495. package/dist/upload/FileUploadInput.js.map +1 -1
  496. package/dist/upload/ImageInput.js +8 -5
  497. package/dist/upload/ImageInput.js.map +1 -1
  498. package/dist/upload/TemplateDownloadButton.js +3 -2
  499. package/dist/upload/TemplateDownloadButton.js.map +1 -1
  500. package/package.json +1 -1
  501. package/cli/templates/project/src/app/combineTexts.js.tpl +0 -31
@@ -1 +1 @@
1
- {"version":3,"file":"SortableFilterHeader.js","sources":["../../../src/DataTable/ColumnFilters/SortableFilterHeader.jsx"],"sourcesContent":["// Encabezado con orden y filtro.\n//\n// El que ordena es el TÍTULO, no un botón aparte: es el gesto que ya tiene aprendido quien usa tablas. La flecha solo\n// aparece cuando la columna está ordenando, y su × quita ese orden sin tener que ciclar hasta el tercer clic.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaSortableFilterHeader con defaultProps y\n// styleOverrides de sus partes: title, root, sortButton, sortIndicator, clearButton.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport ButtonBase from '@mui/material/ButtonBase';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\n\nimport HeaderFilterPopover from '@/DataTable/ColumnFilters/HeaderFilterPopover.jsx';\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.CalcitaSortableFilterHeader)\nconst THEME_NAME = 'CalcitaSortableFilterHeader';\nconst SortableTitle = piecePart(THEME_NAME, 'Title', Typography);\nconst SortableRoot = piecePart(THEME_NAME, 'Root', Stack);\nconst SortableSortButton = piecePart(THEME_NAME, 'SortButton', ButtonBase);\nconst SortableSortIndicator = piecePart(THEME_NAME, 'SortIndicator', Box);\nconst SortableClearButton = piecePart(THEME_NAME, 'ClearButton', ButtonBase);\n\n/**\n * @param {object} props\n * @param {string} props.label\n * @param {boolean} [props.sortable]\n * @param {{column: string, direction: 'asc'|'desc'}} [props.sortEntry]\n * @param {() => void} [props.onSort]\n * @param {() => void} [props.onClearSort]\n * @param {boolean} [props.filterable]\n * @param {number} [props.activeCount]\n * @param {() => void} [props.onClear]\n * @param {import('react').ReactNode} [props.children] el filtro de la columna\n */\nexport default function SortableFilterHeader(props) {\n // lo que el proyecto puso en su tema (components.CalcitaSortableFilterHeader.defaultProps) y encima lo que llega aquí\n const {\n label, sortable = true, sortEntry, onSort, onClearSort, filterable = true, activeCount, onClear, children,\n ...unknownProps\n} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('table');\n const title = <SortableTitle variant=\"caption\" ownSx={{fontWeight: 700, whiteSpace: 'nowrap'}}>{label}</SortableTitle>;\n\n return (\n <SortableRoot direction=\"row\" spacing={0.25} ownSx={{alignItems: 'center'}}>\n {sortable ? (\n <Tooltip title={t('sort.tooltip')}>\n <SortableSortButton onClick={onSort} ownSx={{gap: 0.25, borderRadius: 0.5}}>\n {title}\n {sortEntry && (\n <SortableSortIndicator component=\"span\" ownSx={{display: 'inline-flex', alignItems: 'center', color: 'primary.main', fontWeight: 700}}\n aria-label={sortEntry.direction === 'asc' ? t('sort.ascending') : t('sort.descending')}>\n {sortEntry.direction === 'asc' ? '↑' : '↓'}\n </SortableSortIndicator>\n )}\n </SortableSortButton>\n </Tooltip>\n ) : title}\n\n {sortEntry && onClearSort && (\n <Tooltip title={t('sort.clear')}>\n <SortableClearButton aria-label={t('sort.clear')}\n // sin opacidad: la × es un control y al 70% daba 2.90:1 sobre el encabezado de la tabla\n ownSx={{fontSize: 12, lineHeight: 1, color: 'primary.main', '&:hover': {color: 'primary.dark'}}}\n onClick={(event) => {\n event.stopPropagation();\n onClearSort();\n }}>\n ×\n </SortableClearButton>\n </Tooltip>\n )}\n\n {filterable && (\n <HeaderFilterPopover activeCount={activeCount} onClear={onClear}>{children}</HeaderFilterPopover>\n )}\n </SortableRoot>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;AAqBA,MAAM,aAAa;AACnB,MAAM,gBAAgB,UAAU,YAAY,SAAS,UAAU;AAC/D,MAAM,eAAe,UAAU,YAAY,QAAQ,KAAK;AACxD,MAAM,qBAAqB,UAAU,YAAY,cAAc,UAAU;AACzE,MAAM,wBAAwB,UAAU,YAAY,iBAAiB,GAAG;AACxE,MAAM,sBAAsB,UAAU,YAAY,eAAe,UAAU;AAc3E,SAAwB,qBAAqB,OAAO;AAEhD,QAAM;AAAA,IACN;AAAA,IAAO,WAAW;AAAA,IAAM;AAAA,IAAW;AAAA,IAAQ;AAAA,IAAa,aAAa;AAAA,IAAM;AAAA,IAAa;AAAA,IAAS;AAAA,IACjG,GAAG;AAAA,EAAA,IACH,cAAc,OAAO,UAAU;AAC/B,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,OAAO;AACzC,QAAM,QAAQ,oBAAC,eAAA,EAAc,SAAQ,WAAU,OAAO,EAAC,YAAY,KAAK,YAAY,SAAA,GAAY,UAAA,MAAA,CAAM;AAEtG,SACI,qBAAC,cAAA,EAAa,WAAU,OAAM,SAAS,MAAM,OAAO,EAAC,YAAY,SAAA,GAC5D,UAAA;AAAA,IAAA,+BACI,SAAA,EAAQ,OAAO,EAAE,cAAc,GAC5B,UAAA,qBAAC,oBAAA,EAAmB,SAAS,QAAQ,OAAO,EAAC,KAAK,MAAM,cAAc,OACjE,UAAA;AAAA,MAAA;AAAA,MACA,aACG;AAAA,QAAC;AAAA,QAAA;AAAA,UAAsB,WAAU;AAAA,UAAO,OAAO,EAAC,SAAS,eAAe,YAAY,UAAU,OAAO,gBAAgB,YAAY,IAAA;AAAA,UAC5H,cAAY,UAAU,cAAc,QAAQ,EAAE,gBAAgB,IAAI,EAAE,iBAAiB;AAAA,UACrF,UAAA,UAAU,cAAc,QAAQ,MAAM;AAAA,QAAA;AAAA,MAAA;AAAA,IAC3C,EAAA,CAER,GACJ,IACA;AAAA,IAEH,aAAa,eACV,oBAAC,WAAQ,OAAO,EAAE,YAAY,GAC1B,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QAAoB,cAAY,EAAE,YAAY;AAAA,QAEnC,OAAO,EAAC,UAAU,IAAI,YAAY,GAAG,OAAO,gBAAgB,WAAW,EAAC,OAAO,eAAA,EAAc;AAAA,QAC7F,SAAS,CAAC,UAAU;AAChB,gBAAM,gBAAA;AACN,sBAAA;AAAA,QACJ;AAAA,QAAG,UAAA;AAAA,MAAA;AAAA,IAAA,GAGnB;AAAA,IAGH,cACG,oBAAC,qBAAA,EAAoB,aAA0B,SAAmB,SAAA,CAAS;AAAA,EAAA,GAEnF;AAER;"}
1
+ {"version":3,"file":"SortableFilterHeader.js","sources":["../../../src/DataTable/ColumnFilters/SortableFilterHeader.jsx"],"sourcesContent":["// Encabezado con orden y filtro.\n//\n// El que ordena es el TÍTULO, no un botón aparte: es el gesto que ya tiene aprendido quien usa tablas. La flecha solo\n// aparece cuando la columna está ordenando, y su × quita ese orden sin tener que ciclar hasta el tercer clic.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaSortableFilterHeader con defaultProps y\n// styleOverrides de sus partes: title, root, sortButton, sortIndicator, clearButton.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport ButtonBase from '@mui/material/ButtonBase';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\n\nimport HeaderFilterPopover from '@/DataTable/ColumnFilters/HeaderFilterPopover.jsx';\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.CalcitaSortableFilterHeader)\nconst THEME_NAME = 'CalcitaSortableFilterHeader';\nconst SortableTitle = piecePart(THEME_NAME, 'Title', Typography);\nconst SortableRoot = piecePart(THEME_NAME, 'Root', Stack);\nconst SortableSortButton = piecePart(THEME_NAME, 'SortButton', ButtonBase);\nconst SortableSortIndicator = piecePart(THEME_NAME, 'SortIndicator', Box);\nconst SortableClearButton = piecePart(THEME_NAME, 'ClearButton', ButtonBase);\n\n/**\n * @param {object} props\n * @param {string} props.label\n * @param {boolean} [props.sortable]\n * @param {{column: string, direction: 'asc'|'desc'}} [props.sortEntry]\n * @param {() => void} [props.onSort]\n * @param {() => void} [props.onClearSort]\n * @param {boolean} [props.filterable]\n * @param {number} [props.activeCount]\n * @param {() => void} [props.onClear]\n * @param {import('react').ReactNode} [props.children] el filtro de la columna\n */\nfunction SortableFilterHeaderContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaSortableFilterHeader.defaultProps) y encima lo que llega aquí\n const {\n label, sortable = true, sortEntry, onSort, onClearSort, filterable = true, activeCount, onClear, children,\n ...unknownProps\n} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('table');\n const title = <SortableTitle variant=\"caption\" ownSx={{fontWeight: 700, whiteSpace: 'nowrap'}}>{label}</SortableTitle>;\n\n return (\n <SortableRoot direction=\"row\" spacing={0.25} ownSx={{alignItems: 'center'}}>\n {sortable ? (\n <Tooltip title={t('sort.tooltip')}>\n <SortableSortButton onClick={onSort} ownSx={{gap: 0.25, borderRadius: 0.5}}>\n {title}\n {sortEntry && (\n <SortableSortIndicator component=\"span\" ownSx={{display: 'inline-flex', alignItems: 'center', color: 'primary.main', fontWeight: 700}}\n aria-label={sortEntry.direction === 'asc' ? t('sort.ascending') : t('sort.descending')}>\n {sortEntry.direction === 'asc' ? '↑' : '↓'}\n </SortableSortIndicator>\n )}\n </SortableSortButton>\n </Tooltip>\n ) : title}\n\n {sortEntry && onClearSort && (\n <Tooltip title={t('sort.clear')}>\n <SortableClearButton aria-label={t('sort.clear')}\n // sin opacidad: la × es un control y al 70% daba 2.90:1 sobre el encabezado de la tabla\n ownSx={{fontSize: 12, lineHeight: 1, color: 'primary.main', '&:hover': {color: 'primary.dark'}}}\n onClick={(event) => {\n event.stopPropagation();\n onClearSort();\n }}>\n ×\n </SortableClearButton>\n </Tooltip>\n )}\n\n {filterable && (\n <HeaderFilterPopover activeCount={activeCount} onClear={onClear}>{children}</HeaderFilterPopover>\n )}\n </SortableRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst SortableFilterHeader = withPieceSlots(SortableFilterHeaderContent, THEME_NAME);\nexport default SortableFilterHeader;\n"],"names":[],"mappings":";;;;;;;;;;;AAqBA,MAAM,aAAa;AACnB,MAAM,gBAAgB,UAAU,YAAY,SAAS,UAAU;AAC/D,MAAM,eAAe,UAAU,YAAY,QAAQ,KAAK;AACxD,MAAM,qBAAqB,UAAU,YAAY,cAAc,UAAU;AACzE,MAAM,wBAAwB,UAAU,YAAY,iBAAiB,GAAG;AACxE,MAAM,sBAAsB,UAAU,YAAY,eAAe,UAAU;AAc3E,SAAS,4BAA4B,OAAO;AAExC,QAAM;AAAA,IACN;AAAA,IAAO,WAAW;AAAA,IAAM;AAAA,IAAW;AAAA,IAAQ;AAAA,IAAa,aAAa;AAAA,IAAM;AAAA,IAAa;AAAA,IAAS;AAAA,IACjG,GAAG;AAAA,EAAA,IACH,cAAc,OAAO,UAAU;AAC/B,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,OAAO;AACzC,QAAM,QAAQ,oBAAC,eAAA,EAAc,SAAQ,WAAU,OAAO,EAAC,YAAY,KAAK,YAAY,SAAA,GAAY,UAAA,MAAA,CAAM;AAEtG,SACI,qBAAC,cAAA,EAAa,WAAU,OAAM,SAAS,MAAM,OAAO,EAAC,YAAY,SAAA,GAC5D,UAAA;AAAA,IAAA,+BACI,SAAA,EAAQ,OAAO,EAAE,cAAc,GAC5B,UAAA,qBAAC,oBAAA,EAAmB,SAAS,QAAQ,OAAO,EAAC,KAAK,MAAM,cAAc,OACjE,UAAA;AAAA,MAAA;AAAA,MACA,aACG;AAAA,QAAC;AAAA,QAAA;AAAA,UAAsB,WAAU;AAAA,UAAO,OAAO,EAAC,SAAS,eAAe,YAAY,UAAU,OAAO,gBAAgB,YAAY,IAAA;AAAA,UAC5H,cAAY,UAAU,cAAc,QAAQ,EAAE,gBAAgB,IAAI,EAAE,iBAAiB;AAAA,UACrF,UAAA,UAAU,cAAc,QAAQ,MAAM;AAAA,QAAA;AAAA,MAAA;AAAA,IAC3C,EAAA,CAER,GACJ,IACA;AAAA,IAEH,aAAa,eACV,oBAAC,WAAQ,OAAO,EAAE,YAAY,GAC1B,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QAAoB,cAAY,EAAE,YAAY;AAAA,QAEnC,OAAO,EAAC,UAAU,IAAI,YAAY,GAAG,OAAO,gBAAgB,WAAW,EAAC,OAAO,eAAA,EAAc;AAAA,QAC7F,SAAS,CAAC,UAAU;AAChB,gBAAM,gBAAA;AACN,sBAAA;AAAA,QACJ;AAAA,QAAG,UAAA;AAAA,MAAA;AAAA,IAAA,GAGnB;AAAA,IAGH,cACG,oBAAC,qBAAA,EAAoB,aAA0B,SAAmB,SAAA,CAAS;AAAA,EAAA,GAEnF;AAER;AAGA,MAAM,uBAAuB,eAAe,6BAA6B,UAAU;"}
@@ -7,12 +7,12 @@ import Stack from "@mui/material/Stack";
7
7
  import Typography from "@mui/material/Typography";
8
8
  import FilterListOffIcon from "@mui/icons-material/FilterListOff";
9
9
  import InboxOutlinedIcon from "@mui/icons-material/InboxOutlined";
10
- import { piecePart, usePieceProps } from "../theme/themePieces.js";
10
+ import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
11
11
  import { warnUnknownProps } from "../toolkit/unknownProps.js";
12
12
  const THEME_NAME = "CalcitaEmptyState";
13
13
  const EmptyRoot = piecePart(THEME_NAME, "Root", Stack);
14
14
  const EmptyIcon = piecePart(THEME_NAME, "Icon", Box);
15
- function EmptyState(props) {
15
+ function EmptyStateContent(props) {
16
16
  const { filtered = false, label, onClearFilters, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
17
17
  warnUnknownProps(THEME_NAME, unknownProps);
18
18
  const { t } = useToolkitTranslation("table", texts);
@@ -23,6 +23,7 @@ function EmptyState(props) {
23
23
  filtered && onClearFilters && /* @__PURE__ */ jsx(Button, { size: "small", onClick: onClearFilters, children: t("empty.clearFilters") })
24
24
  ] });
25
25
  }
26
+ const EmptyState = withPieceSlots(EmptyStateContent, THEME_NAME);
26
27
  export {
27
28
  EmptyState as default
28
29
  };
@@ -1 +1 @@
1
- {"version":3,"file":"EmptyState.js","sources":["../../src/DataTable/EmptyState.jsx"],"sourcesContent":["// Qué decir cuando la tabla no tiene filas.\n//\n// Son dos situaciones distintas y confundirlas hace daño:\n// - sin filtros puestos, la lista vacía es el RESULTADO y se dice tal cual (label);\n// - con filtros puestos, la lista vacía NO dice nada del conjunto: dice que lo filtrado no existe dentro de él. Ahí\n// sí hay algo que hacer, y el botón lo hace.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaEmptyState con defaultProps y\n// styleOverrides de sus partes: root, icon.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport FilterListOffIcon from '@mui/icons-material/FilterListOff';\nimport InboxOutlinedIcon from '@mui/icons-material/InboxOutlined';\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.CalcitaEmptyState)\nconst THEME_NAME = 'CalcitaEmptyState';\nconst EmptyRoot = piecePart(THEME_NAME, 'Root', Stack);\nconst EmptyIcon = piecePart(THEME_NAME, 'Icon', Box);\n\n/**\n * @param {object} [props]\n * @param {boolean} [props.filtered]\n * @param {string} [props.label] ya traducido\n * @param {() => void} [props.onClearFilters]\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\nexport default function EmptyState(props) {\n // lo que el proyecto puso en su tema (components.CalcitaEmptyState.defaultProps) y encima lo que llega aquí\n const {filtered = false, label, onClearFilters, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('table', texts);\n const Icon = filtered ? FilterListOffIcon : InboxOutlinedIcon;\n\n return (\n <EmptyRoot spacing={1} ownSx={{height: '100%', px: 3, textAlign: 'center', alignItems: 'center', justifyContent: 'center'}}>\n <EmptyIcon ownSx={{color: 'text.disabled', display: 'flex'}}>\n <Icon fontSize=\"large\" />\n </EmptyIcon>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {filtered ? t('empty.filtered') : (label ?? t('empty.default'))}\n </Typography>\n {filtered && onClearFilters && (\n <Button size=\"small\" onClick={onClearFilters}>{t('empty.clearFilters')}</Button>\n )}\n </EmptyRoot>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;AAsBA,MAAM,aAAa;AACnB,MAAM,YAAY,UAAU,YAAY,QAAQ,KAAK;AACrD,MAAM,YAAY,UAAU,YAAY,QAAQ,GAAG;AASnD,SAAwB,WAAW,OAAO;AAEtC,QAAM,EAAC,WAAW,OAAO,OAAO,gBAAgB,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AACzG,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,SAAS,KAAK;AAChD,QAAM,OAAO,WAAW,oBAAoB;AAE5C,8BACK,WAAA,EAAU,SAAS,GAAG,OAAO,EAAC,QAAQ,QAAQ,IAAI,GAAG,WAAW,UAAU,YAAY,UAAU,gBAAgB,YAC7G,UAAA;AAAA,IAAA,oBAAC,WAAA,EAAU,OAAO,EAAC,OAAO,iBAAiB,SAAS,OAAA,GAChD,UAAA,oBAAC,MAAA,EAAK,UAAS,QAAA,CAAQ,GAC3B;AAAA,IACA,oBAAC,YAAA,EAAW,SAAQ,SAAQ,OAAM,kBAC7B,UAAA,WAAW,EAAE,gBAAgB,IAAK,SAAS,EAAE,eAAe,GACjE;AAAA,IACC,YAAY,kBACT,oBAAC,QAAA,EAAO,MAAK,SAAQ,SAAS,gBAAiB,UAAA,EAAE,oBAAoB,EAAA,CAAE;AAAA,EAAA,GAE/E;AAER;"}
1
+ {"version":3,"file":"EmptyState.js","sources":["../../src/DataTable/EmptyState.jsx"],"sourcesContent":["// Qué decir cuando la tabla no tiene filas.\n//\n// Son dos situaciones distintas y confundirlas hace daño:\n// - sin filtros puestos, la lista vacía es el RESULTADO y se dice tal cual (label);\n// - con filtros puestos, la lista vacía NO dice nada del conjunto: dice que lo filtrado no existe dentro de él. Ahí\n// sí hay algo que hacer, y el botón lo hace.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaEmptyState con defaultProps y\n// styleOverrides de sus partes: root, icon.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport FilterListOffIcon from '@mui/icons-material/FilterListOff';\nimport InboxOutlinedIcon from '@mui/icons-material/InboxOutlined';\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.CalcitaEmptyState)\nconst THEME_NAME = 'CalcitaEmptyState';\nconst EmptyRoot = piecePart(THEME_NAME, 'Root', Stack);\nconst EmptyIcon = piecePart(THEME_NAME, 'Icon', Box);\n\n/**\n * @param {object} [props]\n * @param {boolean} [props.filtered]\n * @param {string} [props.label] ya traducido\n * @param {() => void} [props.onClearFilters]\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\nfunction EmptyStateContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaEmptyState.defaultProps) y encima lo que llega aquí\n const {filtered = false, label, onClearFilters, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('table', texts);\n const Icon = filtered ? FilterListOffIcon : InboxOutlinedIcon;\n\n return (\n <EmptyRoot spacing={1} ownSx={{height: '100%', px: 3, textAlign: 'center', alignItems: 'center', justifyContent: 'center'}}>\n <EmptyIcon ownSx={{color: 'text.disabled', display: 'flex'}}>\n <Icon fontSize=\"large\" />\n </EmptyIcon>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {filtered ? t('empty.filtered') : (label ?? t('empty.default'))}\n </Typography>\n {filtered && onClearFilters && (\n <Button size=\"small\" onClick={onClearFilters}>{t('empty.clearFilters')}</Button>\n )}\n </EmptyRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst EmptyState = withPieceSlots(EmptyStateContent, THEME_NAME);\nexport default EmptyState;\n"],"names":[],"mappings":";;;;;;;;;;;AAsBA,MAAM,aAAa;AACnB,MAAM,YAAY,UAAU,YAAY,QAAQ,KAAK;AACrD,MAAM,YAAY,UAAU,YAAY,QAAQ,GAAG;AASnD,SAAS,kBAAkB,OAAO;AAE9B,QAAM,EAAC,WAAW,OAAO,OAAO,gBAAgB,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AACzG,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,SAAS,KAAK;AAChD,QAAM,OAAO,WAAW,oBAAoB;AAE5C,8BACK,WAAA,EAAU,SAAS,GAAG,OAAO,EAAC,QAAQ,QAAQ,IAAI,GAAG,WAAW,UAAU,YAAY,UAAU,gBAAgB,YAC7G,UAAA;AAAA,IAAA,oBAAC,WAAA,EAAU,OAAO,EAAC,OAAO,iBAAiB,SAAS,OAAA,GAChD,UAAA,oBAAC,MAAA,EAAK,UAAS,QAAA,CAAQ,GAC3B;AAAA,IACA,oBAAC,YAAA,EAAW,SAAQ,SAAQ,OAAM,kBAC7B,UAAA,WAAW,EAAE,gBAAgB,IAAK,SAAS,EAAE,eAAe,GACjE;AAAA,IACC,YAAY,kBACT,oBAAC,QAAA,EAAO,MAAK,SAAQ,SAAS,gBAAiB,UAAA,EAAE,oBAAoB,EAAA,CAAE;AAAA,EAAA,GAE/E;AAER;AAGA,MAAM,aAAa,eAAe,mBAAmB,UAAU;"}
@@ -8,13 +8,13 @@ import Typography from "@mui/material/Typography";
8
8
  import ClearAllIcon from "@mui/icons-material/ClearAll";
9
9
  import ScrollableRow from "../ui/layout/ScrollableRow.js";
10
10
  import Tag from "../ui/labels/Tag.js";
11
- import { piecePart, usePieceProps } from "../theme/themePieces.js";
11
+ import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
12
12
  import { warnUnknownProps } from "../toolkit/unknownProps.js";
13
13
  const THEME_NAME = "CalcitaFilterChips";
14
14
  const ChipsRoot = piecePart(THEME_NAME, "Root", Box);
15
15
  const ChipsHeader = piecePart(THEME_NAME, "Header", Stack);
16
16
  const ChipsClearButton = piecePart(THEME_NAME, "ClearButton", Button);
17
- function FilterChips(props) {
17
+ function FilterChipsContent(props) {
18
18
  const { chipConfig, filters, onSetFilter, onClearAll, quickActiveCount = 0, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
19
19
  warnUnknownProps(THEME_NAME, unknownProps);
20
20
  const { t } = useToolkitTranslation("table", texts);
@@ -41,6 +41,7 @@ function FilterChips(props) {
41
41
  chips.length > 0 && /* @__PURE__ */ jsx(ScrollableRow, { children: chips.map(({ id, label, onDelete }) => /* @__PURE__ */ jsx(Tag, { label, color: "primary", onDelete, sx: { flex: "0 0 auto" } }, id)) })
42
42
  ] });
43
43
  }
44
+ const FilterChips = withPieceSlots(FilterChipsContent, THEME_NAME);
44
45
  export {
45
46
  FilterChips as default
46
47
  };
@@ -1 +1 @@
1
- {"version":3,"file":"FilterChips.js","sources":["../../src/DataTable/FilterChips.jsx"],"sourcesContent":["// Los filtros activos, a la vista y desarmables de a uno.\n//\n// Un filtro que solo se ve como un icono encendido en el encabezado se olvida: alguien filtra, se va al detalle,\n// regresa y lee el total como si fuera el de todo. Por eso los filtros puestos se dicen con todas sus letras arriba de\n// la tabla.\n//\n// Van en UNA tira que se desliza (ScrollableRow), no envolviéndose en renglones que empujan la tabla fuera de la\n// pantalla. La cuenta y \"Limpiar todo\" van en su propio renglón, arriba, para no tener que deslizar hasta encontrarlo.\n// Sin filtros activos no se pinta nada (ni el hueco).\n//\n// Los accesos rápidos cuentan aunque no tengan chip aquí: su propio chip encendido ya dice qué está elegido.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaFilterChips con defaultProps y\n// styleOverrides de sus partes: root, header, clearButton.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport ClearAllIcon from '@mui/icons-material/ClearAll';\n\nimport ScrollableRow from '@/ui/layout/ScrollableRow.jsx';\nimport Tag from '@/ui/labels/Tag.jsx';\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.CalcitaFilterChips)\nconst THEME_NAME = 'CalcitaFilterChips';\nconst ChipsRoot = piecePart(THEME_NAME, 'Root', Box);\nconst ChipsHeader = piecePart(THEME_NAME, 'Header', Stack);\nconst ChipsClearButton = piecePart(THEME_NAME, 'ClearButton', Button);\n\n/**\n * @param {object} props\n * @param {Array<object>} props.chipConfig lo que arma buildChipConfig\n * @param {object} props.filters\n * @param {(field: string, value: unknown) => void} props.onSetFilter\n * @param {() => void} props.onClearAll\n * @param {number} [props.quickActiveCount] accesos rápidos puestos que no tienen chip aquí\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\nexport default function FilterChips(props) {\n // lo que el proyecto puso en su tema (components.CalcitaFilterChips.defaultProps) y encima lo que llega aquí\n const {chipConfig, filters, onSetFilter, onClearAll, quickActiveCount = 0, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('table', texts);\n const chips = chipConfig\n .filter((chipDeclaration) => chipDeclaration.isActive(filters[chipDeclaration.key]))\n .flatMap((chipDeclaration) => chipDeclaration.chipsFor(filters[chipDeclaration.key], onSetFilter));\n\n const activeCount = chips.length + quickActiveCount;\n // guard clause: sin filtros no se pinta nada\n if (activeCount === 0) {\n return null;\n }\n\n return (\n <ChipsRoot ownSx={{mb: 1.5, minWidth: 0}}>\n <ChipsHeader direction=\"row\" spacing={1} ownSx={{px: 0.25, alignItems: 'center', justifyContent: 'space-between'}}>\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {t('chips.applied', {count: activeCount})}\n </Typography>\n <ChipsClearButton size=\"small\" color=\"error\" startIcon={<ClearAllIcon fontSize=\"small\" />} onClick={onClearAll}\n ownSx={{flexShrink: 0}}>\n {t('chips.clearAll')}\n </ChipsClearButton>\n </ChipsHeader>\n\n {chips.length > 0 && (\n <ScrollableRow>\n {chips.map(({id, label, onDelete}) => (\n <Tag key={id} label={label} color=\"primary\" onDelete={onDelete} sx={{flex: '0 0 auto'}} />\n ))}\n </ScrollableRow>\n )}\n </ChipsRoot>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;AA6BA,MAAM,aAAa;AACnB,MAAM,YAAY,UAAU,YAAY,QAAQ,GAAG;AACnD,MAAM,cAAc,UAAU,YAAY,UAAU,KAAK;AACzD,MAAM,mBAAmB,UAAU,YAAY,eAAe,MAAM;AAWpE,SAAwB,YAAY,OAAO;AAEvC,QAAM,EAAC,YAAY,SAAS,aAAa,YAAY,mBAAmB,GAAG,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AACpI,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,SAAS,KAAK;AAChD,QAAM,QAAQ,WACT,OAAO,CAAC,oBAAoB,gBAAgB,SAAS,QAAQ,gBAAgB,GAAG,CAAC,CAAC,EAClF,QAAQ,CAAC,oBAAoB,gBAAgB,SAAS,QAAQ,gBAAgB,GAAG,GAAG,WAAW,CAAC;AAErG,QAAM,cAAc,MAAM,SAAS;AAEnC,MAAI,gBAAgB,GAAG;AACnB,WAAO;AAAA,EACX;AAEA,SACI,qBAAC,aAAU,OAAO,EAAC,IAAI,KAAK,UAAU,KAClC,UAAA;AAAA,IAAA,qBAAC,aAAA,EAAY,WAAU,OAAM,SAAS,GAAG,OAAO,EAAC,IAAI,MAAM,YAAY,UAAU,gBAAgB,mBAC7F,UAAA;AAAA,MAAA,oBAAC,YAAA,EAAW,SAAQ,WAAU,OAAM,kBAAiB,QAAM,MACtD,UAAA,EAAE,iBAAiB,EAAC,OAAO,YAAA,CAAY,GAC5C;AAAA,MACA;AAAA,QAAC;AAAA,QAAA;AAAA,UAAiB,MAAK;AAAA,UAAQ,OAAM;AAAA,UAAQ,WAAW,oBAAC,cAAA,EAAa,UAAS,QAAA,CAAQ;AAAA,UAAI,SAAS;AAAA,UAC5F,OAAO,EAAC,YAAY,EAAA;AAAA,UACvB,YAAE,gBAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IACvB,GACJ;AAAA,IAEC,MAAM,SAAS,KACZ,oBAAC,eAAA,EACI,UAAA,MAAM,IAAI,CAAC,EAAC,IAAI,OAAO,SAAA,0BACnB,KAAA,EAAa,OAAc,OAAM,WAAU,UAAoB,IAAI,EAAC,MAAM,WAAA,KAAjE,EAA8E,CAC3F,EAAA,CACL;AAAA,EAAA,GAER;AAER;"}
1
+ {"version":3,"file":"FilterChips.js","sources":["../../src/DataTable/FilterChips.jsx"],"sourcesContent":["// Los filtros activos, a la vista y desarmables de a uno.\n//\n// Un filtro que solo se ve como un icono encendido en el encabezado se olvida: alguien filtra, se va al detalle,\n// regresa y lee el total como si fuera el de todo. Por eso los filtros puestos se dicen con todas sus letras arriba de\n// la tabla.\n//\n// Van en UNA tira que se desliza (ScrollableRow), no envolviéndose en renglones que empujan la tabla fuera de la\n// pantalla. La cuenta y \"Limpiar todo\" van en su propio renglón, arriba, para no tener que deslizar hasta encontrarlo.\n// Sin filtros activos no se pinta nada (ni el hueco).\n//\n// Los accesos rápidos cuentan aunque no tengan chip aquí: su propio chip encendido ya dice qué está elegido.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaFilterChips con defaultProps y\n// styleOverrides de sus partes: root, header, clearButton.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport ClearAllIcon from '@mui/icons-material/ClearAll';\n\nimport ScrollableRow from '@/ui/layout/ScrollableRow.jsx';\nimport Tag from '@/ui/labels/Tag.jsx';\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.CalcitaFilterChips)\nconst THEME_NAME = 'CalcitaFilterChips';\nconst ChipsRoot = piecePart(THEME_NAME, 'Root', Box);\nconst ChipsHeader = piecePart(THEME_NAME, 'Header', Stack);\nconst ChipsClearButton = piecePart(THEME_NAME, 'ClearButton', Button);\n\n/**\n * @param {object} props\n * @param {Array<object>} props.chipConfig lo que arma buildChipConfig\n * @param {object} props.filters\n * @param {(field: string, value: unknown) => void} props.onSetFilter\n * @param {() => void} props.onClearAll\n * @param {number} [props.quickActiveCount] accesos rápidos puestos que no tienen chip aquí\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\nfunction FilterChipsContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaFilterChips.defaultProps) y encima lo que llega aquí\n const {chipConfig, filters, onSetFilter, onClearAll, quickActiveCount = 0, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('table', texts);\n const chips = chipConfig\n .filter((chipDeclaration) => chipDeclaration.isActive(filters[chipDeclaration.key]))\n .flatMap((chipDeclaration) => chipDeclaration.chipsFor(filters[chipDeclaration.key], onSetFilter));\n\n const activeCount = chips.length + quickActiveCount;\n // guard clause: sin filtros no se pinta nada\n if (activeCount === 0) {\n return null;\n }\n\n return (\n <ChipsRoot ownSx={{mb: 1.5, minWidth: 0}}>\n <ChipsHeader direction=\"row\" spacing={1} ownSx={{px: 0.25, alignItems: 'center', justifyContent: 'space-between'}}>\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {t('chips.applied', {count: activeCount})}\n </Typography>\n <ChipsClearButton size=\"small\" color=\"error\" startIcon={<ClearAllIcon fontSize=\"small\" />} onClick={onClearAll}\n ownSx={{flexShrink: 0}}>\n {t('chips.clearAll')}\n </ChipsClearButton>\n </ChipsHeader>\n\n {chips.length > 0 && (\n <ScrollableRow>\n {chips.map(({id, label, onDelete}) => (\n <Tag key={id} label={label} color=\"primary\" onDelete={onDelete} sx={{flex: '0 0 auto'}} />\n ))}\n </ScrollableRow>\n )}\n </ChipsRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst FilterChips = withPieceSlots(FilterChipsContent, THEME_NAME);\nexport default FilterChips;\n"],"names":[],"mappings":";;;;;;;;;;;;AA6BA,MAAM,aAAa;AACnB,MAAM,YAAY,UAAU,YAAY,QAAQ,GAAG;AACnD,MAAM,cAAc,UAAU,YAAY,UAAU,KAAK;AACzD,MAAM,mBAAmB,UAAU,YAAY,eAAe,MAAM;AAWpE,SAAS,mBAAmB,OAAO;AAE/B,QAAM,EAAC,YAAY,SAAS,aAAa,YAAY,mBAAmB,GAAG,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AACpI,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,SAAS,KAAK;AAChD,QAAM,QAAQ,WACT,OAAO,CAAC,oBAAoB,gBAAgB,SAAS,QAAQ,gBAAgB,GAAG,CAAC,CAAC,EAClF,QAAQ,CAAC,oBAAoB,gBAAgB,SAAS,QAAQ,gBAAgB,GAAG,GAAG,WAAW,CAAC;AAErG,QAAM,cAAc,MAAM,SAAS;AAEnC,MAAI,gBAAgB,GAAG;AACnB,WAAO;AAAA,EACX;AAEA,SACI,qBAAC,aAAU,OAAO,EAAC,IAAI,KAAK,UAAU,KAClC,UAAA;AAAA,IAAA,qBAAC,aAAA,EAAY,WAAU,OAAM,SAAS,GAAG,OAAO,EAAC,IAAI,MAAM,YAAY,UAAU,gBAAgB,mBAC7F,UAAA;AAAA,MAAA,oBAAC,YAAA,EAAW,SAAQ,WAAU,OAAM,kBAAiB,QAAM,MACtD,UAAA,EAAE,iBAAiB,EAAC,OAAO,YAAA,CAAY,GAC5C;AAAA,MACA;AAAA,QAAC;AAAA,QAAA;AAAA,UAAiB,MAAK;AAAA,UAAQ,OAAM;AAAA,UAAQ,WAAW,oBAAC,cAAA,EAAa,UAAS,QAAA,CAAQ;AAAA,UAAI,SAAS;AAAA,UAC5F,OAAO,EAAC,YAAY,EAAA;AAAA,UACvB,YAAE,gBAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IACvB,GACJ;AAAA,IAEC,MAAM,SAAS,KACZ,oBAAC,eAAA,EACI,UAAA,MAAM,IAAI,CAAC,EAAC,IAAI,OAAO,SAAA,0BACnB,KAAA,EAAa,OAAc,OAAM,WAAU,UAAoB,IAAI,EAAC,MAAM,WAAA,KAAjE,EAA8E,CAC3F,EAAA,CACL;AAAA,EAAA,GAER;AAER;AAGA,MAAM,cAAc,eAAe,oBAAoB,UAAU;"}
@@ -8,7 +8,7 @@ import Typography from "@mui/material/Typography";
8
8
  import useMediaQuery from "@mui/material/useMediaQuery";
9
9
  import { List } from "react-window";
10
10
  import { pageNumbersOf, filterPages } from "./goToPageOptions.js";
11
- import { piecePart, usePieceProps } from "../theme/themePieces.js";
11
+ import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
12
12
  import { useFormatters } from "../toolkit/useFormatters.js";
13
13
  import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
14
14
  import { warnUnknownProps } from "../toolkit/unknownProps.js";
@@ -66,7 +66,7 @@ function PageListbox({ children: pageOptions, ref, pageCount, pageListRef, pageI
66
66
  pageOptions.length
67
67
  ) });
68
68
  }
69
- function GoToPage(props) {
69
+ function GoToPageContent(props) {
70
70
  const { page, pageCount, onChange, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
71
71
  warnUnknownProps(THEME_NAME, unknownProps);
72
72
  const { t } = useToolkitTranslation("table", texts);
@@ -120,6 +120,7 @@ function GoToPage(props) {
120
120
  /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", noWrap: true, children: t("goToPage.of", { count: pageCount, total: formatNumber(pageCount) }) })
121
121
  ] });
122
122
  }
123
+ const GoToPage = withPieceSlots(GoToPageContent, THEME_NAME);
123
124
  export {
124
125
  GoToPage as default
125
126
  };
@@ -1 +1 @@
1
- {"version":3,"file":"GoToPage.js","sources":["../../src/DataTable/GoToPage.jsx"],"sourcesContent":["// \"Ir a la página N\", como un selector con búsqueda.\n//\n// Con cientos de páginas, llegar a la 137 a punta de flechita no es navegar. Un Autocomplete dice las tres cosas sin\n// explicarlas: se abre y se ve la lista, se teclea y se filtra, se elige y ya.\n//\n// Cuatro detalles:\n// 1. la lista trae TODAS las páginas, pero pinta solo las que se ven (react-window, el «Virtualization» de la\n// documentación del Autocomplete de MUI): con decenas de miles de páginas abre igual de rápido y se desliza hasta la\n// última. Antes se cortaba en 100 y la 101 solo se alcanzaba tecleando;\n// 2. abre en la página donde está la tabla, no en la 1;\n// 3. filtra por PREFIJO primero (teclear 13 da 13, 130, 131...) y luego por \"contiene\" (goToPageOptions.js);\n// 4. con una sola página no se pinta: sería un control que no lleva a ningún lado.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaGoToPage con defaultProps y\n// styleOverrides de sus partes: root, field.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useMemo, useRef} from 'react';\nimport Autocomplete from '@mui/material/Autocomplete';\nimport Stack from '@mui/material/Stack';\nimport TextField from '@mui/material/TextField';\nimport Typography from '@mui/material/Typography';\nimport useMediaQuery from '@mui/material/useMediaQuery';\nimport {List} from 'react-window';\n\nimport {filterPages, pageNumbersOf} from '@/DataTable/goToPageOptions.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaGoToPage)\nconst THEME_NAME = 'CalcitaGoToPage';\nconst GoToRoot = piecePart(THEME_NAME, 'Root', Stack);\nconst GoToField = piecePart(THEME_NAME, 'Field', Autocomplete);\n\n// alto de cada página en la lista: el de una opción de MUI, 36 px desde «sm» y 48 en el teléfono (MUI les da 48 de alto\n// mínimo ahí). OJO: react-window acomoda cada renglón con este número; si no es el alto real, se encimarían\nconst OPTION_HEIGHT = 36;\nconst PHONE_OPTION_HEIGHT = 48;\n// lo más alto que crece la lista y el margen de arriba y abajo que MUI les da a sus listas\nconst LISTBOX_MAX_HEIGHT = 240;\nconst LISTBOX_PADDING = 8;\n// renglones de más que se pintan arriba y abajo de lo visible, para que no parpadee al deslizar\nconst OVERSCAN_ROWS = 5;\n\n/**\n * Un renglón de la lista: la opción que armó MUI (role=\"option\", resaltado, clic) acomodada donde dice react-window.\n *\n * @param {{index: number, style: object, pageOptions: Array<[object, number]>}} props\n */\nfunction PageOption({index, style, pageOptions}) {\n const [{key, ...optionProps}, pageNumber] = pageOptions[index];\n\n return (\n <Typography key={key} component=\"li\" {...optionProps} noWrap style={{...style, top: (style.top ?? 0) + LISTBOX_PADDING}}>\n {pageNumber}\n </Typography>\n );\n}\n\n/**\n * La lista del Autocomplete con react-window (el adaptador de la documentación de MUI).\n *\n * MUI le pasa sus props de lista (role=\"listbox\", id, eventos) y cada opción ya armada como [props, página] (ver\n * renderOption en GoToPage). Al abrir, se acomoda en la página elegida.\n *\n * @param {object} props\n * @param {Array<[object, number]>} props.children las opciones ya armadas por MUI\n * @param {import('react').Ref<HTMLDivElement>} [props.ref]\n * @param {number} props.pageCount cuántas páginas tiene la tabla: con todas en la lista, nadie ha tecleado\n * @param {{current: object|null}} props.pageListRef la API de react-window, para deslizar hasta una página\n * @param {{current: Map<number, number>}} props.pageIndexesRef se llena con página → lugar en la lista, para seguir con el\n * teclado a la resaltada\n * @param {string} [props.className]\n */\nfunction PageListbox({children: pageOptions, ref, pageCount, pageListRef, pageIndexesRef, className, style, ...listboxProps}) {\n const isWideScreen = useMediaQuery((theme) => theme.breakpoints.up('sm'), {noSsr: true});\n const optionHeight = isWideScreen ? OPTION_HEIGHT : PHONE_OPTION_HEIGHT;\n const listHeight = Math.min(pageOptions.length * optionHeight, LISTBOX_MAX_HEIGHT);\n\n // dónde quedó cada página en la lista filtrada\n useEffect(() => {\n const pageIndexes = new Map();\n pageOptions.forEach(([, pageNumber], pageIndex) => pageIndexes.set(pageNumber, pageIndex));\n pageIndexesRef.current = pageIndexes;\n }, [pageOptions, pageIndexesRef]);\n\n // al abrir sin teclear (la lista trae TODAS las páginas) se acomoda en la página elegida, la opción que MUI marca como\n // seleccionada; tecleando se queda arriba, en la primera que coincide.\n // OJO: no va en un useEffect al montar: en ese momento react-window todavía no guarda su contenedor y scrollToRow no\n // hace nada. Se hace cuando react-window entrega su API ya con el contenedor (listRef como función), una sola vez por\n // lista armada: después no pelea con quien desliza\n const placedListElementsRef = useRef(new WeakSet());\n const keepListApi = (listApi) => {\n pageListRef.current = listApi;\n const listElement = listApi?.element;\n if (!listElement || placedListElementsRef.current.has(listElement)) {\n return;\n }\n placedListElementsRef.current.add(listElement);\n if (pageOptions.length !== pageCount) {\n return;\n }\n const selectedIndex = pageOptions.findIndex(([optionProps]) => optionProps['aria-selected'] === true);\n if (selectedIndex >= 0) {\n listApi.scrollToRow({index: selectedIndex, align: 'center'});\n }\n };\n\n return (\n <div ref={ref} {...listboxProps}>\n <List\n // OJO: react-window le pone role=\"list\" a su contenedor; las opciones tienen que ser de la lista de MUI\n // (role=\"listbox\", el div de afuera) para que un lector de pantalla las anuncie como opciones del selector\n role=\"none\"\n className={className}\n listRef={keepListApi}\n // OJO: otra cantidad de páginas (al teclear) arma la lista de nuevo y la regresa arriba\n key={pageOptions.length}\n rowCount={pageOptions.length}\n rowHeight={optionHeight}\n rowComponent={PageOption}\n rowProps={{pageOptions}}\n style={{height: listHeight + 2 * LISTBOX_PADDING, width: '100%', boxSizing: 'border-box'}}\n overscanCount={OVERSCAN_ROWS}\n tagName=\"ul\"\n />\n </div>\n );\n}\n\n/**\n * @param {object} props\n * @param {number} props.page cuenta desde 0\n * @param {number} props.pageCount\n * @param {(page: number) => void} props.onChange\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\nexport default function GoToPage(props) {\n // lo que el proyecto puso en su tema (components.CalcitaGoToPage.defaultProps) y encima lo que llega aquí\n const {page, pageCount, onChange, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('table', texts);\n const {formatNumber} = useFormatters();\n // la persona cuenta desde 1 y el estado de la tabla desde 0: la conversión vive AQUÍ y en ningún otro lado\n const pageNumbers = useMemo(() => pageNumbersOf(pageCount), [pageCount]);\n const pageListRef = useRef(null);\n const pageIndexesRef = useRef(new Map());\n\n // guard clause: con una página no hay a dónde ir\n if (pageCount <= 1) {\n return null;\n }\n\n // con las flechas del teclado, la lista desliza hasta la página resaltada (react-window no la tiene pintada)\n const scrollToHighlightedPage = (event, highlightedPageNumber) => {\n const highlightedIndex = pageIndexesRef.current.get(highlightedPageNumber);\n if (highlightedIndex !== undefined) {\n pageListRef.current?.scrollToRow({index: highlightedIndex, align: 'auto'});\n }\n };\n\n return (\n <GoToRoot direction=\"row\" spacing={0.75} ownSx={{alignItems: 'baseline'}}>\n <Typography variant=\"body2\" color=\"text.secondary\" noWrap>{t('goToPage.page')}</Typography>\n <GoToField\n size=\"small\"\n disableClearable\n disableListWrap\n openOnFocus\n autoHighlight\n options={pageNumbers}\n filterOptions={filterPages}\n value={page + 1}\n isOptionEqualToValue={(option, selectedValue) => option === selectedValue}\n getOptionLabel={(option) => String(option)}\n // cada opción viaja armada a PageListbox, que pinta solo las que se ven\n renderOption={(optionProps, pageNumber) => [optionProps, pageNumber]}\n onHighlightChange={scrollToHighlightedPage}\n onChange={(event, selectedPageNumber) => {\n if (selectedPageNumber !== null && selectedPageNumber - 1 !== page) {\n onChange(selectedPageNumber - 1);\n }\n }}\n ownSx={{width: 78, '& .MuiAutocomplete-endAdornment': {right: 0}}}\n slotProps={{listbox: {component: PageListbox, pageCount, pageListRef, pageIndexesRef}}}\n renderInput={(params) => (\n <TextField {...params} variant=\"standard\"\n slotProps={{htmlInput: {...params.inputProps, inputMode: 'numeric', 'aria-label': t('goToPage.ariaLabel')}}} />\n )}\n />\n <Typography variant=\"body2\" color=\"text.secondary\" noWrap>\n {t('goToPage.of', {count: pageCount, total: formatNumber(pageCount)})}\n </Typography>\n </GoToRoot>\n );\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"GoToPage.js","sources":["../../src/DataTable/GoToPage.jsx"],"sourcesContent":["// \"Ir a la página N\", como un selector con búsqueda.\n//\n// Con cientos de páginas, llegar a la 137 a punta de flechita no es navegar. Un Autocomplete dice las tres cosas sin\n// explicarlas: se abre y se ve la lista, se teclea y se filtra, se elige y ya.\n//\n// Cuatro detalles:\n// 1. la lista trae TODAS las páginas, pero pinta solo las que se ven (react-window, el «Virtualization» de la\n// documentación del Autocomplete de MUI): con decenas de miles de páginas abre igual de rápido y se desliza hasta la\n// última. Antes se cortaba en 100 y la 101 solo se alcanzaba tecleando;\n// 2. abre en la página donde está la tabla, no en la 1;\n// 3. filtra por PREFIJO primero (teclear 13 da 13, 130, 131...) y luego por \"contiene\" (goToPageOptions.js);\n// 4. con una sola página no se pinta: sería un control que no lleva a ningún lado.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaGoToPage con defaultProps y\n// styleOverrides de sus partes: root, field.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useMemo, useRef} from 'react';\nimport Autocomplete from '@mui/material/Autocomplete';\nimport Stack from '@mui/material/Stack';\nimport TextField from '@mui/material/TextField';\nimport Typography from '@mui/material/Typography';\nimport useMediaQuery from '@mui/material/useMediaQuery';\nimport {List} from 'react-window';\n\nimport {filterPages, pageNumbersOf} from '@/DataTable/goToPageOptions.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaGoToPage)\nconst THEME_NAME = 'CalcitaGoToPage';\nconst GoToRoot = piecePart(THEME_NAME, 'Root', Stack);\nconst GoToField = piecePart(THEME_NAME, 'Field', Autocomplete);\n\n// alto de cada página en la lista: el de una opción de MUI, 36 px desde «sm» y 48 en el teléfono (MUI les da 48 de alto\n// mínimo ahí). OJO: react-window acomoda cada renglón con este número; si no es el alto real, se encimarían\nconst OPTION_HEIGHT = 36;\nconst PHONE_OPTION_HEIGHT = 48;\n// lo más alto que crece la lista y el margen de arriba y abajo que MUI les da a sus listas\nconst LISTBOX_MAX_HEIGHT = 240;\nconst LISTBOX_PADDING = 8;\n// renglones de más que se pintan arriba y abajo de lo visible, para que no parpadee al deslizar\nconst OVERSCAN_ROWS = 5;\n\n/**\n * Un renglón de la lista: la opción que armó MUI (role=\"option\", resaltado, clic) acomodada donde dice react-window.\n *\n * @param {{index: number, style: object, pageOptions: Array<[object, number]>}} props\n */\nfunction PageOption({index, style, pageOptions}) {\n const [{key, ...optionProps}, pageNumber] = pageOptions[index];\n\n return (\n <Typography key={key} component=\"li\" {...optionProps} noWrap style={{...style, top: (style.top ?? 0) + LISTBOX_PADDING}}>\n {pageNumber}\n </Typography>\n );\n}\n\n/**\n * La lista del Autocomplete con react-window (el adaptador de la documentación de MUI).\n *\n * MUI le pasa sus props de lista (role=\"listbox\", id, eventos) y cada opción ya armada como [props, página] (ver\n * renderOption en GoToPage). Al abrir, se acomoda en la página elegida.\n *\n * @param {object} props\n * @param {Array<[object, number]>} props.children las opciones ya armadas por MUI\n * @param {import('react').Ref<HTMLDivElement>} [props.ref]\n * @param {number} props.pageCount cuántas páginas tiene la tabla: con todas en la lista, nadie ha tecleado\n * @param {{current: object|null}} props.pageListRef la API de react-window, para deslizar hasta una página\n * @param {{current: Map<number, number>}} props.pageIndexesRef se llena con página → lugar en la lista, para seguir con el\n * teclado a la resaltada\n * @param {string} [props.className]\n */\nfunction PageListbox({children: pageOptions, ref, pageCount, pageListRef, pageIndexesRef, className, style, ...listboxProps}) {\n const isWideScreen = useMediaQuery((theme) => theme.breakpoints.up('sm'), {noSsr: true});\n const optionHeight = isWideScreen ? OPTION_HEIGHT : PHONE_OPTION_HEIGHT;\n const listHeight = Math.min(pageOptions.length * optionHeight, LISTBOX_MAX_HEIGHT);\n\n // dónde quedó cada página en la lista filtrada\n useEffect(() => {\n const pageIndexes = new Map();\n pageOptions.forEach(([, pageNumber], pageIndex) => pageIndexes.set(pageNumber, pageIndex));\n pageIndexesRef.current = pageIndexes;\n }, [pageOptions, pageIndexesRef]);\n\n // al abrir sin teclear (la lista trae TODAS las páginas) se acomoda en la página elegida, la opción que MUI marca como\n // seleccionada; tecleando se queda arriba, en la primera que coincide.\n // OJO: no va en un useEffect al montar: en ese momento react-window todavía no guarda su contenedor y scrollToRow no\n // hace nada. Se hace cuando react-window entrega su API ya con el contenedor (listRef como función), una sola vez por\n // lista armada: después no pelea con quien desliza\n const placedListElementsRef = useRef(new WeakSet());\n const keepListApi = (listApi) => {\n pageListRef.current = listApi;\n const listElement = listApi?.element;\n if (!listElement || placedListElementsRef.current.has(listElement)) {\n return;\n }\n placedListElementsRef.current.add(listElement);\n if (pageOptions.length !== pageCount) {\n return;\n }\n const selectedIndex = pageOptions.findIndex(([optionProps]) => optionProps['aria-selected'] === true);\n if (selectedIndex >= 0) {\n listApi.scrollToRow({index: selectedIndex, align: 'center'});\n }\n };\n\n return (\n <div ref={ref} {...listboxProps}>\n <List\n // OJO: react-window le pone role=\"list\" a su contenedor; las opciones tienen que ser de la lista de MUI\n // (role=\"listbox\", el div de afuera) para que un lector de pantalla las anuncie como opciones del selector\n role=\"none\"\n className={className}\n listRef={keepListApi}\n // OJO: otra cantidad de páginas (al teclear) arma la lista de nuevo y la regresa arriba\n key={pageOptions.length}\n rowCount={pageOptions.length}\n rowHeight={optionHeight}\n rowComponent={PageOption}\n rowProps={{pageOptions}}\n style={{height: listHeight + 2 * LISTBOX_PADDING, width: '100%', boxSizing: 'border-box'}}\n overscanCount={OVERSCAN_ROWS}\n tagName=\"ul\"\n />\n </div>\n );\n}\n\n/**\n * @param {object} props\n * @param {number} props.page cuenta desde 0\n * @param {number} props.pageCount\n * @param {(page: number) => void} props.onChange\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\nfunction GoToPageContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaGoToPage.defaultProps) y encima lo que llega aquí\n const {page, pageCount, onChange, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('table', texts);\n const {formatNumber} = useFormatters();\n // la persona cuenta desde 1 y el estado de la tabla desde 0: la conversión vive AQUÍ y en ningún otro lado\n const pageNumbers = useMemo(() => pageNumbersOf(pageCount), [pageCount]);\n const pageListRef = useRef(null);\n const pageIndexesRef = useRef(new Map());\n\n // guard clause: con una página no hay a dónde ir\n if (pageCount <= 1) {\n return null;\n }\n\n // con las flechas del teclado, la lista desliza hasta la página resaltada (react-window no la tiene pintada)\n const scrollToHighlightedPage = (event, highlightedPageNumber) => {\n const highlightedIndex = pageIndexesRef.current.get(highlightedPageNumber);\n if (highlightedIndex !== undefined) {\n pageListRef.current?.scrollToRow({index: highlightedIndex, align: 'auto'});\n }\n };\n\n return (\n <GoToRoot direction=\"row\" spacing={0.75} ownSx={{alignItems: 'baseline'}}>\n <Typography variant=\"body2\" color=\"text.secondary\" noWrap>{t('goToPage.page')}</Typography>\n <GoToField\n size=\"small\"\n disableClearable\n disableListWrap\n openOnFocus\n autoHighlight\n options={pageNumbers}\n filterOptions={filterPages}\n value={page + 1}\n isOptionEqualToValue={(option, selectedValue) => option === selectedValue}\n getOptionLabel={(option) => String(option)}\n // cada opción viaja armada a PageListbox, que pinta solo las que se ven\n renderOption={(optionProps, pageNumber) => [optionProps, pageNumber]}\n onHighlightChange={scrollToHighlightedPage}\n onChange={(event, selectedPageNumber) => {\n if (selectedPageNumber !== null && selectedPageNumber - 1 !== page) {\n onChange(selectedPageNumber - 1);\n }\n }}\n ownSx={{width: 78, '& .MuiAutocomplete-endAdornment': {right: 0}}}\n slotProps={{listbox: {component: PageListbox, pageCount, pageListRef, pageIndexesRef}}}\n renderInput={(params) => (\n <TextField {...params} variant=\"standard\"\n slotProps={{htmlInput: {...params.inputProps, inputMode: 'numeric', 'aria-label': t('goToPage.ariaLabel')}}} />\n )}\n />\n <Typography variant=\"body2\" color=\"text.secondary\" noWrap>\n {t('goToPage.of', {count: pageCount, total: formatNumber(pageCount)})}\n </Typography>\n </GoToRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst GoToPage = withPieceSlots(GoToPageContent, THEME_NAME);\nexport default GoToPage;\n"],"names":[],"mappings":"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"}
@@ -21,6 +21,11 @@ import GoToPage from "./GoToPage.js";
21
21
  import { TableFilterContext } from "./filterContext.js";
22
22
  import { EMPTY_ROW_SELECTION, checkedIdsOf, rowSelectionOf, canSelectAllMatching, selectionAfterCheck } from "./rowSelection.js";
23
23
  import { tableMachine, buildTableActors } from "./tableMachine.js";
24
+ import { fixedColumnOffsetsOf, fixedFieldsOf } from "./fixedColumns.js";
25
+ import TableCardsView, { TableViewToggle } from "./TableCardsView.js";
26
+ import { COLUMN_STACKED_KEY } from "./columns.js";
27
+ import { useTableView, TABLE_VIEW } from "./useTableView.js";
28
+ import { createLogger } from "../observability/logger.js";
24
29
  import { useDebouncedFilter } from "./useDebouncedFilter.js";
25
30
  import { useTableState, isFilterActive, FILTER_KINDS } from "./useTableState.js";
26
31
  import BarSearch from "../appShell/BarSearch.js";
@@ -31,7 +36,7 @@ import { useFormatters } from "../toolkit/useFormatters.js";
31
36
  import { materialBackgroundOf } from "../theme/glassSurface.js";
32
37
  import QuickFilters from "../ui/filters/QuickFilters.js";
33
38
  import Tag from "../ui/labels/Tag.js";
34
- import { piecePart, usePieceProps } from "../theme/themePieces.js";
39
+ import { piecePart, withPieceSlots, usePieceProps, sxListOf } from "../theme/themePieces.js";
35
40
  import { warnUnknownProps } from "../toolkit/unknownProps.js";
36
41
  const THEME_NAME = "CalcitaServerTable";
37
42
  const TableToolbar = piecePart(THEME_NAME, "Toolbar", Stack);
@@ -59,40 +64,48 @@ const COLUMN_HEADER_HEIGHT_PIXELS = 39;
59
64
  const FOOTER_HEIGHT_PIXELS = 52;
60
65
  const GRID_BORDER_PIXELS = 2;
61
66
  const HEIGHT_SLACK_PIXELS = 2;
67
+ const AUTO_ROW_HEIGHT = "auto";
68
+ const CELL_LINE_HEIGHT = "inherit";
69
+ const log = createLogger("table");
70
+ const warnedFixedColumns = /* @__PURE__ */ new Set();
62
71
  const DATA_GRID_DENSITY = "compact";
63
72
  const STRIPED_ROW_CLASS = "server-table-row--striped";
64
73
  const FIXED_CELL_Z_INDEX = 30;
65
74
  const FIXED_HEADER_Z_INDEX = 40;
66
75
  const CHECKBOX_COLUMN_WIDTH_PIXELS = GRID_CHECKBOX_SELECTION_COL_DEF.width;
67
- function fixedColumnSxOf(theme, field, { withCheckboxColumn = false } = {}) {
76
+ function fixedColumnSxOf(theme, fixedColumns, { withCheckboxColumn = false } = {}) {
68
77
  const { palette } = theme.vars ?? theme;
69
78
  const paper = palette.background.paper;
70
79
  const divider = `1px solid ${palette.divider}`;
71
- const ownBandHeader = `.MuiDataGrid-columnHeader[data-fields="|-${field}-|"]`;
72
80
  const isMaterialContent = Boolean(theme.toolkit?.glass?.surfaces);
73
81
  const stickyBackground = { backgroundColor: "inherit", ...isMaterialContent ? materialBackgroundOf(theme, { thick: true }) : { backgroundImage: `linear-gradient(${paper}, ${paper})` } };
74
82
  const headerBackground = isMaterialContent ? materialBackgroundOf(theme, { thick: true }) : { backgroundColor: paper };
75
83
  const rowColorLayer = { content: '""', position: "absolute", inset: 0, zIndex: -1, backgroundColor: "inherit" };
76
- const fixedLeft = withCheckboxColumn ? CHECKBOX_COLUMN_WIDTH_PIXELS : 0;
77
84
  const checkboxCell = `.MuiDataGrid-cell[data-field="${GRID_CHECKBOX_SELECTION_FIELD}"]`;
78
85
  const checkboxHeader = `.MuiDataGrid-columnHeader[data-field="${GRID_CHECKBOX_SELECTION_FIELD}"]`;
79
- return {
80
- "& :where(.MuiDataGrid-row)": { backgroundColor: isMaterialContent ? "transparent" : paper },
81
- [`& .MuiDataGrid-cell[data-field="${field}"]`]: {
86
+ const columnRules = {};
87
+ for (const { field, left, isLast } of fixedColumns) {
88
+ const ownBandHeader = `.MuiDataGrid-columnHeader[data-fields="|-${field}-|"]`;
89
+ const edge = isLast ? { borderRight: divider } : {};
90
+ columnRules[`& .MuiDataGrid-cell[data-field="${field}"]`] = {
82
91
  position: "sticky",
83
- left: fixedLeft,
92
+ left,
84
93
  zIndex: FIXED_CELL_Z_INDEX,
85
- borderRight: divider,
94
+ ...edge,
86
95
  ...stickyBackground,
87
96
  "&::before": rowColorLayer
88
- },
89
- [`& :where(.MuiDataGrid-columnHeader[data-field="${field}"], ${ownBandHeader})`]: headerBackground,
90
- [`& .MuiDataGrid-columnHeader[data-field="${field}"], & ${ownBandHeader}`]: {
97
+ };
98
+ columnRules[`& :where(.MuiDataGrid-columnHeader[data-field="${field}"], ${ownBandHeader})`] = headerBackground;
99
+ columnRules[`& .MuiDataGrid-columnHeader[data-field="${field}"], & ${ownBandHeader}`] = {
91
100
  position: "sticky",
92
- left: fixedLeft,
101
+ left,
93
102
  zIndex: FIXED_HEADER_Z_INDEX,
94
- borderRight: divider
95
- },
103
+ ...edge
104
+ };
105
+ }
106
+ return {
107
+ "& :where(.MuiDataGrid-row)": { backgroundColor: isMaterialContent ? "transparent" : paper },
108
+ ...columnRules,
96
109
  ...withCheckboxColumn && {
97
110
  [`& ${checkboxCell}`]: { position: "sticky", left: 0, zIndex: FIXED_CELL_Z_INDEX, ...stickyBackground, "&::before": rowColorLayer },
98
111
  [`& :where(${checkboxHeader})`]: headerBackground,
@@ -146,7 +159,7 @@ function QuickFilterRow({ quickFilter, facets, total, filters, isMultiple, setFi
146
159
  }
147
160
  );
148
161
  }
149
- function ServerTable(props) {
162
+ function ServerTableContent(props) {
150
163
  const {
151
164
  fetchPage,
152
165
  queryKey,
@@ -191,6 +204,12 @@ function ServerTable(props) {
191
204
  onLoaded,
192
205
  onLoadError,
193
206
  gridProps,
207
+ renderCard,
208
+ view,
209
+ defaultView,
210
+ onViewChange,
211
+ showViewToggle,
212
+ cardSkeleton,
194
213
  texts,
195
214
  ...unknownProps
196
215
  } = usePieceProps(props, THEME_NAME);
@@ -200,6 +219,10 @@ function ServerTable(props) {
200
219
  const theme = useTheme();
201
220
  const tableState = useTableState({ prefix, filterDefaults, filterKinds, defaultPageSize });
202
221
  const { filters, sortOrders, page, pageSize } = tableState;
222
+ const tableView = useTableView({ prefix, view, defaultView, onViewChange });
223
+ const showsCards = Boolean(renderCard) && tableView.view === TABLE_VIEW.cards;
224
+ const showsViewToggle = Boolean(renderCard) && (showViewToggle ?? true);
225
+ const rowHeightOf = getRowHeight ?? (columns.some((column) => column[COLUMN_STACKED_KEY]) ? () => AUTO_ROW_HEIGHT : void 0);
203
226
  const [searchDraft, setSearchDraft] = useDebouncedFilter(
204
227
  searchField ? filters[searchField] : "",
205
228
  (value) => searchField && tableState.setFilter(searchField, value)
@@ -312,10 +335,29 @@ function ServerTable(props) {
312
335
  placeholderRowCount = isLoading ? Math.min(pageSize, 8) : 3;
313
336
  }
314
337
  let rowsHeight = placeholderRowCount * ROW_HEIGHT_PIXELS;
338
+ let hasAutoHeightRows = false;
315
339
  for (const row of visibleRows) {
316
- const requestedRowHeight = getRowHeight?.({ id: getRowId ? getRowId(row) : row.id, model: row, densityFactor: COMPACT_DENSITY_FACTOR });
340
+ const rowParams = { id: getRowId ? getRowId(row) : row.id, model: row, densityFactor: COMPACT_DENSITY_FACTOR };
341
+ const requestedRowHeight = rowHeightOf?.(rowParams);
342
+ if (requestedRowHeight === AUTO_ROW_HEIGHT) {
343
+ hasAutoHeightRows = true;
344
+ const estimatedRowHeight = gridProps?.getEstimatedRowHeight?.(rowParams);
345
+ rowsHeight += typeof estimatedRowHeight === "number" ? estimatedRowHeight : ROW_HEIGHT_PIXELS;
346
+ continue;
347
+ }
317
348
  rowsHeight += typeof requestedRowHeight === "number" ? requestedRowHeight : ROW_HEIGHT_PIXELS;
318
349
  }
350
+ const measuresItself = hasAutoHeightRows && !maxGridHeight;
351
+ const fixedColumns = fixedColumnOffsetsOf(fixedFieldsOf(fixedColumn), columns, { startLeft: isSelectable ? CHECKBOX_COLUMN_WIDTH_PIXELS : 0 });
352
+ const fixedWithUnknownWidth = fixedColumns.filter((fixed) => fixed.hasUnknownWidth).map((fixed) => fixed.field).join(",");
353
+ useEffect(() => {
354
+ for (const field of fixedWithUnknownWidth ? fixedWithUnknownWidth.split(",") : []) {
355
+ if (!warnedFixedColumns.has(field)) {
356
+ warnedFixedColumns.add(field);
357
+ log.warn(`La columna fija «${field}» no es la última y no trae un width fijo: la siguiente se corre su minWidth y podría encimarse. Póngale width.`);
358
+ }
359
+ }
360
+ }, [fixedWithUnknownWidth]);
319
361
  const headerHeight = columnGroupingModel ? 2 * COLUMN_HEADER_HEIGHT_PIXELS : COLUMN_HEADER_HEIGHT_PIXELS;
320
362
  const isFooterHidden = hideFooterWhenAllRowsFit && page === 0 && total <= pageSize;
321
363
  const footerHeight = isFooterHidden ? 0 : FOOTER_HEIGHT_PIXELS + GRID_BORDER_PIXELS;
@@ -353,7 +395,8 @@ function ServerTable(props) {
353
395
  ] }),
354
396
  toolbarExtra
355
397
  ] })
356
- ) })
398
+ ) }),
399
+ showsViewToggle && /* @__PURE__ */ jsx(TableViewToggle, { view: tableView.view, onChange: tableView.setView })
357
400
  ] }),
358
401
  beforeQuickFilters,
359
402
  quickFilters.map((quickFilter) => /* @__PURE__ */ jsx(
@@ -410,7 +453,24 @@ function ServerTable(props) {
410
453
  children: error.message ?? t("error.generic")
411
454
  }
412
455
  ),
413
- /* @__PURE__ */ jsx(TableCard, { variant: "outlined", ownSx: { width: "100%", minWidth: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx(
456
+ showsCards && /* @__PURE__ */ jsx(
457
+ TableCardsView,
458
+ {
459
+ rows: visibleRows,
460
+ renderCard,
461
+ rowIdOf: (row) => getRowId ? getRowId(row) : row.id,
462
+ isLoading,
463
+ page,
464
+ pageCount: Math.ceil(total / pageSize) || 1,
465
+ onPageChange: tableState.setPage,
466
+ hasActiveFilters,
467
+ emptyLabel,
468
+ onClearFilters: tableState.clearAll,
469
+ skeleton: cardSkeleton,
470
+ ariaLabel
471
+ }
472
+ ),
473
+ !showsCards && /* @__PURE__ */ jsx(TableCard, { variant: "outlined", ownSx: { width: "100%", minWidth: 0, overflow: "hidden" }, children: /* @__PURE__ */ jsx(
414
474
  TableGrid,
415
475
  {
416
476
  ...gridProps,
@@ -422,7 +482,7 @@ function ServerTable(props) {
422
482
  getRowClassName?.(params),
423
483
  striped && params.indexRelativeToCurrentPage % 2 === 1 ? STRIPED_ROW_CLASS : ""
424
484
  ].filter(Boolean).join(" "),
425
- getRowHeight,
485
+ getRowHeight: rowHeightOf,
426
486
  "aria-label": ariaLabel,
427
487
  nonce: readCspNonce(),
428
488
  loading: isLoading,
@@ -449,7 +509,7 @@ function ServerTable(props) {
449
509
  keepNonExistentRowsSelected: isSelectable,
450
510
  disableRowSelectionExcludeModel: true,
451
511
  hideFooterSelectedRowCount: true,
452
- disableVirtualization: Boolean(fixedColumn),
512
+ disableVirtualization: fixedColumns.length > 0,
453
513
  density: DATA_GRID_DENSITY,
454
514
  localeText: { ...gridText, noRowsLabel: emptyLabel ?? t("empty.default") },
455
515
  slotProps: {
@@ -472,22 +532,29 @@ function ServerTable(props) {
472
532
  // IMPORTANTE: el alto va en la raíz del DataGrid y no en la caja de afuera: las variables
473
533
  // --DataGrid-hasScrollX y --DataGrid-scrollbarSize solo existen en la raíz. Cuando las columnas no
474
534
  // caben (historial a 390 px) la barra horizontal ocupa su alto dentro de la tabla y, sin sumarlo, los
475
- // renglones se desplazaban 13 px por dentro. Con barras superpuestas (teléfono, trackpad) mide 0
476
- height: `calc(${gridHeight}px + var(--DataGrid-hasScrollX, 0) * var(--DataGrid-scrollbarSize, 0px))`,
535
+ // renglones se desplazaban 13 px por dentro. Con barras superpuestas (teléfono, trackpad) mide 0.
536
+ // Con renglones 'auto' el DataGrid se mide solo y aquí no se le pone alto
537
+ ...!measuresItself && { height: `calc(${gridHeight}px + var(--DataGrid-hasScrollX, 0) * var(--DataGrid-scrollbarSize, 0px))` },
477
538
  border: 0,
478
- // todo centrado verticalmente: el texto suelto se pegaba arriba y los chips quedaban a media altura
479
- "& .MuiDataGrid-cell": { display: "flex", alignItems: "center" },
539
+ // todo centrado verticalmente: el texto suelto se pegaba arriba y los chips quedaban a media altura.
540
+ // OJO, trampa pagada: el DataGrid le da a cada celda una altura de línea IGUAL al alto del renglón
541
+ // (para centrar una sola línea de texto). En un renglón alto (100 px) todo texto que no traiga la
542
+ // suya quedaba en una línea de 99 px: a media celda o hasta abajo, y lo que iba debajo se salía y se
543
+ // cortaba. Las celdas ya se centran con flex, así que la altura de línea vuelve a la del texto
544
+ "& .MuiDataGrid-cell": { display: "flex", alignItems: "center", lineHeight: CELL_LINE_HEIGHT },
480
545
  "& .MuiDataGrid-columnHeader": { alignItems: "center" },
481
546
  // cebra: el color del hover del tema
482
547
  [`& .${STRIPED_ROW_CLASS}`]: { bgcolor: "action.hover" },
483
- [`& .${STRIPED_ROW_CLASS}:hover`]: { bgcolor: "action.selected" },
484
- ...gridSx
485
- }, (gridTheme) => fixedColumn ? fixedColumnSxOf(gridTheme, fixedColumn, { withCheckboxColumn: isSelectable }) : {}]
548
+ [`& .${STRIPED_ROW_CLASS}:hover`]: { bgcolor: "action.selected" }
549
+ }, (gridTheme) => fixedColumns.length > 0 ? fixedColumnSxOf(gridTheme, fixedColumns, { withCheckboxColumn: isSelectable }) : {}],
550
+ sx: [...sxListOf(gridProps?.sx), ...sxListOf(gridSx)],
551
+ autoHeight: measuresItself
486
552
  }
487
553
  ) }),
488
554
  footer?.({ total, capped })
489
555
  ] }) });
490
556
  }
557
+ const ServerTable = withPieceSlots(ServerTableContent, THEME_NAME);
491
558
  export {
492
559
  SELECTION_PHONE_LAYOUT,
493
560
  ServerTable as default