@stackcraftmx/calcita 0.0.0-stage → 0.25.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 (900) hide show
  1. package/LICENSE +110 -0
  2. package/README.md +700 -2
  3. package/cli/askQuestions.js +63 -0
  4. package/cli/calcita.js +150 -0
  5. package/cli/makeComponent.js +50 -0
  6. package/cli/makeForm.js +68 -0
  7. package/cli/makeModule.js +78 -0
  8. package/cli/makePage.js +62 -0
  9. package/cli/names.js +64 -0
  10. package/cli/newProject.js +103 -0
  11. package/cli/packageVersions.js +38 -0
  12. package/cli/projectAnswers.js +145 -0
  13. package/cli/projectConfig.js +38 -0
  14. package/cli/projectFiles.js +128 -0
  15. package/cli/screenLabels.js +41 -0
  16. package/cli/templateFiles.js +186 -0
  17. package/cli/templates/component/core/__ComponentName__.jsx.tpl +23 -0
  18. package/cli/templates/component/module/__ComponentName__.jsx.tpl +21 -0
  19. package/cli/templates/form/formik/__FormName__.jsx.tpl +50 -0
  20. package/cli/templates/form/hookForm/__FormName__.jsx.tpl +53 -0
  21. package/cli/templates/form/shared/__formName__Schema.js.tpl +20 -0
  22. package/cli/templates/form/shared/__formName__Texts.js.tpl +6 -0
  23. package/cli/templates/module/__Name__Page.jsx.tpl +75 -0
  24. package/cli/templates/module/__name__Api.js.tpl +39 -0
  25. package/cli/templates/module/__name__Texts.js.tpl +27 -0
  26. package/cli/templates/module/menu.js.tpl +21 -0
  27. package/cli/templates/module/routes.js.tpl +7 -0
  28. package/cli/templates/moduleServer/__name__Server.js.tpl +68 -0
  29. package/cli/templates/page/__PageName__Page.jsx.tpl +22 -0
  30. package/cli/templates/page/__pageName__PageTexts.js.tpl +23 -0
  31. package/cli/templates/project/README.md.tpl +83 -0
  32. package/cli/templates/project/dot-gitignore.tpl +11 -0
  33. package/cli/templates/project/index.html.tpl +20 -0
  34. package/cli/templates/project/jsconfig.json.tpl +16 -0
  35. package/cli/templates/project/pnpm-workspace.yaml.tpl +5 -0
  36. package/cli/templates/project/public/favicon.svg +1 -0
  37. package/cli/templates/project/public/icons/apple-touch-icon.png +0 -0
  38. package/cli/templates/project/public/icons/icon-192.png +0 -0
  39. package/cli/templates/project/public/icons/icon-512-maskable.png +0 -0
  40. package/cli/templates/project/public/icons/icon-512.png +0 -0
  41. package/cli/templates/project/public/manifest.webmanifest.tpl +17 -0
  42. package/cli/templates/project/src/app/AppProviders.jsx.tpl +107 -0
  43. package/cli/templates/project/src/app/AppShell.jsx.tpl +87 -0
  44. package/cli/templates/project/src/app/appRouter.jsx.tpl +51 -0
  45. package/cli/templates/project/src/app/appSettings.js.tpl +27 -0
  46. package/cli/templates/project/src/app/appTexts.js.tpl +15 -0
  47. package/cli/templates/project/src/app/combineTexts.js.tpl +31 -0
  48. package/cli/templates/project/src/app/i18n.js.tpl +19 -0
  49. package/cli/templates/project/src/app/shellTexts.js.tpl +16 -0
  50. package/cli/templates/project/src/core/AppLogo.jsx.tpl +14 -0
  51. package/cli/templates/project/src/core/accountConnector.js.tpl +36 -0
  52. package/cli/templates/project/src/core/apiClient.js.tpl +15 -0
  53. package/cli/templates/project/src/core/appPaths.js.tpl +11 -0
  54. package/cli/templates/project/src/core/index.js.tpl +9 -0
  55. package/cli/templates/project/src/core/publicPaths.js.tpl +24 -0
  56. package/cli/templates/project/src/fakeServer/networkDelay.js.tpl +40 -0
  57. package/cli/templates/project/src/fakeServer/serverText.js.tpl +20 -0
  58. package/cli/templates/project/src/main.jsx.tpl +24 -0
  59. package/cli/templates/project/src/modules/auth/ForgotPasswordPage.jsx.tpl +14 -0
  60. package/cli/templates/project/src/modules/auth/ResetPasswordPage.jsx.tpl +15 -0
  61. package/cli/templates/project/src/modules/auth/SignInPage.jsx.tpl +29 -0
  62. package/cli/templates/project/src/modules/auth/authTexts.js.tpl +6 -0
  63. package/cli/templates/project/src/modules/auth/routes.js.tpl +11 -0
  64. package/cli/templates/project/src/modules/home/HomePage.jsx.tpl +38 -0
  65. package/cli/templates/project/src/modules/home/homeTexts.js.tpl +29 -0
  66. package/cli/templates/project/src/modules/home/menu.js.tpl +17 -0
  67. package/cli/templates/project/src/modules/home/routes.js.tpl +4 -0
  68. package/cli/templates/project/src/modules/profile/ProfilePage.jsx.tpl +13 -0
  69. package/cli/templates/project/src/modules/profile/routes.js.tpl +6 -0
  70. package/cli/templates/project/vite.config.js.tpl +53 -0
  71. package/dist/DataTable/AuditTrailDialog.js +40 -0
  72. package/dist/DataTable/AuditTrailDialog.js.map +1 -0
  73. package/dist/DataTable/AuditTrailTable.js +89 -0
  74. package/dist/DataTable/AuditTrailTable.js.map +1 -0
  75. package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js +71 -0
  76. package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js.map +1 -0
  77. package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js +51 -0
  78. package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js.map +1 -0
  79. package/dist/DataTable/ColumnFilters/SortableFilterHeader.js +54 -0
  80. package/dist/DataTable/ColumnFilters/SortableFilterHeader.js.map +1 -0
  81. package/dist/DataTable/ColumnFilters/TextColumnFilter.js +24 -0
  82. package/dist/DataTable/ColumnFilters/TextColumnFilter.js.map +1 -0
  83. package/dist/DataTable/EmptyState.js +22 -0
  84. package/dist/DataTable/EmptyState.js.map +1 -0
  85. package/dist/DataTable/FilterChips.js +39 -0
  86. package/dist/DataTable/FilterChips.js.map +1 -0
  87. package/dist/DataTable/GoToPage.js +63 -0
  88. package/dist/DataTable/GoToPage.js.map +1 -0
  89. package/dist/DataTable/ServerTable.js +477 -0
  90. package/dist/DataTable/ServerTable.js.map +1 -0
  91. package/dist/DataTable/buildChipConfig.js +27 -0
  92. package/dist/DataTable/buildChipConfig.js.map +1 -0
  93. package/dist/DataTable/columns.js +122 -0
  94. package/dist/DataTable/columns.js.map +1 -0
  95. package/dist/DataTable/filterContext.js +15 -0
  96. package/dist/DataTable/filterContext.js.map +1 -0
  97. package/dist/DataTable/rowSelection.js +61 -0
  98. package/dist/DataTable/rowSelection.js.map +1 -0
  99. package/dist/DataTable/serverTableParams.js +19 -0
  100. package/dist/DataTable/serverTableParams.js.map +1 -0
  101. package/dist/DataTable/tableMachine.js +87 -0
  102. package/dist/DataTable/tableMachine.js.map +1 -0
  103. package/dist/DataTable/useDebouncedFilter.js +29 -0
  104. package/dist/DataTable/useDebouncedFilter.js.map +1 -0
  105. package/dist/DataTable/useTableState.js +132 -0
  106. package/dist/DataTable/useTableState.js.map +1 -0
  107. package/dist/access/Can.js +9 -0
  108. package/dist/access/Can.js.map +1 -0
  109. package/dist/access/PermissionMatrix.js +84 -0
  110. package/dist/access/PermissionMatrix.js.map +1 -0
  111. package/dist/access/RequireAccess.js +14 -0
  112. package/dist/access/RequireAccess.js.map +1 -0
  113. package/dist/access/accessRules.js +49 -0
  114. package/dist/access/accessRules.js.map +1 -0
  115. package/dist/access/permissionGroups.js +43 -0
  116. package/dist/access/permissionGroups.js.map +1 -0
  117. package/dist/access/useCan.js +12 -0
  118. package/dist/access/useCan.js.map +1 -0
  119. package/dist/account/AccountProvider.js +58 -0
  120. package/dist/account/AccountProvider.js.map +1 -0
  121. package/dist/account/AccountSecuritySection.js +81 -0
  122. package/dist/account/AccountSecuritySection.js.map +1 -0
  123. package/dist/account/DemoTotpCodeButton.js +26 -0
  124. package/dist/account/DemoTotpCodeButton.js.map +1 -0
  125. package/dist/account/ForgotPasswordScreen.js +27 -0
  126. package/dist/account/ForgotPasswordScreen.js.map +1 -0
  127. package/dist/account/ProfileScreen.js +134 -0
  128. package/dist/account/ProfileScreen.js.map +1 -0
  129. package/dist/account/ResetPasswordScreen.js +58 -0
  130. package/dist/account/ResetPasswordScreen.js.map +1 -0
  131. package/dist/account/SignInScreen.js +102 -0
  132. package/dist/account/SignInScreen.js.map +1 -0
  133. package/dist/account/accountConnector.js +31 -0
  134. package/dist/account/accountConnector.js.map +1 -0
  135. package/dist/account/demo/createDemoAccountConnector.js +368 -0
  136. package/dist/account/demo/createDemoAccountConnector.js.map +1 -0
  137. package/dist/account/demo/totp.js +61 -0
  138. package/dist/account/demo/totp.js.map +1 -0
  139. package/dist/account/restAccountConnector.js +118 -0
  140. package/dist/account/restAccountConnector.js.map +1 -0
  141. package/dist/account-demo.js +12 -0
  142. package/dist/account-demo.js.map +1 -0
  143. package/dist/account.js +25 -0
  144. package/dist/account.js.map +1 -0
  145. package/dist/adapters/i18next.js +7 -0
  146. package/dist/adapters/i18next.js.map +1 -0
  147. package/dist/adapters/nextNavigation.js +36 -0
  148. package/dist/adapters/nextNavigation.js.map +1 -0
  149. package/dist/adapters/reactRouter.js +7 -0
  150. package/dist/adapters/reactRouter.js.map +1 -0
  151. package/dist/adapters/reactRouterRoutes.js +49 -0
  152. package/dist/adapters/reactRouterRoutes.js.map +1 -0
  153. package/dist/api/ApiError.js +58 -0
  154. package/dist/api/ApiError.js.map +1 -0
  155. package/dist/api/createApiClient.js +256 -0
  156. package/dist/api/createApiClient.js.map +1 -0
  157. package/dist/api/staleChunks.js +47 -0
  158. package/dist/api/staleChunks.js.map +1 -0
  159. package/dist/appShell/AccountMenu.js +86 -0
  160. package/dist/appShell/AccountMenu.js.map +1 -0
  161. package/dist/appShell/AppLayout.js +513 -0
  162. package/dist/appShell/AppLayout.js.map +1 -0
  163. package/dist/appShell/AppearanceSettings.js +116 -0
  164. package/dist/appShell/AppearanceSettings.js.map +1 -0
  165. package/dist/appShell/AuthLayout.js +46 -0
  166. package/dist/appShell/AuthLayout.js.map +1 -0
  167. package/dist/appShell/BarActionButton.js +31 -0
  168. package/dist/appShell/BarActionButton.js.map +1 -0
  169. package/dist/appShell/BarActions.js +105 -0
  170. package/dist/appShell/BarActions.js.map +1 -0
  171. package/dist/appShell/BarCapsule.js +50 -0
  172. package/dist/appShell/BarCapsule.js.map +1 -0
  173. package/dist/appShell/BarSearch.js +92 -0
  174. package/dist/appShell/BarSearch.js.map +1 -0
  175. package/dist/appShell/HeaderTools.js +53 -0
  176. package/dist/appShell/HeaderTools.js.map +1 -0
  177. package/dist/appShell/MobileTabBar.js +348 -0
  178. package/dist/appShell/MobileTabBar.js.map +1 -0
  179. package/dist/appShell/SettingsMenu.js +41 -0
  180. package/dist/appShell/SettingsMenu.js.map +1 -0
  181. package/dist/appShell/SideMenu.js +217 -0
  182. package/dist/appShell/SideMenu.js.map +1 -0
  183. package/dist/appShell/SideMenuEntry.js +140 -0
  184. package/dist/appShell/SideMenuEntry.js.map +1 -0
  185. package/dist/appShell/SubmenuActionsMenu.js +71 -0
  186. package/dist/appShell/SubmenuActionsMenu.js.map +1 -0
  187. package/dist/appShell/TabBarEditor.js +55 -0
  188. package/dist/appShell/TabBarEditor.js.map +1 -0
  189. package/dist/appShell/TopMenu.js +80 -0
  190. package/dist/appShell/TopMenu.js.map +1 -0
  191. package/dist/appShell/appMenuContext.js +11 -0
  192. package/dist/appShell/appMenuContext.js.map +1 -0
  193. package/dist/appShell/barActionsSlot.js +26 -0
  194. package/dist/appShell/barActionsSlot.js.map +1 -0
  195. package/dist/appShell/barMenuPlacement.js +33 -0
  196. package/dist/appShell/barMenuPlacement.js.map +1 -0
  197. package/dist/appShell/menuItemText.js +33 -0
  198. package/dist/appShell/menuItemText.js.map +1 -0
  199. package/dist/appShell/pageTitle.js +45 -0
  200. package/dist/appShell/pageTitle.js.map +1 -0
  201. package/dist/appShell/shellSizes.js +40 -0
  202. package/dist/appShell/shellSizes.js.map +1 -0
  203. package/dist/appShell/tabBarRule.js +12 -0
  204. package/dist/appShell/tabBarRule.js.map +1 -0
  205. package/dist/appShell/tabBarScroll.js +23 -0
  206. package/dist/appShell/tabBarScroll.js.map +1 -0
  207. package/dist/appShell/useDrawerCollapsed.js +29 -0
  208. package/dist/appShell/useDrawerCollapsed.js.map +1 -0
  209. package/dist/appShell/useFittingActionCount.js +45 -0
  210. package/dist/appShell/useFittingActionCount.js.map +1 -0
  211. package/dist/appShell/usePinnedMobileTabs.js +32 -0
  212. package/dist/appShell/usePinnedMobileTabs.js.map +1 -0
  213. package/dist/appShell/useTabBarMinimized.js +33 -0
  214. package/dist/appShell/useTabBarMinimized.js.map +1 -0
  215. package/dist/auth/PasswordChecklist.js +44 -0
  216. package/dist/auth/PasswordChecklist.js.map +1 -0
  217. package/dist/auth/passwordRules.js +43 -0
  218. package/dist/auth/passwordRules.js.map +1 -0
  219. package/dist/calendar/EventCalendar.js +149 -0
  220. package/dist/calendar/EventCalendar.js.map +1 -0
  221. package/dist/calendar/EventDetails.js +74 -0
  222. package/dist/calendar/EventDetails.js.map +1 -0
  223. package/dist/calendar/calendarEvents.js +31 -0
  224. package/dist/calendar/calendarEvents.js.map +1 -0
  225. package/dist/calendar.js +13 -0
  226. package/dist/calendar.js.map +1 -0
  227. package/dist/charts.js +16 -0
  228. package/dist/charts.js.map +1 -0
  229. package/dist/date-pickers.js +8 -0
  230. package/dist/date-pickers.js.map +1 -0
  231. package/dist/datePickers/DateInput.js +76 -0
  232. package/dist/datePickers/DateInput.js.map +1 -0
  233. package/dist/datePickers/FormDateField.js +12 -0
  234. package/dist/datePickers/FormDateField.js.map +1 -0
  235. package/dist/dates.js +25 -0
  236. package/dist/dates.js.map +1 -0
  237. package/dist/dictionaries/dictionaries.js +48 -0
  238. package/dist/dictionaries/dictionaries.js.map +1 -0
  239. package/dist/downloads/DownloadManager.js +195 -0
  240. package/dist/downloads/DownloadManager.js.map +1 -0
  241. package/dist/downloads/downloadQueue.js +56 -0
  242. package/dist/downloads/downloadQueue.js.map +1 -0
  243. package/dist/downloads/downloadsMachine.js +80 -0
  244. package/dist/downloads/downloadsMachine.js.map +1 -0
  245. package/dist/downloads/fileTypes.js +22 -0
  246. package/dist/downloads/fileTypes.js.map +1 -0
  247. package/dist/excel/reportWorkbook.js +299 -0
  248. package/dist/excel/reportWorkbook.js.map +1 -0
  249. package/dist/excel.js +13 -0
  250. package/dist/excel.js.map +1 -0
  251. package/dist/feedback/ConfirmDialog.js +73 -0
  252. package/dist/feedback/ConfirmDialog.js.map +1 -0
  253. package/dist/feedback/ModalWaiting.js +23 -0
  254. package/dist/feedback/ModalWaiting.js.map +1 -0
  255. package/dist/feedback/NewBuildNotice.js +79 -0
  256. package/dist/feedback/NewBuildNotice.js.map +1 -0
  257. package/dist/feedback/StaleBuildBoundary.js +36 -0
  258. package/dist/feedback/StaleBuildBoundary.js.map +1 -0
  259. package/dist/feedback/Toaster.js +20 -0
  260. package/dist/feedback/Toaster.js.map +1 -0
  261. package/dist/feedback/confirmActionMachine.js +67 -0
  262. package/dist/feedback/confirmActionMachine.js.map +1 -0
  263. package/dist/feedback/toast.js +88 -0
  264. package/dist/feedback/toast.js.map +1 -0
  265. package/dist/feedback/useConfirmAction.js +40 -0
  266. package/dist/feedback/useConfirmAction.js.map +1 -0
  267. package/dist/filepond/FileDropzone.js +256 -0
  268. package/dist/filepond/FileDropzone.js.map +1 -0
  269. package/dist/filepond/pondServer.js +48 -0
  270. package/dist/filepond/pondServer.js.map +1 -0
  271. package/dist/filepond.js +10 -0
  272. package/dist/filepond.js.map +1 -0
  273. package/dist/files.js +43 -0
  274. package/dist/files.js.map +1 -0
  275. package/dist/formatting.js +205 -0
  276. package/dist/formatting.js.map +1 -0
  277. package/dist/forms/FormCatalogField.js +12 -0
  278. package/dist/forms/FormCatalogField.js.map +1 -0
  279. package/dist/forms/FormColorField.js +12 -0
  280. package/dist/forms/FormColorField.js.map +1 -0
  281. package/dist/forms/FormNumberField.js +12 -0
  282. package/dist/forms/FormNumberField.js.map +1 -0
  283. package/dist/forms/FormProblemAlert.js +15 -0
  284. package/dist/forms/FormProblemAlert.js.map +1 -0
  285. package/dist/forms/FormSelectField.js +12 -0
  286. package/dist/forms/FormSelectField.js.map +1 -0
  287. package/dist/forms/FormServerProblem.js +23 -0
  288. package/dist/forms/FormServerProblem.js.map +1 -0
  289. package/dist/forms/FormTextField.js +12 -0
  290. package/dist/forms/FormTextField.js.map +1 -0
  291. package/dist/forms/FormWizard.js +63 -0
  292. package/dist/forms/FormWizard.js.map +1 -0
  293. package/dist/forms/SubmitButton.js +14 -0
  294. package/dist/forms/SubmitButton.js.map +1 -0
  295. package/dist/forms/applyServerProblem.js +15 -0
  296. package/dist/forms/applyServerProblem.js.map +1 -0
  297. package/dist/forms/auth/ChangePasswordForm.js +47 -0
  298. package/dist/forms/auth/ChangePasswordForm.js.map +1 -0
  299. package/dist/forms/auth/ForgotPasswordForm.js +50 -0
  300. package/dist/forms/auth/ForgotPasswordForm.js.map +1 -0
  301. package/dist/forms/auth/SignInForm.js +48 -0
  302. package/dist/forms/auth/SignInForm.js.map +1 -0
  303. package/dist/forms/security/SecondStepForm.js +122 -0
  304. package/dist/forms/security/SecondStepForm.js.map +1 -0
  305. package/dist/forms/security/TwoStepVerificationCard.js +338 -0
  306. package/dist/forms/security/TwoStepVerificationCard.js.map +1 -0
  307. package/dist/forms/security/securityRules.js +28 -0
  308. package/dist/forms/security/securityRules.js.map +1 -0
  309. package/dist/forms/serverProblemFields.js +25 -0
  310. package/dist/forms/serverProblemFields.js.map +1 -0
  311. package/dist/forms/useFormikField.js +16 -0
  312. package/dist/forms/useFormikField.js.map +1 -0
  313. package/dist/forms/validation.js +55 -0
  314. package/dist/forms/validation.js.map +1 -0
  315. package/dist/forms/validationMessages.js +16 -0
  316. package/dist/forms/validationMessages.js.map +1 -0
  317. package/dist/forms.js +57 -0
  318. package/dist/forms.js.map +1 -0
  319. package/dist/hookForm/FormCatalogField.js +12 -0
  320. package/dist/hookForm/FormCatalogField.js.map +1 -0
  321. package/dist/hookForm/FormColorField.js +12 -0
  322. package/dist/hookForm/FormColorField.js.map +1 -0
  323. package/dist/hookForm/FormNumberField.js +12 -0
  324. package/dist/hookForm/FormNumberField.js.map +1 -0
  325. package/dist/hookForm/FormProblemAlert.js +17 -0
  326. package/dist/hookForm/FormProblemAlert.js.map +1 -0
  327. package/dist/hookForm/FormSelectField.js +12 -0
  328. package/dist/hookForm/FormSelectField.js.map +1 -0
  329. package/dist/hookForm/FormTextField.js +12 -0
  330. package/dist/hookForm/FormTextField.js.map +1 -0
  331. package/dist/hookForm/FormWizard.js +59 -0
  332. package/dist/hookForm/FormWizard.js.map +1 -0
  333. package/dist/hookForm/SubmitButton.js +15 -0
  334. package/dist/hookForm/SubmitButton.js.map +1 -0
  335. package/dist/hookForm/applyServerProblem.js +21 -0
  336. package/dist/hookForm/applyServerProblem.js.map +1 -0
  337. package/dist/hookForm/useHookFormField.js +19 -0
  338. package/dist/hookForm/useHookFormField.js.map +1 -0
  339. package/dist/i18next.js +5 -0
  340. package/dist/i18next.js.map +1 -0
  341. package/dist/identifiers.js +8 -0
  342. package/dist/identifiers.js.map +1 -0
  343. package/dist/inbox/InboxLayout.js +104 -0
  344. package/dist/inbox/InboxLayout.js.map +1 -0
  345. package/dist/inbox/MessageList.js +114 -0
  346. package/dist/inbox/MessageList.js.map +1 -0
  347. package/dist/inbox/MessageView.js +104 -0
  348. package/dist/inbox/MessageView.js.map +1 -0
  349. package/dist/inbox/inboxDates.js +9 -0
  350. package/dist/inbox/inboxDates.js.map +1 -0
  351. package/dist/index.js +407 -0
  352. package/dist/index.js.map +1 -0
  353. package/dist/inputs/CatalogInput.js +66 -0
  354. package/dist/inputs/CatalogInput.js.map +1 -0
  355. package/dist/inputs/ColorInput.js +109 -0
  356. package/dist/inputs/ColorInput.js.map +1 -0
  357. package/dist/inputs/FieldFrame.js +20 -0
  358. package/dist/inputs/FieldFrame.js.map +1 -0
  359. package/dist/inputs/FormSection.js +105 -0
  360. package/dist/inputs/FormSection.js.map +1 -0
  361. package/dist/inputs/NumberInput.js +70 -0
  362. package/dist/inputs/NumberInput.js.map +1 -0
  363. package/dist/inputs/SelectInput.js +84 -0
  364. package/dist/inputs/SelectInput.js.map +1 -0
  365. package/dist/inputs/TextInput.js +101 -0
  366. package/dist/inputs/TextInput.js.map +1 -0
  367. package/dist/inputs/WizardLayout.js +54 -0
  368. package/dist/inputs/WizardLayout.js.map +1 -0
  369. package/dist/inputs/colorContrast.js +46 -0
  370. package/dist/inputs/colorContrast.js.map +1 -0
  371. package/dist/inputs/formLayoutContext.js +9 -0
  372. package/dist/inputs/formLayoutContext.js.map +1 -0
  373. package/dist/inputs/numberText.js +48 -0
  374. package/dist/inputs/numberText.js.map +1 -0
  375. package/dist/kanban/KanbanBoard.js +338 -0
  376. package/dist/kanban/KanbanBoard.js.map +1 -0
  377. package/dist/kanban/kanbanCards.js +19 -0
  378. package/dist/kanban/kanbanCards.js.map +1 -0
  379. package/dist/kanban/kanbanMoves.js +29 -0
  380. package/dist/kanban/kanbanMoves.js.map +1 -0
  381. package/dist/kanban.js +15 -0
  382. package/dist/kanban.js.map +1 -0
  383. package/dist/laravel/csrfRetry.js +18 -0
  384. package/dist/laravel/csrfRetry.js.map +1 -0
  385. package/dist/laravel.js +6 -0
  386. package/dist/laravel.js.map +1 -0
  387. package/dist/lastListUrl.js +35 -0
  388. package/dist/lastListUrl.js.map +1 -0
  389. package/dist/locales/en.js +787 -0
  390. package/dist/locales/en.js.map +1 -0
  391. package/dist/locales/es.js +787 -0
  392. package/dist/locales/es.js.map +1 -0
  393. package/dist/maps/MapView.js +116 -0
  394. package/dist/maps/MapView.js.map +1 -0
  395. package/dist/maps/mapMarkers.js +19 -0
  396. package/dist/maps/mapMarkers.js.map +1 -0
  397. package/dist/maps.js +10 -0
  398. package/dist/maps.js.map +1 -0
  399. package/dist/money/money.js +380 -0
  400. package/dist/money/money.js.map +1 -0
  401. package/dist/money.js +6 -0
  402. package/dist/money.js.map +1 -0
  403. package/dist/navigation/appMenu.js +93 -0
  404. package/dist/navigation/appMenu.js.map +1 -0
  405. package/dist/navigation/useMenuBadges.js +45 -0
  406. package/dist/navigation/useMenuBadges.js.map +1 -0
  407. package/dist/navigation.js +30 -0
  408. package/dist/navigation.js.map +1 -0
  409. package/dist/navigationTrail.js +82 -0
  410. package/dist/navigationTrail.js.map +1 -0
  411. package/dist/next.js +5 -0
  412. package/dist/next.js.map +1 -0
  413. package/dist/observability/buildWatch.js +19 -0
  414. package/dist/observability/buildWatch.js.map +1 -0
  415. package/dist/observability/logger.js +43 -0
  416. package/dist/observability/logger.js.map +1 -0
  417. package/dist/observability/publishedBuild.js +39 -0
  418. package/dist/observability/publishedBuild.js.map +1 -0
  419. package/dist/observability/usePublishedBuildWatch.js +77 -0
  420. package/dist/observability/usePublishedBuildWatch.js.map +1 -0
  421. package/dist/passkeys.js +7 -0
  422. package/dist/passkeys.js.map +1 -0
  423. package/dist/periodRanges.js +33 -0
  424. package/dist/periodRanges.js.map +1 -0
  425. package/dist/problems.js +51 -0
  426. package/dist/problems.js.map +1 -0
  427. package/dist/pwa/InstallAppSetting.js +34 -0
  428. package/dist/pwa/InstallAppSetting.js.map +1 -0
  429. package/dist/pwa/InstallInstructionsDialog.js +35 -0
  430. package/dist/pwa/InstallInstructionsDialog.js.map +1 -0
  431. package/dist/pwa/InstallPromptBanner.js +70 -0
  432. package/dist/pwa/InstallPromptBanner.js.map +1 -0
  433. package/dist/pwa/installInstructions.js +60 -0
  434. package/dist/pwa/installInstructions.js.map +1 -0
  435. package/dist/pwa/useInstallPrompt.js +71 -0
  436. package/dist/pwa/useInstallPrompt.js.map +1 -0
  437. package/dist/react-hook-form.js +32 -0
  438. package/dist/react-hook-form.js.map +1 -0
  439. package/dist/react-router.js +10 -0
  440. package/dist/react-router.js.map +1 -0
  441. package/dist/security/ActivityLog.js +80 -0
  442. package/dist/security/ActivityLog.js.map +1 -0
  443. package/dist/security/RecoveryCodesDialog.js +85 -0
  444. package/dist/security/RecoveryCodesDialog.js.map +1 -0
  445. package/dist/security/SessionsCard.js +83 -0
  446. package/dist/security/SessionsCard.js.map +1 -0
  447. package/dist/security/passkeys.js +39 -0
  448. package/dist/security/passkeys.js.map +1 -0
  449. package/dist/table.js +37 -0
  450. package/dist/table.js.map +1 -0
  451. package/dist/theme/androidDevice.js +16 -0
  452. package/dist/theme/androidDevice.js.map +1 -0
  453. package/dist/theme/appleTracking.js +34 -0
  454. package/dist/theme/appleTracking.js.map +1 -0
  455. package/dist/theme/components/MuiAppBar.js +27 -0
  456. package/dist/theme/components/MuiAppBar.js.map +1 -0
  457. package/dist/theme/components/MuiBackdrop.js +13 -0
  458. package/dist/theme/components/MuiBackdrop.js.map +1 -0
  459. package/dist/theme/components/MuiButton.js +25 -0
  460. package/dist/theme/components/MuiButton.js.map +1 -0
  461. package/dist/theme/components/MuiButtonBase.js +16 -0
  462. package/dist/theme/components/MuiButtonBase.js.map +1 -0
  463. package/dist/theme/components/MuiChip.js +30 -0
  464. package/dist/theme/components/MuiChip.js.map +1 -0
  465. package/dist/theme/components/MuiDataGrid.js +30 -0
  466. package/dist/theme/components/MuiDataGrid.js.map +1 -0
  467. package/dist/theme/components/MuiDialog.js +13 -0
  468. package/dist/theme/components/MuiDialog.js.map +1 -0
  469. package/dist/theme/components/MuiDrawer.js +18 -0
  470. package/dist/theme/components/MuiDrawer.js.map +1 -0
  471. package/dist/theme/components/MuiMenuItem.js +17 -0
  472. package/dist/theme/components/MuiMenuItem.js.map +1 -0
  473. package/dist/theme/components/MuiTypography.js +22 -0
  474. package/dist/theme/components/MuiTypography.js.map +1 -0
  475. package/dist/theme/components/glassComponents.js +885 -0
  476. package/dist/theme/components/glassComponents.js.map +1 -0
  477. package/dist/theme/components/minimalComponents.js +146 -0
  478. package/dist/theme/components/minimalComponents.js.map +1 -0
  479. package/dist/theme/components/paletteOf.js +7 -0
  480. package/dist/theme/components/paletteOf.js.map +1 -0
  481. package/dist/theme/createToolkitTheme.js +100 -0
  482. package/dist/theme/createToolkitTheme.js.map +1 -0
  483. package/dist/theme/glassSurface.js +328 -0
  484. package/dist/theme/glassSurface.js.map +1 -0
  485. package/dist/theme/glassToasterStyles.js +50 -0
  486. package/dist/theme/glassToasterStyles.js.map +1 -0
  487. package/dist/theme/mergeComponents.js +42 -0
  488. package/dist/theme/mergeComponents.js.map +1 -0
  489. package/dist/theme/stackcraftPalette.js +59 -0
  490. package/dist/theme/stackcraftPalette.js.map +1 -0
  491. package/dist/theme/toolkitComponents.js +28 -0
  492. package/dist/theme/toolkitComponents.js.map +1 -0
  493. package/dist/timeline.js +8 -0
  494. package/dist/timeline.js.map +1 -0
  495. package/dist/toolkit/ComponentTexts.js +13 -0
  496. package/dist/toolkit/ComponentTexts.js.map +1 -0
  497. package/dist/toolkit/ToolkitProvider.js +57 -0
  498. package/dist/toolkit/ToolkitProvider.js.map +1 -0
  499. package/dist/toolkit/browserNavigation.js +33 -0
  500. package/dist/toolkit/browserNavigation.js.map +1 -0
  501. package/dist/toolkit/componentTextsContext.js +15 -0
  502. package/dist/toolkit/componentTextsContext.js.map +1 -0
  503. package/dist/toolkit/hashNavigation.js +40 -0
  504. package/dist/toolkit/hashNavigation.js.map +1 -0
  505. package/dist/toolkit/navigationPaths.js +49 -0
  506. package/dist/toolkit/navigationPaths.js.map +1 -0
  507. package/dist/toolkit/toolkitContext.js +19 -0
  508. package/dist/toolkit/toolkitContext.js.map +1 -0
  509. package/dist/toolkit/toolkitSettings.js +107 -0
  510. package/dist/toolkit/toolkitSettings.js.map +1 -0
  511. package/dist/toolkit/useFormatters.js +12 -0
  512. package/dist/toolkit/useFormatters.js.map +1 -0
  513. package/dist/toolkit/useToolkitTranslation.js +22 -0
  514. package/dist/toolkit/useToolkitTranslation.js.map +1 -0
  515. package/dist/types/DataTable/AuditTrailDialog.d.ts +32 -0
  516. package/dist/types/DataTable/AuditTrailTable.d.ts +30 -0
  517. package/dist/types/DataTable/ColumnFilters/HeaderFilterPopover.d.ts +8 -0
  518. package/dist/types/DataTable/ColumnFilters/MultiSelectColumnFilter.d.ts +16 -0
  519. package/dist/types/DataTable/ColumnFilters/SortableFilterHeader.d.ts +26 -0
  520. package/dist/types/DataTable/ColumnFilters/TextColumnFilter.d.ts +8 -0
  521. package/dist/types/DataTable/ColumnFilters/index.d.ts +4 -0
  522. package/dist/types/DataTable/EmptyState.d.ts +13 -0
  523. package/dist/types/DataTable/FilterChips.d.ts +17 -0
  524. package/dist/types/DataTable/GoToPage.d.ts +13 -0
  525. package/dist/types/DataTable/SelectionBar.d.ts +32 -0
  526. package/dist/types/DataTable/ServerTable.d.ts +171 -0
  527. package/dist/types/DataTable/buildChipConfig.d.ts +22 -0
  528. package/dist/types/DataTable/columns.d.ts +93 -0
  529. package/dist/types/DataTable/filterContext.d.ts +13 -0
  530. package/dist/types/DataTable/index.d.ts +13 -0
  531. package/dist/types/DataTable/rowSelection.d.ts +113 -0
  532. package/dist/types/DataTable/serverTableParams.d.ts +16 -0
  533. package/dist/types/DataTable/tableMachine.d.ts +41 -0
  534. package/dist/types/DataTable/useDebouncedFilter.d.ts +8 -0
  535. package/dist/types/DataTable/useTableState.d.ts +93 -0
  536. package/dist/types/access/Can.d.ts +11 -0
  537. package/dist/types/access/PermissionMatrix.d.ts +23 -0
  538. package/dist/types/access/RequireAccess.d.ts +11 -0
  539. package/dist/types/access/accessRules.d.ts +24 -0
  540. package/dist/types/access/permissionGroups.d.ts +56 -0
  541. package/dist/types/access/useCan.d.ts +11 -0
  542. package/dist/types/account/AccountProvider.d.ts +27 -0
  543. package/dist/types/account/AccountSecuritySection.d.ts +9 -0
  544. package/dist/types/account/DemoTotpCodeButton.d.ts +6 -0
  545. package/dist/types/account/ForgotPasswordScreen.d.ts +17 -0
  546. package/dist/types/account/ProfileScreen.d.ts +43 -0
  547. package/dist/types/account/ResetPasswordScreen.d.ts +21 -0
  548. package/dist/types/account/SignInScreen.d.ts +27 -0
  549. package/dist/types/account/accountConnector.d.ts +268 -0
  550. package/dist/types/account/demo/createDemoAccountConnector.d.ts +30 -0
  551. package/dist/types/account/demo/totp.d.ts +45 -0
  552. package/dist/types/account/restAccountConnector.d.ts +49 -0
  553. package/dist/types/account-demo.d.ts +2 -0
  554. package/dist/types/account.d.ts +16 -0
  555. package/dist/types/adapters/i18next.d.ts +11 -0
  556. package/dist/types/adapters/nextNavigation.d.ts +33 -0
  557. package/dist/types/adapters/reactRouter.d.ts +6 -0
  558. package/dist/types/adapters/reactRouterRoutes.d.ts +42 -0
  559. package/dist/types/api/ApiError.d.ts +42 -0
  560. package/dist/types/api/createApiClient.d.ts +174 -0
  561. package/dist/types/api/staleChunks.d.ts +15 -0
  562. package/dist/types/appShell/AccountMenu.d.ts +28 -0
  563. package/dist/types/appShell/AppLayout.d.ts +76 -0
  564. package/dist/types/appShell/AppearanceSettings.d.ts +41 -0
  565. package/dist/types/appShell/AuthLayout.d.ts +21 -0
  566. package/dist/types/appShell/BarActionButton.d.ts +15 -0
  567. package/dist/types/appShell/BarActions.d.ts +23 -0
  568. package/dist/types/appShell/BarCapsule.d.ts +20 -0
  569. package/dist/types/appShell/BarSearch.d.ts +24 -0
  570. package/dist/types/appShell/HeaderTools.d.ts +27 -0
  571. package/dist/types/appShell/MobileTabBar.d.ts +20 -0
  572. package/dist/types/appShell/SettingsMenu.d.ts +13 -0
  573. package/dist/types/appShell/SideMenu.d.ts +31 -0
  574. package/dist/types/appShell/SideMenuEntry.d.ts +17 -0
  575. package/dist/types/appShell/SubmenuActionsMenu.d.ts +24 -0
  576. package/dist/types/appShell/TabBarEditor.d.ts +13 -0
  577. package/dist/types/appShell/TopMenu.d.ts +7 -0
  578. package/dist/types/appShell/appMenuContext.d.ts +9 -0
  579. package/dist/types/appShell/barActionsSlot.d.ts +35 -0
  580. package/dist/types/appShell/barMenuPlacement.d.ts +9 -0
  581. package/dist/types/appShell/menuItemText.d.ts +55 -0
  582. package/dist/types/appShell/pageTitle.d.ts +26 -0
  583. package/dist/types/appShell/shellSizes.d.ts +46 -0
  584. package/dist/types/appShell/tabBarRule.d.ts +5 -0
  585. package/dist/types/appShell/tabBarScroll.d.ts +26 -0
  586. package/dist/types/appShell/useDrawerCollapsed.d.ts +8 -0
  587. package/dist/types/appShell/useFittingActionCount.d.ts +7 -0
  588. package/dist/types/appShell/usePinnedMobileTabs.d.ts +7 -0
  589. package/dist/types/appShell/useTabBarMinimized.d.ts +8 -0
  590. package/dist/types/auth/PasswordChecklist.d.ts +13 -0
  591. package/dist/types/auth/passwordRules.d.ts +34 -0
  592. package/dist/types/calendar/EventCalendar.d.ts +63 -0
  593. package/dist/types/calendar/EventDetails.d.ts +36 -0
  594. package/dist/types/calendar/calendarEvents.d.ts +27 -0
  595. package/dist/types/calendar.d.ts +3 -0
  596. package/dist/types/charts.d.ts +6 -0
  597. package/dist/types/date-pickers.d.ts +2 -0
  598. package/dist/types/datePickers/DateInput.d.ts +41 -0
  599. package/dist/types/datePickers/FormDateField.d.ts +7 -0
  600. package/dist/types/dates.d.ts +18 -0
  601. package/dist/types/dictionaries/dictionaries.d.ts +54 -0
  602. package/dist/types/downloads/DownloadManager.d.ts +7 -0
  603. package/dist/types/downloads/downloadQueue.d.ts +50 -0
  604. package/dist/types/downloads/downloadsMachine.d.ts +10 -0
  605. package/dist/types/downloads/fileTypes.d.ts +39 -0
  606. package/dist/types/downloads/index.d.ts +4 -0
  607. package/dist/types/excel/reportWorkbook.d.ts +157 -0
  608. package/dist/types/excel.d.ts +1 -0
  609. package/dist/types/feedback/ConfirmDialog.d.ts +31 -0
  610. package/dist/types/feedback/ModalWaiting.d.ts +13 -0
  611. package/dist/types/feedback/NewBuildNotice.d.ts +20 -0
  612. package/dist/types/feedback/StaleBuildBoundary.d.ts +21 -0
  613. package/dist/types/feedback/Toaster.d.ts +1 -0
  614. package/dist/types/feedback/confirmActionMachine.d.ts +19 -0
  615. package/dist/types/feedback/index.d.ts +8 -0
  616. package/dist/types/feedback/toast.d.ts +100 -0
  617. package/dist/types/feedback/useConfirmAction.d.ts +33 -0
  618. package/dist/types/filepond/FileDropzone.d.ts +61 -0
  619. package/dist/types/filepond/pondServer.d.ts +17 -0
  620. package/dist/types/filepond.d.ts +3 -0
  621. package/dist/types/files.d.ts +29 -0
  622. package/dist/types/formatting.d.ts +61 -0
  623. package/dist/types/forms/FormCatalogField.d.ts +6 -0
  624. package/dist/types/forms/FormColorField.d.ts +6 -0
  625. package/dist/types/forms/FormNumberField.d.ts +6 -0
  626. package/dist/types/forms/FormProblemAlert.d.ts +6 -0
  627. package/dist/types/forms/FormSelectField.d.ts +6 -0
  628. package/dist/types/forms/FormServerProblem.d.ts +8 -0
  629. package/dist/types/forms/FormTextField.d.ts +6 -0
  630. package/dist/types/forms/FormWizard.d.ts +22 -0
  631. package/dist/types/forms/SubmitButton.d.ts +9 -0
  632. package/dist/types/forms/applyServerProblem.d.ts +9 -0
  633. package/dist/types/forms/auth/ChangePasswordForm.d.ts +17 -0
  634. package/dist/types/forms/auth/ForgotPasswordForm.d.ts +14 -0
  635. package/dist/types/forms/auth/SignInForm.d.ts +20 -0
  636. package/dist/types/forms/index.d.ts +19 -0
  637. package/dist/types/forms/security/SecondStepForm.d.ts +30 -0
  638. package/dist/types/forms/security/TwoStepVerificationCard.d.ts +83 -0
  639. package/dist/types/forms/security/securityRules.d.ts +24 -0
  640. package/dist/types/forms/serverProblemFields.d.ts +19 -0
  641. package/dist/types/forms/useFormikField.d.ts +11 -0
  642. package/dist/types/forms/validation.d.ts +251 -0
  643. package/dist/types/forms/validationMessages.d.ts +12 -0
  644. package/dist/types/forms.d.ts +2 -0
  645. package/dist/types/hookForm/FormCatalogField.d.ts +8 -0
  646. package/dist/types/hookForm/FormColorField.d.ts +8 -0
  647. package/dist/types/hookForm/FormNumberField.d.ts +8 -0
  648. package/dist/types/hookForm/FormProblemAlert.d.ts +7 -0
  649. package/dist/types/hookForm/FormSelectField.d.ts +8 -0
  650. package/dist/types/hookForm/FormTextField.d.ts +8 -0
  651. package/dist/types/hookForm/FormWizard.d.ts +22 -0
  652. package/dist/types/hookForm/SubmitButton.d.ts +21 -0
  653. package/dist/types/hookForm/applyServerProblem.d.ts +10 -0
  654. package/dist/types/hookForm/useHookFormField.d.ts +13 -0
  655. package/dist/types/i18next.d.ts +1 -0
  656. package/dist/types/identifiers.d.ts +2 -0
  657. package/dist/types/inbox/InboxLayout.d.ts +38 -0
  658. package/dist/types/inbox/MessageList.d.ts +52 -0
  659. package/dist/types/inbox/MessageView.d.ts +55 -0
  660. package/dist/types/inbox/inboxDates.d.ts +11 -0
  661. package/dist/types/index.d.ts +91 -0
  662. package/dist/types/inputs/CatalogInput.d.ts +45 -0
  663. package/dist/types/inputs/ColorInput.d.ts +30 -0
  664. package/dist/types/inputs/FieldFrame.d.ts +14 -0
  665. package/dist/types/inputs/FormSection.d.ts +29 -0
  666. package/dist/types/inputs/NumberInput.d.ts +38 -0
  667. package/dist/types/inputs/SelectInput.d.ts +38 -0
  668. package/dist/types/inputs/TextInput.d.ts +62 -0
  669. package/dist/types/inputs/WizardLayout.d.ts +34 -0
  670. package/dist/types/inputs/colorContrast.d.ts +18 -0
  671. package/dist/types/inputs/formLayoutContext.d.ts +3 -0
  672. package/dist/types/inputs/numberText.d.ts +25 -0
  673. package/dist/types/kanban/KanbanBoard.d.ts +88 -0
  674. package/dist/types/kanban/kanbanCards.d.ts +22 -0
  675. package/dist/types/kanban/kanbanMoves.d.ts +38 -0
  676. package/dist/types/kanban.d.ts +3 -0
  677. package/dist/types/laravel/csrfRetry.d.ts +21 -0
  678. package/dist/types/laravel.d.ts +1 -0
  679. package/dist/types/lastListUrl.d.ts +20 -0
  680. package/dist/types/locales/en.d.ts +788 -0
  681. package/dist/types/locales/es.d.ts +788 -0
  682. package/dist/types/maps/MapView.d.ts +41 -0
  683. package/dist/types/maps/mapMarkers.d.ts +23 -0
  684. package/dist/types/maps.d.ts +2 -0
  685. package/dist/types/money/money.d.ts +203 -0
  686. package/dist/types/money.d.ts +1 -0
  687. package/dist/types/navigation/appMenu.d.ts +92 -0
  688. package/dist/types/navigation/useMenuBadges.d.ts +16 -0
  689. package/dist/types/navigation.d.ts +22 -0
  690. package/dist/types/navigationTrail.d.ts +49 -0
  691. package/dist/types/next.d.ts +1 -0
  692. package/dist/types/observability/buildWatch.d.ts +28 -0
  693. package/dist/types/observability/logger.d.ts +19 -0
  694. package/dist/types/observability/publishedBuild.d.ts +35 -0
  695. package/dist/types/observability/usePublishedBuildWatch.d.ts +18 -0
  696. package/dist/types/passkeys.d.ts +1 -0
  697. package/dist/types/periodRanges.d.ts +32 -0
  698. package/dist/types/problems.d.ts +31 -0
  699. package/dist/types/pwa/InstallAppSetting.d.ts +7 -0
  700. package/dist/types/pwa/InstallInstructionsDialog.d.ts +20 -0
  701. package/dist/types/pwa/InstallPromptBanner.d.ts +16 -0
  702. package/dist/types/pwa/installInstructions.d.ts +52 -0
  703. package/dist/types/pwa/useInstallPrompt.d.ts +13 -0
  704. package/dist/types/react-hook-form.d.ts +12 -0
  705. package/dist/types/react-router.d.ts +2 -0
  706. package/dist/types/security/ActivityLog.d.ts +33 -0
  707. package/dist/types/security/RecoveryCodesDialog.d.ts +16 -0
  708. package/dist/types/security/SessionsCard.d.ts +24 -0
  709. package/dist/types/security/passkeys.d.ts +18 -0
  710. package/dist/types/table.d.ts +3 -0
  711. package/dist/types/theme/androidDevice.d.ts +11 -0
  712. package/dist/types/theme/appleTracking.d.ts +17 -0
  713. package/dist/types/theme/components/MuiAppBar.d.ts +13 -0
  714. package/dist/types/theme/components/MuiBackdrop.d.ts +11 -0
  715. package/dist/types/theme/components/MuiButton.d.ts +27 -0
  716. package/dist/types/theme/components/MuiButtonBase.d.ts +14 -0
  717. package/dist/types/theme/components/MuiChip.d.ts +29 -0
  718. package/dist/types/theme/components/MuiDataGrid.d.ts +45 -0
  719. package/dist/types/theme/components/MuiDialog.d.ts +9 -0
  720. package/dist/types/theme/components/MuiDrawer.d.ts +13 -0
  721. package/dist/types/theme/components/MuiMenuItem.d.ts +17 -0
  722. package/dist/types/theme/components/MuiTypography.d.ts +20 -0
  723. package/dist/types/theme/components/glassComponents.d.ts +8 -0
  724. package/dist/types/theme/components/minimalComponents.d.ts +22 -0
  725. package/dist/types/theme/components/paletteOf.d.ts +5 -0
  726. package/dist/types/theme/createToolkitTheme.d.ts +48 -0
  727. package/dist/types/theme/glassSurface.d.ts +247 -0
  728. package/dist/types/theme/glassToasterStyles.d.ts +7 -0
  729. package/dist/types/theme/mergeComponents.d.ts +15 -0
  730. package/dist/types/theme/stackcraftPalette.d.ts +142 -0
  731. package/dist/types/theme/toolkitComponents.d.ts +4 -0
  732. package/dist/types/timeline.d.ts +2 -0
  733. package/dist/types/toolkit/ComponentTexts.d.ts +11 -0
  734. package/dist/types/toolkit/ToolkitProvider.d.ts +47 -0
  735. package/dist/types/toolkit/browserNavigation.d.ts +27 -0
  736. package/dist/types/toolkit/componentTextsContext.d.ts +20 -0
  737. package/dist/types/toolkit/hashNavigation.d.ts +12 -0
  738. package/dist/types/toolkit/navigationPaths.d.ts +43 -0
  739. package/dist/types/toolkit/toolkitContext.d.ts +28 -0
  740. package/dist/types/toolkit/toolkitSettings.d.ts +113 -0
  741. package/dist/types/toolkit/useFormatters.d.ts +6 -0
  742. package/dist/types/toolkit/useToolkitTranslation.d.ts +11 -0
  743. package/dist/types/ui/actions/ActionsMenu.d.ts +20 -0
  744. package/dist/types/ui/actions/CopyButton.d.ts +15 -0
  745. package/dist/types/ui/actions/DownloadMenu.d.ts +55 -0
  746. package/dist/types/ui/actions/SecretField.d.ts +17 -0
  747. package/dist/types/ui/actions/SelectionActions.d.ts +39 -0
  748. package/dist/types/ui/filters/DateRangeFilter.d.ts +18 -0
  749. package/dist/types/ui/filters/PeriodRangeSelector.d.ts +28 -0
  750. package/dist/types/ui/filters/QuickFilters.d.ts +23 -0
  751. package/dist/types/ui/filters/SegmentedControl.d.ts +44 -0
  752. package/dist/types/ui/index.d.ts +33 -0
  753. package/dist/types/ui/labels/DictionaryText.d.ts +7 -0
  754. package/dist/types/ui/labels/StatusChip.d.ts +21 -0
  755. package/dist/types/ui/labels/Tag.d.ts +19 -0
  756. package/dist/types/ui/labels/tagOf.d.ts +13 -0
  757. package/dist/types/ui/layout/CollapsibleSection.d.ts +18 -0
  758. package/dist/types/ui/layout/ContentDialog.d.ts +15 -0
  759. package/dist/types/ui/layout/DefinitionList.d.ts +15 -0
  760. package/dist/types/ui/layout/DetailHeader.d.ts +15 -0
  761. package/dist/types/ui/layout/ErrorPage.d.ts +35 -0
  762. package/dist/types/ui/layout/FullPageLoader.d.ts +7 -0
  763. package/dist/types/ui/layout/GlassLensFilter.d.ts +1 -0
  764. package/dist/types/ui/layout/GlassPanel.d.ts +11 -0
  765. package/dist/types/ui/layout/PageHeader.d.ts +15 -0
  766. package/dist/types/ui/layout/PageHeading.d.ts +20 -0
  767. package/dist/types/ui/layout/ProfileHeader.d.ts +17 -0
  768. package/dist/types/ui/layout/ScrollableRow.d.ts +33 -0
  769. package/dist/types/ui/layout/SectionCard.d.ts +11 -0
  770. package/dist/types/ui/layout/appBarHeight.d.ts +13 -0
  771. package/dist/types/ui/metrics/BarList.d.ts +25 -0
  772. package/dist/types/ui/metrics/CalendarHeatmap.d.ts +34 -0
  773. package/dist/types/ui/metrics/ChartTooltip.d.ts +11 -0
  774. package/dist/types/ui/metrics/ColumnChart.d.ts +47 -0
  775. package/dist/types/ui/metrics/LineChart.d.ts +41 -0
  776. package/dist/types/ui/metrics/MetricCard.d.ts +39 -0
  777. package/dist/types/ui/metrics/TableToggle.d.ts +14 -0
  778. package/dist/types/ui/metrics/barListLabels.d.ts +17 -0
  779. package/dist/types/ui/metrics/chartParts.d.ts +112 -0
  780. package/dist/types/ui/metrics/heatmapScale.d.ts +45 -0
  781. package/dist/types/ui/navigation/BackButton.d.ts +13 -0
  782. package/dist/types/ui/navigation/ColorSchemeToggle.d.ts +13 -0
  783. package/dist/types/ui/navigation/DocumentTitle.d.ts +6 -0
  784. package/dist/types/ui/navigation/FontSizeToggle.d.ts +11 -0
  785. package/dist/types/ui/navigation/LanguageToggle.d.ts +13 -0
  786. package/dist/types/ui/navigation/PageBreadcrumbs.d.ts +12 -0
  787. package/dist/types/ui/navigation/colorMode.d.ts +18 -0
  788. package/dist/types/ui/navigation/fontSizeLevels.d.ts +25 -0
  789. package/dist/types/ui/navigation/useFontSize.d.ts +10 -0
  790. package/dist/types/ui/timeline/GroupedTimeline.d.ts +41 -0
  791. package/dist/types/ui/timeline/timelineDot.d.ts +19 -0
  792. package/dist/types/upload/FileDropzone.d.ts +36 -0
  793. package/dist/types/upload/fileRules.d.ts +51 -0
  794. package/dist/types/upload/uploadMachine.d.ts +23 -0
  795. package/dist/types/upload/uploadWithProgress.d.ts +16 -0
  796. package/dist/ui/actions/ActionsMenu.js +51 -0
  797. package/dist/ui/actions/ActionsMenu.js.map +1 -0
  798. package/dist/ui/actions/CopyButton.js +28 -0
  799. package/dist/ui/actions/CopyButton.js.map +1 -0
  800. package/dist/ui/actions/DownloadMenu.js +162 -0
  801. package/dist/ui/actions/DownloadMenu.js.map +1 -0
  802. package/dist/ui/actions/SecretField.js +61 -0
  803. package/dist/ui/actions/SecretField.js.map +1 -0
  804. package/dist/ui/actions/SelectionActions.js +142 -0
  805. package/dist/ui/actions/SelectionActions.js.map +1 -0
  806. package/dist/ui/filters/DateRangeFilter.js +87 -0
  807. package/dist/ui/filters/DateRangeFilter.js.map +1 -0
  808. package/dist/ui/filters/PeriodRangeSelector.js +56 -0
  809. package/dist/ui/filters/PeriodRangeSelector.js.map +1 -0
  810. package/dist/ui/filters/QuickFilters.js +91 -0
  811. package/dist/ui/filters/QuickFilters.js.map +1 -0
  812. package/dist/ui/filters/SegmentedControl.js +80 -0
  813. package/dist/ui/filters/SegmentedControl.js.map +1 -0
  814. package/dist/ui/labels/DictionaryText.js +11 -0
  815. package/dist/ui/labels/DictionaryText.js.map +1 -0
  816. package/dist/ui/labels/StatusChip.js +52 -0
  817. package/dist/ui/labels/StatusChip.js.map +1 -0
  818. package/dist/ui/labels/Tag.js +26 -0
  819. package/dist/ui/labels/Tag.js.map +1 -0
  820. package/dist/ui/labels/tagOf.js +7 -0
  821. package/dist/ui/labels/tagOf.js.map +1 -0
  822. package/dist/ui/layout/CollapsibleSection.js +52 -0
  823. package/dist/ui/layout/CollapsibleSection.js.map +1 -0
  824. package/dist/ui/layout/ContentDialog.js +97 -0
  825. package/dist/ui/layout/ContentDialog.js.map +1 -0
  826. package/dist/ui/layout/DefinitionList.js +30 -0
  827. package/dist/ui/layout/DefinitionList.js.map +1 -0
  828. package/dist/ui/layout/DetailHeader.js +27 -0
  829. package/dist/ui/layout/DetailHeader.js.map +1 -0
  830. package/dist/ui/layout/ErrorPage.js +54 -0
  831. package/dist/ui/layout/ErrorPage.js.map +1 -0
  832. package/dist/ui/layout/FullPageLoader.js +13 -0
  833. package/dist/ui/layout/FullPageLoader.js.map +1 -0
  834. package/dist/ui/layout/GlassLensFilter.js +53 -0
  835. package/dist/ui/layout/GlassLensFilter.js.map +1 -0
  836. package/dist/ui/layout/GlassPanel.js +18 -0
  837. package/dist/ui/layout/GlassPanel.js.map +1 -0
  838. package/dist/ui/layout/PageHeader.js +23 -0
  839. package/dist/ui/layout/PageHeader.js.map +1 -0
  840. package/dist/ui/layout/PageHeading.js +51 -0
  841. package/dist/ui/layout/PageHeading.js.map +1 -0
  842. package/dist/ui/layout/ProfileHeader.js +64 -0
  843. package/dist/ui/layout/ProfileHeader.js.map +1 -0
  844. package/dist/ui/layout/ScrollableRow.js +156 -0
  845. package/dist/ui/layout/ScrollableRow.js.map +1 -0
  846. package/dist/ui/layout/SectionCard.js +18 -0
  847. package/dist/ui/layout/SectionCard.js.map +1 -0
  848. package/dist/ui/layout/appBarHeight.js +42 -0
  849. package/dist/ui/layout/appBarHeight.js.map +1 -0
  850. package/dist/ui/metrics/BarList.js +94 -0
  851. package/dist/ui/metrics/BarList.js.map +1 -0
  852. package/dist/ui/metrics/CalendarHeatmap.js +136 -0
  853. package/dist/ui/metrics/CalendarHeatmap.js.map +1 -0
  854. package/dist/ui/metrics/ChartTooltip.js +16 -0
  855. package/dist/ui/metrics/ChartTooltip.js.map +1 -0
  856. package/dist/ui/metrics/ColumnChart.js +106 -0
  857. package/dist/ui/metrics/ColumnChart.js.map +1 -0
  858. package/dist/ui/metrics/LineChart.js +117 -0
  859. package/dist/ui/metrics/LineChart.js.map +1 -0
  860. package/dist/ui/metrics/MetricCard.js +97 -0
  861. package/dist/ui/metrics/MetricCard.js.map +1 -0
  862. package/dist/ui/metrics/TableToggle.js +15 -0
  863. package/dist/ui/metrics/TableToggle.js.map +1 -0
  864. package/dist/ui/metrics/barListLabels.js +9 -0
  865. package/dist/ui/metrics/barListLabels.js.map +1 -0
  866. package/dist/ui/metrics/chartParts.js +93 -0
  867. package/dist/ui/metrics/chartParts.js.map +1 -0
  868. package/dist/ui/metrics/heatmapScale.js +67 -0
  869. package/dist/ui/metrics/heatmapScale.js.map +1 -0
  870. package/dist/ui/navigation/BackButton.js +28 -0
  871. package/dist/ui/navigation/BackButton.js.map +1 -0
  872. package/dist/ui/navigation/ColorSchemeToggle.js +40 -0
  873. package/dist/ui/navigation/ColorSchemeToggle.js.map +1 -0
  874. package/dist/ui/navigation/DocumentTitle.js +11 -0
  875. package/dist/ui/navigation/DocumentTitle.js.map +1 -0
  876. package/dist/ui/navigation/FontSizeToggle.js +41 -0
  877. package/dist/ui/navigation/FontSizeToggle.js.map +1 -0
  878. package/dist/ui/navigation/LanguageToggle.js +48 -0
  879. package/dist/ui/navigation/LanguageToggle.js.map +1 -0
  880. package/dist/ui/navigation/PageBreadcrumbs.js +51 -0
  881. package/dist/ui/navigation/PageBreadcrumbs.js.map +1 -0
  882. package/dist/ui/navigation/colorMode.js +13 -0
  883. package/dist/ui/navigation/colorMode.js.map +1 -0
  884. package/dist/ui/navigation/fontSizeLevels.js +24 -0
  885. package/dist/ui/navigation/fontSizeLevels.js.map +1 -0
  886. package/dist/ui/navigation/useFontSize.js +44 -0
  887. package/dist/ui/navigation/useFontSize.js.map +1 -0
  888. package/dist/ui/timeline/GroupedTimeline.js +106 -0
  889. package/dist/ui/timeline/GroupedTimeline.js.map +1 -0
  890. package/dist/ui/timeline/timelineDot.js +20 -0
  891. package/dist/ui/timeline/timelineDot.js.map +1 -0
  892. package/dist/upload/FileDropzone.js +145 -0
  893. package/dist/upload/FileDropzone.js.map +1 -0
  894. package/dist/upload/fileRules.js +62 -0
  895. package/dist/upload/fileRules.js.map +1 -0
  896. package/dist/upload/uploadMachine.js +73 -0
  897. package/dist/upload/uploadMachine.js.map +1 -0
  898. package/dist/upload/uploadWithProgress.js +45 -0
  899. package/dist/upload/uploadWithProgress.js.map +1 -0
  900. package/package.json +311 -5
@@ -0,0 +1,380 @@
1
+ import { intlLocaleOf, toolkitSettings } from "../toolkit/toolkitSettings.js";
2
+ const MONEY_ROUNDING = Object.freeze({
3
+ // la mitad se aleja del cero: 2.345 → 2.35 y −2.345 → −2.35 (como se redondea a mano)
4
+ halfUp: "halfUp",
5
+ // la mitad va al par: 2.345 → 2.34 y 2.355 → 2.36 (redondeo bancario: en muchas sumas no carga hacia arriba)
6
+ halfEven: "halfEven",
7
+ // corta hacia el cero: 2.349 → 2.34 (lo que hacen el Money de PHP y el de Go al leer)
8
+ down: "down"
9
+ });
10
+ const DEFAULT_ROUNDING = MONEY_ROUNDING.halfUp;
11
+ const PLAIN_NUMBER = /^-?\d+(\.\d+)?$/;
12
+ const DECIMAL_POINT = ".";
13
+ const NEGATIVE_SIGN = "-";
14
+ const TEN = 10n;
15
+ const formatterCache = /* @__PURE__ */ new Map();
16
+ function decimalsOfCurrency(currency) {
17
+ return new Intl.NumberFormat("en", { style: "currency", currency }).resolvedOptions().maximumFractionDigits;
18
+ }
19
+ function settingsOf({ currency, decimals } = {}) {
20
+ const chosenCurrency = currency ?? toolkitSettings().currency;
21
+ const chosenDecimals = decimals ?? decimalsOfCurrency(chosenCurrency);
22
+ if (!Number.isInteger(chosenDecimals) || chosenDecimals < 0) {
23
+ throw new RangeError(`Los decimales de un monto son un entero de 0 en adelante, no ${decimals}`);
24
+ }
25
+ return { currency: chosenCurrency, decimals: chosenDecimals };
26
+ }
27
+ function scaledIntegerOf(text) {
28
+ const [integerText, decimalText = ""] = text.split(DECIMAL_POINT);
29
+ return { units: BigInt(`${integerText}${decimalText}`), scale: decimalText.length };
30
+ }
31
+ function textOfNumber(value) {
32
+ if (!Number.isFinite(value)) {
33
+ throw new TypeError(`${value} no es un monto de dinero`);
34
+ }
35
+ return String(value);
36
+ }
37
+ function factorOf(value) {
38
+ const text = typeof value === "number" ? textOfNumber(value) : value;
39
+ if (typeof text !== "string" || !PLAIN_NUMBER.test(text)) {
40
+ throw new TypeError(`«${value}» no es un número simple para operar con un monto (sin comas, espacios ni exponente)`);
41
+ }
42
+ return scaledIntegerOf(text);
43
+ }
44
+ function divideRounded(numerator, denominator, rounding) {
45
+ const isNegative = numerator < 0n !== denominator < 0n;
46
+ const positiveNumerator = numerator < 0n ? -numerator : numerator;
47
+ const positiveDenominator = denominator < 0n ? -denominator : denominator;
48
+ let quotient = positiveNumerator / positiveDenominator;
49
+ const twiceRemainder = positiveNumerator % positiveDenominator * 2n;
50
+ if (rounding === MONEY_ROUNDING.halfUp && twiceRemainder >= positiveDenominator) {
51
+ quotient += 1n;
52
+ } else if (rounding === MONEY_ROUNDING.halfEven && (twiceRemainder > positiveDenominator || twiceRemainder === positiveDenominator && quotient % 2n === 1n)) {
53
+ quotient += 1n;
54
+ } else if (!Object.values(MONEY_ROUNDING).includes(rounding)) {
55
+ throw new RangeError(`«${rounding}» no es un modo de redondeo de MONEY_ROUNDING`);
56
+ }
57
+ return isNegative ? -quotient : quotient;
58
+ }
59
+ function floorSquareRoot(value) {
60
+ let root = BigInt(Math.floor(Math.sqrt(Number(value))));
61
+ while (root * root > value) {
62
+ root -= 1n;
63
+ }
64
+ while ((root + 1n) * (root + 1n) <= value) {
65
+ root += 1n;
66
+ }
67
+ return root;
68
+ }
69
+ function safeMinorUnitsOf(minorUnits) {
70
+ if (minorUnits > BigInt(Number.MAX_SAFE_INTEGER) || minorUnits < BigInt(Number.MIN_SAFE_INTEGER)) {
71
+ throw new RangeError("El monto pasa del tope que JavaScript guarda exacto (unos 90 billones con dos decimales)");
72
+ }
73
+ return Number(minorUnits);
74
+ }
75
+ class Money {
76
+ /**
77
+ * Centavos (la unidad menor de la moneda): 1050 son $10.50.
78
+ *
79
+ * @readonly
80
+ * @type {number}
81
+ */
82
+ minorUnits;
83
+ /**
84
+ * Código ISO 4217 de la moneda.
85
+ *
86
+ * @readonly
87
+ * @type {string}
88
+ */
89
+ currency;
90
+ /**
91
+ * Cuántos decimales lleva.
92
+ *
93
+ * @readonly
94
+ * @type {number}
95
+ */
96
+ decimals;
97
+ /**
98
+ * No se usa directo: los montos se arman con Money.fromString, Money.fromNumber, Money.fromMinorUnits o Money.zero.
99
+ *
100
+ * @param {number} minorUnits centavos (la unidad menor de la moneda), entero
101
+ * @param {string} currency código ISO 4217
102
+ * @param {number} decimals cuántos decimales lleva
103
+ */
104
+ constructor(minorUnits, currency, decimals) {
105
+ if (!Number.isSafeInteger(minorUnits)) {
106
+ throw new RangeError(`Un monto se guarda en centavos enteros; ${minorUnits} no lo es o pasa del tope de JavaScript`);
107
+ }
108
+ this.minorUnits = minorUnits;
109
+ this.currency = currency;
110
+ this.decimals = decimals;
111
+ Object.freeze(this);
112
+ }
113
+ /**
114
+ * Cero, para arrancar una suma.
115
+ *
116
+ * @param {object} [options]
117
+ * @param {string} [options.currency] código ISO 4217; por omisión, la del proveedor
118
+ * @param {number} [options.decimals] por omisión, los de la moneda
119
+ * @returns {Money}
120
+ */
121
+ static zero(options) {
122
+ const { currency, decimals } = settingsOf(options);
123
+ return new Money(0, currency, decimals);
124
+ }
125
+ /**
126
+ * Un monto a partir del texto que manda el API o la base ('1234.50', '-3', '0.5').
127
+ *
128
+ * @param {string} text un número simple: sin comas, espacios, símbolo ni exponente
129
+ * @param {object} [options]
130
+ * @param {string} [options.currency] código ISO 4217; por omisión, la del proveedor
131
+ * @param {number} [options.decimals] por omisión, los de la moneda
132
+ * @returns {Money}
133
+ */
134
+ static fromString(text, options) {
135
+ const { currency, decimals } = settingsOf(options);
136
+ if (typeof text !== "string" || !PLAIN_NUMBER.test(text)) {
137
+ throw new TypeError(`«${text}» no es un monto de dinero: se espera un número simple como '1234.50'`);
138
+ }
139
+ const { units, scale } = scaledIntegerOf(text);
140
+ const extraDecimals = scale - decimals;
141
+ if (extraDecimals <= 0) {
142
+ return new Money(safeMinorUnitsOf(units * TEN ** BigInt(-extraDecimals)), currency, decimals);
143
+ }
144
+ const divisor = TEN ** BigInt(extraDecimals);
145
+ if (units % divisor !== 0n) {
146
+ throw new RangeError(`«${text}» trae más de ${decimals} decimales; para no perder centavos, configure más decimales`);
147
+ }
148
+ return new Money(safeMinorUnitsOf(units / divisor), currency, decimals);
149
+ }
150
+ /**
151
+ * Un monto a partir de un número del JSON del API (2450.5). Lo que trae decimales de más (lo que deja hacer cuentas
152
+ * con decimales, como 0.30000000000000004) truena igual que en fromString.
153
+ *
154
+ * @param {number} value
155
+ * @param {object} [options]
156
+ * @param {string} [options.currency] código ISO 4217; por omisión, la del proveedor
157
+ * @param {number} [options.decimals] por omisión, los de la moneda
158
+ * @returns {Money}
159
+ */
160
+ static fromNumber(value, options) {
161
+ if (typeof value !== "number") {
162
+ throw new TypeError(`fromNumber recibe un número; para el texto del API use fromString («${value}»)`);
163
+ }
164
+ return Money.fromString(textOfNumber(value), options);
165
+ }
166
+ /**
167
+ * Un monto a partir de sus centavos enteros (1050 son $10.50).
168
+ *
169
+ * @param {number} minorUnits
170
+ * @param {object} [options]
171
+ * @param {string} [options.currency] código ISO 4217; por omisión, la del proveedor
172
+ * @param {number} [options.decimals] por omisión, los de la moneda
173
+ * @returns {Money}
174
+ */
175
+ static fromMinorUnits(minorUnits, options) {
176
+ const { currency, decimals } = settingsOf(options);
177
+ return new Money(minorUnits, currency, decimals);
178
+ }
179
+ /**
180
+ * Revisa que el otro monto sea de la misma moneda y con los mismos decimales.
181
+ *
182
+ * @param {Money} other
183
+ * @returns {void}
184
+ */
185
+ #assertSameKind(other) {
186
+ if (!(other instanceof Money)) {
187
+ throw new TypeError("Solo se opera un monto con otro Money; arme el otro con Money.fromString o Money.fromNumber");
188
+ }
189
+ if (other.currency !== this.currency || other.decimals !== this.decimals) {
190
+ throw new RangeError(`No se mezclan ${this.currency} con ${this.decimals} decimales y ${other.currency} con ${other.decimals}`);
191
+ }
192
+ }
193
+ /**
194
+ * Un monto nuevo de la misma moneda a partir de un entero grande de centavos.
195
+ *
196
+ * @param {bigint} minorUnits
197
+ * @returns {Money}
198
+ */
199
+ #withMinorUnits(minorUnits) {
200
+ return new Money(safeMinorUnitsOf(minorUnits), this.currency, this.decimals);
201
+ }
202
+ /**
203
+ * Este monto más otro.
204
+ *
205
+ * @param {Money} other
206
+ * @returns {Money}
207
+ */
208
+ plus(other) {
209
+ this.#assertSameKind(other);
210
+ return this.#withMinorUnits(BigInt(this.minorUnits) + BigInt(other.minorUnits));
211
+ }
212
+ /**
213
+ * Este monto menos otro.
214
+ *
215
+ * @param {Money} other
216
+ * @returns {Money}
217
+ */
218
+ minus(other) {
219
+ this.#assertSameKind(other);
220
+ return this.#withMinorUnits(BigInt(this.minorUnits) - BigInt(other.minorUnits));
221
+ }
222
+ /**
223
+ * Este monto por un factor (1.16 para el IVA, 3 piezas, '0.5'), redondeado al centavo.
224
+ *
225
+ * @param {number|string} factor un número simple; mejor en texto si viene de una tasa ('0.16')
226
+ * @param {object} [options]
227
+ * @param {string} [options.rounding] uno de MONEY_ROUNDING; por omisión halfUp
228
+ * @returns {Money}
229
+ */
230
+ times(factor, { rounding = DEFAULT_ROUNDING } = {}) {
231
+ const { units, scale } = factorOf(factor);
232
+ return this.#withMinorUnits(divideRounded(BigInt(this.minorUnits) * units, TEN ** BigInt(scale), rounding));
233
+ }
234
+ /**
235
+ * Este monto entre un divisor (3 pagos, '1.16' para quitar el IVA), redondeado al centavo.
236
+ *
237
+ * OJO: tres pagos de un tercio redondeado no siempre suman el total (10.00 / 3 = 3.33 y 3 × 3.33 = 9.99). Si las
238
+ * partes tienen que sumar el total exacto, la última se calcula restando las demás.
239
+ *
240
+ * @param {number|string} divisor un número simple, distinto de cero
241
+ * @param {object} [options]
242
+ * @param {string} [options.rounding] uno de MONEY_ROUNDING; por omisión halfUp
243
+ * @returns {Money}
244
+ */
245
+ dividedBy(divisor, { rounding = DEFAULT_ROUNDING } = {}) {
246
+ const { units, scale } = factorOf(divisor);
247
+ if (units === 0n) {
248
+ throw new RangeError("Un monto no se divide entre cero");
249
+ }
250
+ return this.#withMinorUnits(divideRounded(BigInt(this.minorUnits) * TEN ** BigInt(scale), units, rounding));
251
+ }
252
+ /**
253
+ * Este monto elevado a una potencia entera, redondeado al centavo: (1.05)² = 1.1025 → 1.10.
254
+ *
255
+ * @param {number} exponent entero de 0 en adelante
256
+ * @param {object} [options]
257
+ * @param {string} [options.rounding] uno de MONEY_ROUNDING; por omisión halfUp
258
+ * @returns {Money}
259
+ */
260
+ pow(exponent, { rounding = DEFAULT_ROUNDING } = {}) {
261
+ if (!Number.isInteger(exponent) || exponent < 0) {
262
+ throw new RangeError(`La potencia de un monto es un entero de 0 en adelante, no ${exponent}; la raíz cuadrada es sqrt()`);
263
+ }
264
+ const scale = TEN ** BigInt(this.decimals);
265
+ const power = BigInt(exponent);
266
+ return this.#withMinorUnits(divideRounded(BigInt(this.minorUnits) ** power * scale, scale ** power, rounding));
267
+ }
268
+ /**
269
+ * La raíz cuadrada de este monto, redondeada al centavo: √2.00 = 1.414… → 1.41.
270
+ *
271
+ * @param {object} [options]
272
+ * @param {string} [options.rounding] uno de MONEY_ROUNDING; por omisión halfUp (en una raíz nunca cae justo en la
273
+ * mitad, así que halfEven da lo mismo)
274
+ * @returns {Money}
275
+ */
276
+ sqrt({ rounding = DEFAULT_ROUNDING } = {}) {
277
+ if (this.minorUnits < 0) {
278
+ throw new RangeError("Un monto negativo no tiene raíz cuadrada");
279
+ }
280
+ if (!Object.values(MONEY_ROUNDING).includes(rounding)) {
281
+ throw new RangeError(`«${rounding}» no es un modo de redondeo de MONEY_ROUNDING`);
282
+ }
283
+ const radicand = BigInt(this.minorUnits) * TEN ** BigInt(this.decimals);
284
+ const root = floorSquareRoot(radicand);
285
+ const passesHalf = (2n * root + 1n) ** 2n <= 4n * radicand;
286
+ const roundsUp = rounding !== MONEY_ROUNDING.down && passesHalf;
287
+ return this.#withMinorUnits(roundsUp ? root + 1n : root);
288
+ }
289
+ /**
290
+ * Si los dos montos valen exactamente lo mismo, hasta el centavo.
291
+ *
292
+ * @param {Money} other
293
+ * @returns {boolean}
294
+ */
295
+ equals(other) {
296
+ this.#assertSameKind(other);
297
+ return this.minorUnits === other.minorUnits;
298
+ }
299
+ /**
300
+ * Si este monto es mayor que otro. El centavo de diferencia cuenta.
301
+ *
302
+ * @param {Money} other
303
+ * @returns {boolean}
304
+ */
305
+ isGreaterThan(other) {
306
+ this.#assertSameKind(other);
307
+ return this.minorUnits > other.minorUnits;
308
+ }
309
+ /**
310
+ * Si el monto es cero o negativo.
311
+ *
312
+ * @returns {boolean}
313
+ */
314
+ isZeroOrLess() {
315
+ return this.minorUnits <= 0;
316
+ }
317
+ /**
318
+ * El monto como texto, con todos sus decimales: '1234.50'. Es lo que se le manda al API para una columna NUMERIC.
319
+ *
320
+ * @returns {string}
321
+ */
322
+ amount() {
323
+ const sign = this.minorUnits < 0 ? NEGATIVE_SIGN : "";
324
+ const digits = String(Math.abs(this.minorUnits)).padStart(this.decimals + 1, "0");
325
+ if (this.decimals === 0) {
326
+ return `${sign}${digits}`;
327
+ }
328
+ return `${sign}${digits.slice(0, -this.decimals)}${DECIMAL_POINT}${digits.slice(-this.decimals)}`;
329
+ }
330
+ /**
331
+ * El monto como lo lee una persona, en el idioma del proveedor y con el símbolo de su moneda: $1,234.50 (es) o
332
+ * $1,234.50 (en); US$ o ¥ según la moneda. Sin pasar por decimales: Intl recibe el texto exacto.
333
+ *
334
+ * @returns {string}
335
+ */
336
+ format() {
337
+ const locale = intlLocaleOf(toolkitSettings().language);
338
+ const cacheKey = `${locale}|${this.currency}|${this.decimals}`;
339
+ if (!formatterCache.has(cacheKey)) {
340
+ formatterCache.set(cacheKey, new Intl.NumberFormat(locale, {
341
+ style: "currency",
342
+ currency: this.currency,
343
+ currencyDisplay: "narrowSymbol",
344
+ minimumFractionDigits: this.decimals,
345
+ maximumFractionDigits: this.decimals
346
+ }));
347
+ }
348
+ return formatterCache.get(cacheKey).format(this.amount());
349
+ }
350
+ /**
351
+ * Para que JSON.stringify mande el texto del monto ('1234.50') y no un objeto.
352
+ *
353
+ * @returns {string}
354
+ */
355
+ toJSON() {
356
+ return this.amount();
357
+ }
358
+ /**
359
+ * Para que un texto con el monto adentro (`${total}`) diga '1234.50'.
360
+ *
361
+ * @returns {string}
362
+ */
363
+ toString() {
364
+ return this.amount();
365
+ }
366
+ /**
367
+ * Truena a propósito: `total + iva` o `total > limit` regresarían a los números con decimales sin que nadie se dé
368
+ * cuenta. Se usa plus, minus, isGreaterThan...
369
+ *
370
+ * @returns {never}
371
+ */
372
+ valueOf() {
373
+ throw new TypeError("Un Money no se opera con + - * / > <: use plus, minus, times, dividedBy, isGreaterThan o equals");
374
+ }
375
+ }
376
+ export {
377
+ MONEY_ROUNDING,
378
+ Money
379
+ };
380
+ //# sourceMappingURL=money.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"money.js","sources":["../../src/money/money.js"],"sourcesContent":["// Un monto de dinero exacto: un entero de centavos (o de la unidad menor de su moneda), nunca un número con decimales.\n//\n// POR QUÉ EXISTE. En JavaScript los números con decimales no son exactos: 0.1 + 0.2 da 0.30000000000000004. Sumando\n// cientos de importes el error se acumula y el total de la pantalla deja de ser el del servidor. Con centavos enteros,\n// 10 + 20 siempre da 30. Es la misma regla que el Money de PHP (bcmath) y el money.Amount de Go (int64 de centavos):\n// el dinero nunca pasa por un número con decimales.\n//\n// Cómo se usa, y es a propósito que no se parezca a la aritmética normal:\n//\n// const total = Money.fromString(order.total).plus(Money.fromNumber(order.shipping));\n// const withTax = total.times('1.16'); // IVA del 16 %, redondeado al centavo\n// const perPayment = total.dividedBy(3); // tres pagos\n// if (total.isGreaterThan(Money.fromString('20000'))) { ... }\n// total.format() // \"$23,450.10\" en el idioma y la moneda del proveedor\n// total.amount() // \"23450.10\", el texto que se le manda al API\n//\n// Reglas que hace cumplir, para que un error truene al momento y no tres pantallas después:\n// - un texto que no es un número simple («1,234», « 12», «12.», «») no se lee como cero: truena;\n// - un monto con más decimales de los de su moneda («10.219» en pesos) truena: cortarlo perdería un centavo sin que\n// nadie se entere. Los ceros de más sí entran («10.500» son 10.50). Quien necesite más decimales los configura;\n// - no se suman ni se comparan pesos con dólares, ni montos con distintos decimales: truena;\n// - `+`, `-`, `>` y `<` truenan (valueOf): con ellos JavaScript volvería a los decimales. Se usa plus, minus,\n// isGreaterThan...\n//\n// Multiplicar, dividir, la potencia y la raíz sí tienen que redondear (un tercio de 10 pesos no cabe en centavos). Se\n// calculan con enteros grandes (BigInt) y se redondea UNA vez al final, al centavo, con el modo que se pida\n// (MONEY_ROUNDING). Por omisión, la mitad se aleja del cero, como se redondea a mano.\n//\n// Tope: un entero exacto de JavaScript llega a 9,007,199,254,740,991. Con dos decimales son unos 90 billones de pesos;\n// con más decimales, menos. Pasarse truena.\n//\n// Funciones puras, sin React: function y una clase de valor (no se modifica: cada operación regresa un monto nuevo).\nimport {intlLocaleOf, toolkitSettings} from '@/toolkit/toolkitSettings.js';\n\n/** Cómo se redondea al centavo lo que no cabe en centavos (al multiplicar, dividir, elevar o sacar raíz). */\nexport const MONEY_ROUNDING = Object.freeze({\n // la mitad se aleja del cero: 2.345 → 2.35 y −2.345 → −2.35 (como se redondea a mano)\n halfUp: 'halfUp',\n // la mitad va al par: 2.345 → 2.34 y 2.355 → 2.36 (redondeo bancario: en muchas sumas no carga hacia arriba)\n halfEven: 'halfEven',\n // corta hacia el cero: 2.349 → 2.34 (lo que hacen el Money de PHP y el de Go al leer)\n down: 'down',\n});\n\nconst DEFAULT_ROUNDING = MONEY_ROUNDING.halfUp;\n\n// un número simple: signo opcional, dígitos y, si hay punto, dígitos después. Sin comas, espacios ni exponente\nconst PLAIN_NUMBER = /^-?\\d+(\\.\\d+)?$/;\nconst DECIMAL_POINT = '.';\nconst NEGATIVE_SIGN = '-';\nconst TEN = 10n;\n\n// el formateador de Intl de cada idioma, moneda y decimales: crear uno por celda en una tabla de cientos se nota\nconst formatterCache = new Map();\n\n/**\n * Cuántos decimales lleva una moneda según Intl (ISO 4217): MXN y USD 2, JPY 0, KWD 3.\n *\n * @param {string} currency código ISO 4217\n * @returns {number}\n */\nfunction decimalsOfCurrency(currency) {\n return new Intl.NumberFormat('en', {style: 'currency', currency}).resolvedOptions().maximumFractionDigits;\n}\n\n/**\n * La moneda y los decimales de un monto nuevo: los que se piden o, si no, los del proveedor.\n *\n * OJO: la moneda se fija al CREAR el monto. Un monto armado antes de que ToolkitProvider ponga la moneda del proyecto\n * (una constante de módulo) se queda con la de omisión (MXN); para esos casos se pasa la moneda explícita.\n *\n * @param {{currency?: string, decimals?: number}} options\n * @returns {{currency: string, decimals: number}}\n */\nfunction settingsOf({currency, decimals} = {}) {\n const chosenCurrency = currency ?? toolkitSettings().currency;\n const chosenDecimals = decimals ?? decimalsOfCurrency(chosenCurrency);\n if (!Number.isInteger(chosenDecimals) || chosenDecimals < 0) {\n throw new RangeError(`Los decimales de un monto son un entero de 0 en adelante, no ${decimals}`);\n }\n\n return {currency: chosenCurrency, decimals: chosenDecimals};\n}\n\n/**\n * Un número simple en texto como entero con su escala: '-12.345' → {units: -12345n, scale: 3}.\n *\n * @param {string} text ya revisado con PLAIN_NUMBER\n * @returns {{units: bigint, scale: number}}\n */\nfunction scaledIntegerOf(text) {\n const [integerText, decimalText = ''] = text.split(DECIMAL_POINT);\n return {units: BigInt(`${integerText}${decimalText}`), scale: decimalText.length};\n}\n\n/**\n * El texto de un número de JavaScript como lo escribiría una persona: 2450.5 → '2450.5'. JavaScript escribe el número\n * más corto que vuelve al mismo valor, así que lo que llegó como 2450.55 en el JSON sale como '2450.55'.\n *\n * @param {number} value\n * @returns {string}\n */\nfunction textOfNumber(value) {\n if (!Number.isFinite(value)) {\n throw new TypeError(`${value} no es un monto de dinero`);\n }\n return String(value);\n}\n\n/**\n * Un factor o divisor (1.16, '0.16', 3) como entero con su escala, sin pasar por decimales.\n *\n * @param {number|string} value\n * @returns {{units: bigint, scale: number}}\n */\nfunction factorOf(value) {\n const text = typeof value === 'number' ? textOfNumber(value) : value;\n if (typeof text !== 'string' || !PLAIN_NUMBER.test(text)) {\n throw new TypeError(`«${value}» no es un número simple para operar con un monto (sin comas, espacios ni exponente)`);\n }\n return scaledIntegerOf(text);\n}\n\n/**\n * Divide dos enteros grandes y redondea el resultado a entero con el modo pedido.\n *\n * @param {bigint} numerator\n * @param {bigint} denominator distinto de cero\n * @param {string} rounding uno de MONEY_ROUNDING\n * @returns {bigint}\n */\nfunction divideRounded(numerator, denominator, rounding) {\n const isNegative = (numerator < 0n) !== (denominator < 0n);\n const positiveNumerator = numerator < 0n ? -numerator : numerator;\n const positiveDenominator = denominator < 0n ? -denominator : denominator;\n let quotient = positiveNumerator / positiveDenominator;\n // lo que sobra, por dos: comparado con el divisor dice si lo que sobra pasa de la mitad, es la mitad o no llega\n const twiceRemainder = (positiveNumerator % positiveDenominator) * 2n;\n\n if (rounding === MONEY_ROUNDING.halfUp && twiceRemainder >= positiveDenominator) {\n quotient += 1n;\n } else if (rounding === MONEY_ROUNDING.halfEven\n && (twiceRemainder > positiveDenominator || (twiceRemainder === positiveDenominator && quotient % 2n === 1n))) {\n quotient += 1n;\n } else if (!Object.values(MONEY_ROUNDING).includes(rounding)) {\n throw new RangeError(`«${rounding}» no es un modo de redondeo de MONEY_ROUNDING`);\n }\n\n return isNegative ? -quotient : quotient;\n}\n\n/**\n * La raíz cuadrada entera (hacia abajo) de un entero grande que no es negativo.\n *\n * @param {bigint} value\n * @returns {bigint}\n */\nfunction floorSquareRoot(value) {\n // la raíz con decimales de JavaScript da un punto de partida casi exacto; los dos ciclos lo dejan exacto\n let root = BigInt(Math.floor(Math.sqrt(Number(value))));\n while (root * root > value) {\n root -= 1n;\n }\n while ((root + 1n) * (root + 1n) <= value) {\n root += 1n;\n }\n return root;\n}\n\n/**\n * Un entero grande como centavos de JavaScript, si cabe.\n *\n * @param {bigint} minorUnits\n * @returns {number}\n */\nfunction safeMinorUnitsOf(minorUnits) {\n if (minorUnits > BigInt(Number.MAX_SAFE_INTEGER) || minorUnits < BigInt(Number.MIN_SAFE_INTEGER)) {\n throw new RangeError('El monto pasa del tope que JavaScript guarda exacto (unos 90 billones con dos decimales)');\n }\n return Number(minorUnits);\n}\n\nexport class Money {\n /**\n * Centavos (la unidad menor de la moneda): 1050 son $10.50.\n *\n * @readonly\n * @type {number}\n */\n minorUnits;\n\n /**\n * Código ISO 4217 de la moneda.\n *\n * @readonly\n * @type {string}\n */\n currency;\n\n /**\n * Cuántos decimales lleva.\n *\n * @readonly\n * @type {number}\n */\n decimals;\n\n /**\n * No se usa directo: los montos se arman con Money.fromString, Money.fromNumber, Money.fromMinorUnits o Money.zero.\n *\n * @param {number} minorUnits centavos (la unidad menor de la moneda), entero\n * @param {string} currency código ISO 4217\n * @param {number} decimals cuántos decimales lleva\n */\n constructor(minorUnits, currency, decimals) {\n if (!Number.isSafeInteger(minorUnits)) {\n throw new RangeError(`Un monto se guarda en centavos enteros; ${minorUnits} no lo es o pasa del tope de JavaScript`);\n }\n this.minorUnits = minorUnits;\n this.currency = currency;\n this.decimals = decimals;\n // un monto no cambia nunca: cada operación regresa uno nuevo\n Object.freeze(this);\n }\n\n /**\n * Cero, para arrancar una suma.\n *\n * @param {object} [options]\n * @param {string} [options.currency] código ISO 4217; por omisión, la del proveedor\n * @param {number} [options.decimals] por omisión, los de la moneda\n * @returns {Money}\n */\n static zero(options) {\n const {currency, decimals} = settingsOf(options);\n return new Money(0, currency, decimals);\n }\n\n /**\n * Un monto a partir del texto que manda el API o la base ('1234.50', '-3', '0.5').\n *\n * @param {string} text un número simple: sin comas, espacios, símbolo ni exponente\n * @param {object} [options]\n * @param {string} [options.currency] código ISO 4217; por omisión, la del proveedor\n * @param {number} [options.decimals] por omisión, los de la moneda\n * @returns {Money}\n */\n static fromString(text, options) {\n const {currency, decimals} = settingsOf(options);\n if (typeof text !== 'string' || !PLAIN_NUMBER.test(text)) {\n throw new TypeError(`«${text}» no es un monto de dinero: se espera un número simple como '1234.50'`);\n }\n\n const {units, scale} = scaledIntegerOf(text);\n const extraDecimals = scale - decimals;\n // con decimales de menos se completa con ceros; con decimales de más solo entra si lo de más son ceros\n if (extraDecimals <= 0) {\n return new Money(safeMinorUnitsOf(units * TEN ** BigInt(-extraDecimals)), currency, decimals);\n }\n const divisor = TEN ** BigInt(extraDecimals);\n if (units % divisor !== 0n) {\n throw new RangeError(`«${text}» trae más de ${decimals} decimales; para no perder centavos, configure más decimales`);\n }\n\n return new Money(safeMinorUnitsOf(units / divisor), currency, decimals);\n }\n\n /**\n * Un monto a partir de un número del JSON del API (2450.5). Lo que trae decimales de más (lo que deja hacer cuentas\n * con decimales, como 0.30000000000000004) truena igual que en fromString.\n *\n * @param {number} value\n * @param {object} [options]\n * @param {string} [options.currency] código ISO 4217; por omisión, la del proveedor\n * @param {number} [options.decimals] por omisión, los de la moneda\n * @returns {Money}\n */\n static fromNumber(value, options) {\n if (typeof value !== 'number') {\n throw new TypeError(`fromNumber recibe un número; para el texto del API use fromString («${value}»)`);\n }\n return Money.fromString(textOfNumber(value), options);\n }\n\n /**\n * Un monto a partir de sus centavos enteros (1050 son $10.50).\n *\n * @param {number} minorUnits\n * @param {object} [options]\n * @param {string} [options.currency] código ISO 4217; por omisión, la del proveedor\n * @param {number} [options.decimals] por omisión, los de la moneda\n * @returns {Money}\n */\n static fromMinorUnits(minorUnits, options) {\n const {currency, decimals} = settingsOf(options);\n return new Money(minorUnits, currency, decimals);\n }\n\n /**\n * Revisa que el otro monto sea de la misma moneda y con los mismos decimales.\n *\n * @param {Money} other\n * @returns {void}\n */\n #assertSameKind(other) {\n if (!(other instanceof Money)) {\n throw new TypeError('Solo se opera un monto con otro Money; arme el otro con Money.fromString o Money.fromNumber');\n }\n if (other.currency !== this.currency || other.decimals !== this.decimals) {\n throw new RangeError(`No se mezclan ${this.currency} con ${this.decimals} decimales y ${other.currency} con ${other.decimals}`);\n }\n }\n\n /**\n * Un monto nuevo de la misma moneda a partir de un entero grande de centavos.\n *\n * @param {bigint} minorUnits\n * @returns {Money}\n */\n #withMinorUnits(minorUnits) {\n return new Money(safeMinorUnitsOf(minorUnits), this.currency, this.decimals);\n }\n\n /**\n * Este monto más otro.\n *\n * @param {Money} other\n * @returns {Money}\n */\n plus(other) {\n this.#assertSameKind(other);\n return this.#withMinorUnits(BigInt(this.minorUnits) + BigInt(other.minorUnits));\n }\n\n /**\n * Este monto menos otro.\n *\n * @param {Money} other\n * @returns {Money}\n */\n minus(other) {\n this.#assertSameKind(other);\n return this.#withMinorUnits(BigInt(this.minorUnits) - BigInt(other.minorUnits));\n }\n\n /**\n * Este monto por un factor (1.16 para el IVA, 3 piezas, '0.5'), redondeado al centavo.\n *\n * @param {number|string} factor un número simple; mejor en texto si viene de una tasa ('0.16')\n * @param {object} [options]\n * @param {string} [options.rounding] uno de MONEY_ROUNDING; por omisión halfUp\n * @returns {Money}\n */\n times(factor, {rounding = DEFAULT_ROUNDING} = {}) {\n const {units, scale} = factorOf(factor);\n return this.#withMinorUnits(divideRounded(BigInt(this.minorUnits) * units, TEN ** BigInt(scale), rounding));\n }\n\n /**\n * Este monto entre un divisor (3 pagos, '1.16' para quitar el IVA), redondeado al centavo.\n *\n * OJO: tres pagos de un tercio redondeado no siempre suman el total (10.00 / 3 = 3.33 y 3 × 3.33 = 9.99). Si las\n * partes tienen que sumar el total exacto, la última se calcula restando las demás.\n *\n * @param {number|string} divisor un número simple, distinto de cero\n * @param {object} [options]\n * @param {string} [options.rounding] uno de MONEY_ROUNDING; por omisión halfUp\n * @returns {Money}\n */\n dividedBy(divisor, {rounding = DEFAULT_ROUNDING} = {}) {\n const {units, scale} = factorOf(divisor);\n if (units === 0n) {\n throw new RangeError('Un monto no se divide entre cero');\n }\n return this.#withMinorUnits(divideRounded(BigInt(this.minorUnits) * TEN ** BigInt(scale), units, rounding));\n }\n\n /**\n * Este monto elevado a una potencia entera, redondeado al centavo: (1.05)² = 1.1025 → 1.10.\n *\n * @param {number} exponent entero de 0 en adelante\n * @param {object} [options]\n * @param {string} [options.rounding] uno de MONEY_ROUNDING; por omisión halfUp\n * @returns {Money}\n */\n pow(exponent, {rounding = DEFAULT_ROUNDING} = {}) {\n if (!Number.isInteger(exponent) || exponent < 0) {\n throw new RangeError(`La potencia de un monto es un entero de 0 en adelante, no ${exponent}; la raíz cuadrada es sqrt()`);\n }\n // el monto es centavos / 10^decimales; elevado a la n y vuelto a centavos queda centavos^n / 10^(decimales·(n−1))\n const scale = TEN ** BigInt(this.decimals);\n const power = BigInt(exponent);\n return this.#withMinorUnits(divideRounded(BigInt(this.minorUnits) ** power * scale, scale ** power, rounding));\n }\n\n /**\n * La raíz cuadrada de este monto, redondeada al centavo: √2.00 = 1.414… → 1.41.\n *\n * @param {object} [options]\n * @param {string} [options.rounding] uno de MONEY_ROUNDING; por omisión halfUp (en una raíz nunca cae justo en la\n * mitad, así que halfEven da lo mismo)\n * @returns {Money}\n */\n sqrt({rounding = DEFAULT_ROUNDING} = {}) {\n if (this.minorUnits < 0) {\n throw new RangeError('Un monto negativo no tiene raíz cuadrada');\n }\n if (!Object.values(MONEY_ROUNDING).includes(rounding)) {\n throw new RangeError(`«${rounding}» no es un modo de redondeo de MONEY_ROUNDING`);\n }\n // la raíz en centavos es √(centavos × 10^decimales)\n const radicand = BigInt(this.minorUnits) * TEN ** BigInt(this.decimals);\n const root = floorSquareRoot(radicand);\n // ¿pasa de la mitad? (raíz + ½)² ≤ radicando, multiplicado por 4 para no salir de los enteros\n const passesHalf = (2n * root + 1n) ** 2n <= 4n * radicand;\n const roundsUp = rounding !== MONEY_ROUNDING.down && passesHalf;\n\n return this.#withMinorUnits(roundsUp ? root + 1n : root);\n }\n\n /**\n * Si los dos montos valen exactamente lo mismo, hasta el centavo.\n *\n * @param {Money} other\n * @returns {boolean}\n */\n equals(other) {\n this.#assertSameKind(other);\n return this.minorUnits === other.minorUnits;\n }\n\n /**\n * Si este monto es mayor que otro. El centavo de diferencia cuenta.\n *\n * @param {Money} other\n * @returns {boolean}\n */\n isGreaterThan(other) {\n this.#assertSameKind(other);\n return this.minorUnits > other.minorUnits;\n }\n\n /**\n * Si el monto es cero o negativo.\n *\n * @returns {boolean}\n */\n isZeroOrLess() {\n return this.minorUnits <= 0;\n }\n\n /**\n * El monto como texto, con todos sus decimales: '1234.50'. Es lo que se le manda al API para una columna NUMERIC.\n *\n * @returns {string}\n */\n amount() {\n const sign = this.minorUnits < 0 ? NEGATIVE_SIGN : '';\n // los centavos con ceros a la izquierda hasta tener un entero y sus decimales: 5 → '005' → '0.05'\n const digits = String(Math.abs(this.minorUnits)).padStart(this.decimals + 1, '0');\n if (this.decimals === 0) {\n return `${sign}${digits}`;\n }\n return `${sign}${digits.slice(0, -this.decimals)}${DECIMAL_POINT}${digits.slice(-this.decimals)}`;\n }\n\n /**\n * El monto como lo lee una persona, en el idioma del proveedor y con el símbolo de su moneda: $1,234.50 (es) o\n * $1,234.50 (en); US$ o ¥ según la moneda. Sin pasar por decimales: Intl recibe el texto exacto.\n *\n * @returns {string}\n */\n format() {\n const locale = intlLocaleOf(toolkitSettings().language);\n const cacheKey = `${locale}|${this.currency}|${this.decimals}`;\n if (!formatterCache.has(cacheKey)) {\n formatterCache.set(cacheKey, new Intl.NumberFormat(locale, {\n style: 'currency', currency: this.currency, currencyDisplay: 'narrowSymbol',\n minimumFractionDigits: this.decimals, maximumFractionDigits: this.decimals,\n }));\n }\n return formatterCache.get(cacheKey).format(this.amount());\n }\n\n /**\n * Para que JSON.stringify mande el texto del monto ('1234.50') y no un objeto.\n *\n * @returns {string}\n */\n toJSON() {\n return this.amount();\n }\n\n /**\n * Para que un texto con el monto adentro (`${total}`) diga '1234.50'.\n *\n * @returns {string}\n */\n toString() {\n return this.amount();\n }\n\n /**\n * Truena a propósito: `total + iva` o `total > limit` regresarían a los números con decimales sin que nadie se dé\n * cuenta. Se usa plus, minus, isGreaterThan...\n *\n * @returns {never}\n */\n valueOf() {\n throw new TypeError('Un Money no se opera con + - * / > <: use plus, minus, times, dividedBy, isGreaterThan o equals');\n }\n}\n"],"names":[],"mappings":"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"}
package/dist/money.js ADDED
@@ -0,0 +1,6 @@
1
+ import { MONEY_ROUNDING, Money } from "./money/money.js";
2
+ export {
3
+ MONEY_ROUNDING,
4
+ Money
5
+ };
6
+ //# sourceMappingURL=money.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"money.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -0,0 +1,93 @@
1
+ const LAST_ORDER = 1e3;
2
+ const HOME_PATH = "/";
3
+ function composeMenu(menuModules, { canAccess = () => true, context = {} } = {}) {
4
+ const modules = Array.isArray(menuModules) ? menuModules : Object.values(menuModules);
5
+ return modules.filter((menuModule) => canAccess(menuModule.access)).sort((first, second) => (first.order ?? LAST_ORDER) - (second.order ?? LAST_ORDER)).flatMap((menuModule) => menuModule.buildMenuItems?.(context) ?? [menuModule.buildMenuItem?.(context)]).filter((menuItem) => Boolean(menuItem) && canAccess(menuItem.access)).map((menuItem) => withAllowedChildren(menuItem, canAccess)).filter((menuItem) => Boolean(menuItem.to) || menuItem.children?.length > 0);
6
+ }
7
+ function withAllowedChildren(menuItem, canAccess) {
8
+ if (!Array.isArray(menuItem.children)) {
9
+ return menuItem;
10
+ }
11
+ return { ...menuItem, children: menuItem.children.filter((child) => Boolean(child) && canAccess(child.access)) };
12
+ }
13
+ function screenMenuItemsOf(menuItems) {
14
+ return menuItems.flatMap((menuItem) => [menuItem, ...menuItem.children ?? []]).filter((menuItem) => Boolean(menuItem.to));
15
+ }
16
+ function isChildMenuItem(menuItems, menuItem) {
17
+ return menuItems.some((candidate) => candidate.children?.includes(menuItem));
18
+ }
19
+ function activeMenuItemOf(menuItems, pathname) {
20
+ const matchingItems = screenMenuItemsOf(menuItems).filter((menuItem) => {
21
+ const prefix = menuItem.matchPrefix ?? menuItem.to;
22
+ const isHome = prefix === HOME_PATH;
23
+ return pathname === prefix || !isHome && pathname.startsWith(`${prefix}/`);
24
+ });
25
+ matchingItems.sort((first, second) => {
26
+ const lengthDifference = (second.matchPrefix ?? second.to).length - (first.matchPrefix ?? first.to).length;
27
+ if (lengthDifference !== 0) {
28
+ return lengthDifference;
29
+ }
30
+ return Number(isChildMenuItem(menuItems, second)) - Number(isChildMenuItem(menuItems, first));
31
+ });
32
+ return matchingItems[0] ?? null;
33
+ }
34
+ function parentMenuItemOf(menuItems, menuItem) {
35
+ return menuItems.find((candidate) => candidate.children?.includes(menuItem)) ?? null;
36
+ }
37
+ function menuBreadcrumbsOf(menuItems, pathname) {
38
+ const activeItem = activeMenuItemOf(menuItems, pathname);
39
+ if (!activeItem) {
40
+ return [];
41
+ }
42
+ const homeItem = menuItems.find((menuItem) => menuItem.to === HOME_PATH) ?? null;
43
+ const parentItem = parentMenuItemOf(menuItems, activeItem);
44
+ return [homeItem, parentItem, activeItem].filter((menuItem, index, crumbs) => Boolean(menuItem) && crumbs.indexOf(menuItem) === index);
45
+ }
46
+ function menuBadgeOf(menuItem, menuBadges = {}) {
47
+ const countOf = (item) => {
48
+ const count = item.badgeKey ? Number(menuBadges[item.badgeKey] ?? 0) : 0;
49
+ return Number.isFinite(count) && count > 0 ? count : 0;
50
+ };
51
+ const ownCount = countOf(menuItem);
52
+ const childrenCount = Array.isArray(menuItem.children) ? menuItem.children.reduce((total2, child) => total2 + countOf(child), 0) : 0;
53
+ const total = ownCount + childrenCount;
54
+ if (total > 0) {
55
+ return { content: total, isCount: true };
56
+ }
57
+ if (menuItem.badge !== void 0 && menuItem.badge !== null && menuItem.badge !== "") {
58
+ return { content: menuItem.badge, isCount: typeof menuItem.badge === "number" };
59
+ }
60
+ return null;
61
+ }
62
+ const MOBILE_TAB_LIMIT = 5;
63
+ const PINNABLE_TAB_LIMIT = MOBILE_TAB_LIMIT - 1;
64
+ function menuItemKeyOf(menuItem) {
65
+ return menuItem.to ?? menuItem.labelKey ?? menuItem.label;
66
+ }
67
+ function mobileTabsOf(menuItems, pinnedKeys = null, tabLimit = MOBILE_TAB_LIMIT) {
68
+ if (menuItems.length <= tabLimit) {
69
+ return { tabs: menuItems, more: [] };
70
+ }
71
+ const pinned = menuItems.filter((menuItem) => (pinnedKeys ?? []).includes(menuItemKeyOf(menuItem)));
72
+ const marked = menuItems.filter((menuItem) => menuItem.mobileTab);
73
+ let candidates = menuItems;
74
+ if (pinned.length > 0) {
75
+ candidates = pinned;
76
+ } else if (marked.length > 0) {
77
+ candidates = marked;
78
+ }
79
+ const tabs = candidates.slice(0, Math.max(tabLimit - 1, 1));
80
+ return { tabs, more: menuItems.filter((menuItem) => !tabs.includes(menuItem)) };
81
+ }
82
+ export {
83
+ PINNABLE_TAB_LIMIT,
84
+ activeMenuItemOf,
85
+ composeMenu,
86
+ menuBadgeOf,
87
+ menuBreadcrumbsOf,
88
+ menuItemKeyOf,
89
+ mobileTabsOf,
90
+ parentMenuItemOf,
91
+ screenMenuItemsOf
92
+ };
93
+ //# sourceMappingURL=appMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appMenu.js","sources":["../../src/navigation/appMenu.js"],"sourcesContent":["// El menú de la app: COMPUESTO, no escrito.\n//\n// Cada módulo declara su entrada en su propia carpeta (modules/<módulo>/menu.js) y aquí solo se juntan, se filtran por\n// permiso y se ordenan. Módulo nuevo con menú = cero ediciones en una lista central, y nadie pisa la entrada del vecino al\n// resolver un merge.\n//\n// Forma de un menu.js:\n// export const order = 10; // posición en el menú (los que no dicen, al final)\n// export const access = {ability: 'orders.view'}; // la regla de quién lo ve (accessRules.js); sin ella, todos\n// export function buildMenuItem(context) { // o buildMenuItems (en plural) para dos o más entradas\n// return {\n// to: '/orders', label: 'Pedidos', // o labelKey: 'orders:menu.label' (se traduce al pintarse)\n// description: 'Todos los pedidos…', // o descriptionKey: para las tarjetas de un inicio\n// section: 'Operación', // o sectionKey: el título de la sección del menú lateral\n// Icon: ReceiptLongOutlinedIcon,\n// badge: 3, // opcional: el numerito o la palabra a la derecha («Nuevo»)\n// mobileTab: true, // opcional: va en la barra de pestañas del teléfono (mobileTabsOf)\n// badgeKey: 'pendingPayment', // opcional: su conteo llega del servidor (AppLayout menuBadges)\n// matchPrefix: '/orders', // opcional: desde dónde se marca activo (por omisión, to)\n// access: {...}, // opcional: una entrada con otra regla que su módulo\n// children: [{to: '/orders/returns', label: 'Devoluciones', access: {...}}], // opcional: un submenú\n// };\n// }\n// buildMenuItem puede regresar null (una pantalla apagada por configuración): no sale. Un submenú se filtra igual que las\n// entradas, y si se queda sin hijas (y no lleva a ninguna pantalla propia) no sale.\n//\n// El proyecto le pasa los módulos con el glob de Vite (o una lista, en otro empaquetador):\n// const menuModules = import.meta.glob('@/modules/*/menu.js', {eager: true});\n// const menuItems = composeMenu(menuModules, {canAccess, context: {session}});\n//\n// Funciones puras, sin React: function (regla de la casa). Se prueban con node --test (appMenu.test.js).\n\n// la posición de un módulo que no dice su order: al final\nconst LAST_ORDER = 1000;\n\n// la dirección del inicio: la primera miga\nconst HOME_PATH = '/';\n\n/**\n * Las entradas del menú que le tocan a esta sesión, ordenadas.\n *\n * @param {Record<string, any>|any[]} menuModules lo que regresa import.meta.glob(..., {eager: true}) o una lista\n * @param {object} [options]\n * @param {(access: object|undefined) => boolean} [options.canAccess] la regla de permisos del proyecto; sin ella, todos\n * @param {object} [options.context] lo que reciben buildMenuItem(s): la sesión, la configuración…\n * @returns {object[]} las entradas, cada una con to y su texto\n */\nexport function composeMenu(menuModules, {canAccess = () => true, context = {}} = {}) {\n const modules = Array.isArray(menuModules) ? menuModules : Object.values(menuModules);\n return modules\n .filter((menuModule) => canAccess(menuModule.access))\n .sort((first, second) => (first.order ?? LAST_ORDER) - (second.order ?? LAST_ORDER))\n .flatMap((menuModule) => menuModule.buildMenuItems?.(context) ?? [menuModule.buildMenuItem?.(context)])\n .filter((menuItem) => Boolean(menuItem) && canAccess(menuItem.access))\n .map((menuItem) => withAllowedChildren(menuItem, canAccess))\n .filter((menuItem) => Boolean(menuItem.to) || menuItem.children?.length > 0);\n}\n\n/**\n * La entrada con solo las hijas que la sesión puede ver (una entrada sin submenú se queda igual).\n *\n * @param {object} menuItem\n * @param {(access: object|undefined) => boolean} canAccess\n * @returns {object}\n */\nfunction withAllowedChildren(menuItem, canAccess) {\n if (!Array.isArray(menuItem.children)) {\n return menuItem;\n }\n return {...menuItem, children: menuItem.children.filter((child) => Boolean(child) && canAccess(child.access))};\n}\n\n/**\n * Las entradas que llevan a una pantalla, con las de los submenús (las de arriba primero).\n *\n * @param {object[]} menuItems lo que regresa composeMenu\n * @returns {object[]}\n */\nexport function screenMenuItemsOf(menuItems) {\n return menuItems.flatMap((menuItem) => [menuItem, ...(menuItem.children ?? [])]).filter((menuItem) => Boolean(menuItem.to));\n}\n\n/**\n * ¿Está la entrada dentro de un submenú?\n *\n * @param {object[]} menuItems\n * @param {object} menuItem\n * @returns {boolean}\n */\nfunction isChildMenuItem(menuItems, menuItem) {\n return menuItems.some((candidate) => candidate.children?.includes(menuItem));\n}\n\n/**\n * La entrada del menú de la pantalla abierta: la más específica gana (/orders/15 marca «Pedidos», no «Inicio»).\n *\n * @param {Array<{to: string, matchPrefix?: string}>} menuItems lo que regresa composeMenu\n * @param {string} pathname location.pathname\n * @returns {object|null}\n */\nexport function activeMenuItemOf(menuItems, pathname) {\n const matchingItems = screenMenuItemsOf(menuItems).filter((menuItem) => {\n const prefix = menuItem.matchPrefix ?? menuItem.to;\n // el inicio solo se marca en el inicio: todas las direcciones empiezan con '/'\n const isHome = prefix === HOME_PATH;\n return pathname === prefix || (!isHome && pathname.startsWith(`${prefix}/`));\n });\n matchingItems.sort((first, second) => {\n const lengthDifference = (second.matchPrefix ?? second.to).length - (first.matchPrefix ?? first.to).length;\n if (lengthDifference !== 0) {\n return lengthDifference;\n }\n // con el mismo camino (un submenú cuya primera hija lleva a donde mismo que él), gana la hija: es la pantalla\n return Number(isChildMenuItem(menuItems, second)) - Number(isChildMenuItem(menuItems, first));\n });\n return matchingItems[0] ?? null;\n}\n\n/**\n * El submenú que contiene a una entrada (para abrirlo y para las migas); null si la entrada está arriba.\n *\n * @param {object[]} menuItems lo que regresa composeMenu\n * @param {object|null} menuItem\n * @returns {object|null}\n */\nexport function parentMenuItemOf(menuItems, menuItem) {\n return menuItems.find((candidate) => candidate.children?.includes(menuItem)) ?? null;\n}\n\n/**\n * Las migas de la pantalla abierta, sacadas del menú: el inicio, el submenú (si lo hay) y la entrada activa.\n * En el inicio, o en una pantalla que no está en el menú, regresa solo lo que encuentra (una o ninguna).\n *\n * @param {object[]} menuItems lo que regresa composeMenu\n * @param {string} pathname location.pathname\n * @returns {object[]} entradas del menú, en orden\n */\nexport function menuBreadcrumbsOf(menuItems, pathname) {\n const activeItem = activeMenuItemOf(menuItems, pathname);\n if (!activeItem) {\n return [];\n }\n const homeItem = menuItems.find((menuItem) => menuItem.to === HOME_PATH) ?? null;\n const parentItem = parentMenuItemOf(menuItems, activeItem);\n return [homeItem, parentItem, activeItem].filter((menuItem, index, crumbs) => Boolean(menuItem) && crumbs.indexOf(menuItem) === index);\n}\n\n/**\n * El badge de una entrada del menú: el conteo que llegó del servidor por su badgeKey (lo pendiente de esa pantalla), la\n * suma de sus hijas si es un submenú (como las carpetas del iPhone), o el badge fijo de su menu.js («Nuevo»). Un conteo\n * en cero no se enseña: no hay nada pendiente.\n *\n * menuBadgeOf({badgeKey: 'pendingPayment'}, {pendingPayment: 13}) // {content: 13, isCount: true}\n *\n * @param {object} menuItem una entrada de composeMenu\n * @param {Record<string, number>} [menuBadges] los conteos por badgeKey (el proyecto los pide a su servidor)\n * @returns {{content: number|string, isCount: boolean}|null}\n */\nexport function menuBadgeOf(menuItem, menuBadges = {}) {\n const countOf = (item) => {\n const count = item.badgeKey ? Number(menuBadges[item.badgeKey] ?? 0) : 0;\n return Number.isFinite(count) && count > 0 ? count : 0;\n };\n const ownCount = countOf(menuItem);\n const childrenCount = Array.isArray(menuItem.children) ? menuItem.children.reduce((total, child) => total + countOf(child), 0) : 0;\n const total = ownCount + childrenCount;\n if (total > 0) {\n return {content: total, isCount: true};\n }\n if (menuItem.badge !== undefined && menuItem.badge !== null && menuItem.badge !== '') {\n return {content: menuItem.badge, isCount: typeof menuItem.badge === 'number'};\n }\n return null;\n}\n\n// cuántas pestañas van en la barra del teléfono si no se dice otra cosa, como las de Apple: hasta 5; si hay más entradas,\n// 4 y «Más» con el resto. La barra (MobileTabBar) pasa las que de verdad caben a lo ancho\nconst MOBILE_TAB_LIMIT = 5;\n/** Cuántas puede fijar la persona en la barra: las que caben junto a «Más». */\nexport const PINNABLE_TAB_LIMIT = MOBILE_TAB_LIMIT - 1;\n\n/**\n * Con qué se reconoce una entrada del menú para recordarla (las pestañas que fijó la persona): su ruta, o su llave de\n * texto si no navega. No el texto traducido: cambia con el idioma.\n *\n * @param {{to?: string, labelKey?: string, label?: string}} menuItem\n * @returns {string}\n */\nexport function menuItemKeyOf(menuItem) {\n return menuItem.to ?? menuItem.labelKey ?? menuItem.label;\n}\n\n/**\n * Las pestañas de la barra del teléfono y lo que va en «Más». Van las que fijó la persona (pinnedKeys, en el orden del\n * menú); si no fijó ninguna, las que el menu.js marca con mobileTab: true; si ninguna lo dice, las primeras. Si todas\n * las entradas caben (tabLimit), van todas y no hay «Más»; si no, tabLimit - 1 y «Más» con el resto.\n *\n * @param {object[]} menuItems lo que regresa composeMenu\n * @param {string[]|null} [pinnedKeys] las que eligió la persona (menuItemKeyOf); las que ya no existen o ya no puede ver\n * no cuentan\n * @param {number} [tabLimit] cuántas caben en la barra contando «Más» (por omisión 5; la barra mide su ancho)\n * @returns {{tabs: object[], more: object[]}}\n */\nexport function mobileTabsOf(menuItems, pinnedKeys = null, tabLimit = MOBILE_TAB_LIMIT) {\n if (menuItems.length <= tabLimit) {\n return {tabs: menuItems, more: []};\n }\n const pinned = menuItems.filter((menuItem) => (pinnedKeys ?? []).includes(menuItemKeyOf(menuItem)));\n const marked = menuItems.filter((menuItem) => menuItem.mobileTab);\n let candidates = menuItems;\n if (pinned.length > 0) {\n candidates = pinned;\n } else if (marked.length > 0) {\n candidates = marked;\n }\n // una de las que caben es para «Más»\n const tabs = candidates.slice(0, Math.max(tabLimit - 1, 1));\n return {tabs, more: menuItems.filter((menuItem) => !tabs.includes(menuItem))};\n}\n"],"names":["total"],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ "use client";
2
+ import { useState, useRef, useCallback, useEffect } from "react";
3
+ function menuBadgesFrom(response) {
4
+ const isCount = (count) => count !== null && count !== void 0 && count !== "" && Number.isFinite(Number(count));
5
+ const list = Array.isArray(response) ? response : Array.isArray(response?.badges) ? response.badges : null;
6
+ if (list) {
7
+ return Object.fromEntries(list.filter((item) => item?.badgeKey && isCount(item.count)).map((item) => [item.badgeKey, Number(item.count)]));
8
+ }
9
+ if (response && typeof response === "object") {
10
+ return Object.fromEntries(Object.entries(response).filter(([, count]) => isCount(count)).map(([key, count]) => [key, Number(count)]));
11
+ }
12
+ return {};
13
+ }
14
+ function useMenuBadges(loadBadges) {
15
+ const [menuBadges, setMenuBadges] = useState({});
16
+ const [isLoading, setIsLoading] = useState(false);
17
+ const inflight = useRef(null);
18
+ const loadRef = useRef(loadBadges);
19
+ loadRef.current = loadBadges;
20
+ const refreshMenuBadges = useCallback(() => {
21
+ if (inflight.current) {
22
+ return inflight.current;
23
+ }
24
+ setIsLoading(true);
25
+ inflight.current = (async () => {
26
+ try {
27
+ setMenuBadges(menuBadgesFrom(await loadRef.current()));
28
+ } catch {
29
+ } finally {
30
+ setIsLoading(false);
31
+ inflight.current = null;
32
+ }
33
+ })();
34
+ return inflight.current;
35
+ }, []);
36
+ useEffect(() => {
37
+ refreshMenuBadges();
38
+ }, [refreshMenuBadges]);
39
+ return { menuBadges, refreshMenuBadges, isLoading };
40
+ }
41
+ export {
42
+ menuBadgesFrom,
43
+ useMenuBadges
44
+ };
45
+ //# sourceMappingURL=useMenuBadges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMenuBadges.js","sources":["../../src/navigation/useMenuBadges.js"],"sourcesContent":["// Los conteos de los badges del menú (lo pendiente de cada pantalla), pedidos al servidor del proyecto: AppLayout los pinta\n// por el badgeKey de cada entrada (navigation/appMenu.js, menuBadgeOf).\n//\n// const {menuBadges, refreshMenuBadges} = useMenuBadges(() => api.get('/users/badges'));\n// <AppLayout menuBadges={menuBadges} …>\n//\n// El servidor puede contestar una lista [{badgeKey, count}] o un objeto {badgeKey: count}: los dos se aceptan.\n// refreshMenuBadges() los vuelve a pedir (después de aprobar o rechazar algo); si se llama varias veces seguidas, se pide\n// una sola vez: las demás esperan la misma respuesta. Si la petición falla, se quedan los conteos de antes (un badge viejo\n// es mejor que un menú que truena).\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useCallback, useEffect, useRef, useState} from 'react';\n\n/**\n * La respuesta del servidor como {badgeKey: conteo}.\n *\n * @param {unknown} response\n * @returns {Record<string, number>}\n */\nexport function menuBadgesFrom(response) {\n // OJO: Number(null) es 0 y pasaría como conteo: lo que llega vacío no es un número\n const isCount = (count) => count !== null && count !== undefined && count !== '' && Number.isFinite(Number(count));\n const list = Array.isArray(response) ? response : (Array.isArray(response?.badges) ? response.badges : null);\n if (list) {\n return Object.fromEntries(list\n .filter((item) => item?.badgeKey && isCount(item.count))\n .map((item) => [item.badgeKey, Number(item.count)]));\n }\n if (response && typeof response === 'object') {\n return Object.fromEntries(Object.entries(response).filter(([, count]) => isCount(count)).map(([key, count]) => [key, Number(count)]));\n }\n return {};\n}\n\n/**\n * @param {() => Promise<unknown>} loadBadges pide los conteos al servidor\n * @returns {{menuBadges: Record<string, number>, refreshMenuBadges: () => Promise<void>, isLoading: boolean}}\n */\nexport function useMenuBadges(loadBadges) {\n const [menuBadges, setMenuBadges] = useState({});\n const [isLoading, setIsLoading] = useState(false);\n // la petición en curso: si ya hay una, las demás llamadas esperan esa\n const inflight = useRef(null);\n // la función más reciente del proyecto, sin volver a pedir cada que se pinta\n const loadRef = useRef(loadBadges);\n loadRef.current = loadBadges;\n\n const refreshMenuBadges = useCallback(() => {\n if (inflight.current) {\n return inflight.current;\n }\n setIsLoading(true);\n inflight.current = (async () => {\n try {\n setMenuBadges(menuBadgesFrom(await loadRef.current()));\n } catch {\n // se quedan los conteos de antes\n } finally {\n setIsLoading(false);\n inflight.current = null;\n }\n })();\n return inflight.current;\n }, []);\n\n useEffect(() => {\n refreshMenuBadges();\n }, [refreshMenuBadges]);\n\n return {menuBadges, refreshMenuBadges, isLoading};\n}\n"],"names":[],"mappings":";;AAoBO,SAAS,eAAe,UAAU;AAErC,QAAM,UAAU,CAAC,UAAU,UAAU,QAAQ,UAAU,UAAa,UAAU,MAAM,OAAO,SAAS,OAAO,KAAK,CAAC;AACjH,QAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI,WAAY,MAAM,QAAQ,UAAU,MAAM,IAAI,SAAS,SAAS;AACvG,MAAI,MAAM;AACN,WAAO,OAAO,YAAY,KACrB,OAAO,CAAC,SAAS,MAAM,YAAY,QAAQ,KAAK,KAAK,CAAC,EACtD,IAAI,CAAC,SAAS,CAAC,KAAK,UAAU,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC;AAAA,EAC3D;AACA,MAAI,YAAY,OAAO,aAAa,UAAU;AAC1C,WAAO,OAAO,YAAY,OAAO,QAAQ,QAAQ,EAAE,OAAO,CAAC,GAAG,KAAK,MAAM,QAAQ,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,OAAO,KAAK,CAAC,CAAC,CAAC;AAAA,EACxI;AACA,SAAO,CAAA;AACX;AAMO,SAAS,cAAc,YAAY;AACtC,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,CAAA,CAAE;AAC/C,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAEhD,QAAM,WAAW,OAAO,IAAI;AAE5B,QAAM,UAAU,OAAO,UAAU;AACjC,UAAQ,UAAU;AAElB,QAAM,oBAAoB,YAAY,MAAM;AACxC,QAAI,SAAS,SAAS;AAClB,aAAO,SAAS;AAAA,IACpB;AACA,iBAAa,IAAI;AACjB,aAAS,WAAW,YAAY;AAC5B,UAAI;AACA,sBAAc,eAAe,MAAM,QAAQ,QAAO,CAAE,CAAC;AAAA,MACzD,QAAQ;AAAA,MAER,UAAC;AACG,qBAAa,KAAK;AAClB,iBAAS,UAAU;AAAA,MACvB;AAAA,IACJ,GAAC;AACD,WAAO,SAAS;AAAA,EACpB,GAAG,CAAA,CAAE;AAEL,YAAU,MAAM;AACZ,sBAAiB;AAAA,EACrB,GAAG,CAAC,iBAAiB,CAAC;AAEtB,SAAO,EAAC,YAAY,mBAAmB,UAAS;AACpD;"}