@stackcraftmx/calcita 0.0.0-stage → 0.23.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.
- package/LICENSE +110 -0
- package/README.md +611 -2
- package/cli/askQuestions.js +63 -0
- package/cli/calcita.js +150 -0
- package/cli/makeComponent.js +50 -0
- package/cli/makeForm.js +68 -0
- package/cli/makeModule.js +78 -0
- package/cli/makePage.js +62 -0
- package/cli/names.js +64 -0
- package/cli/newProject.js +103 -0
- package/cli/packageVersions.js +38 -0
- package/cli/projectAnswers.js +145 -0
- package/cli/projectConfig.js +38 -0
- package/cli/projectFiles.js +126 -0
- package/cli/screenLabels.js +41 -0
- package/cli/templateFiles.js +186 -0
- package/cli/templates/component/core/__ComponentName__.jsx.tpl +23 -0
- package/cli/templates/component/module/__ComponentName__.jsx.tpl +21 -0
- package/cli/templates/form/formik/__FormName__.jsx.tpl +50 -0
- package/cli/templates/form/hookForm/__FormName__.jsx.tpl +53 -0
- package/cli/templates/form/shared/__formName__Schema.js.tpl +20 -0
- package/cli/templates/form/shared/__formName__Texts.js.tpl +6 -0
- package/cli/templates/module/__Name__Page.jsx.tpl +75 -0
- package/cli/templates/module/__name__Api.js.tpl +39 -0
- package/cli/templates/module/__name__Texts.js.tpl +27 -0
- package/cli/templates/module/menu.js.tpl +21 -0
- package/cli/templates/module/routes.js.tpl +7 -0
- package/cli/templates/moduleServer/__name__Server.js.tpl +68 -0
- package/cli/templates/page/__PageName__Page.jsx.tpl +22 -0
- package/cli/templates/page/__pageName__PageTexts.js.tpl +23 -0
- package/cli/templates/project/README.md.tpl +55 -0
- package/cli/templates/project/dot-gitignore.tpl +11 -0
- package/cli/templates/project/index.html.tpl +20 -0
- package/cli/templates/project/jsconfig.json.tpl +16 -0
- package/cli/templates/project/pnpm-workspace.yaml.tpl +5 -0
- package/cli/templates/project/public/favicon.svg +1 -0
- package/cli/templates/project/public/icons/apple-touch-icon.png +0 -0
- package/cli/templates/project/public/icons/icon-192.png +0 -0
- package/cli/templates/project/public/icons/icon-512-maskable.png +0 -0
- package/cli/templates/project/public/icons/icon-512.png +0 -0
- package/cli/templates/project/public/manifest.webmanifest.tpl +17 -0
- package/cli/templates/project/src/app/AppProviders.jsx.tpl +102 -0
- package/cli/templates/project/src/app/AppShell.jsx.tpl +87 -0
- package/cli/templates/project/src/app/appRouter.jsx.tpl +49 -0
- package/cli/templates/project/src/app/appSettings.js.tpl +13 -0
- package/cli/templates/project/src/app/appTexts.js.tpl +15 -0
- package/cli/templates/project/src/app/combineTexts.js.tpl +31 -0
- package/cli/templates/project/src/app/i18n.js.tpl +19 -0
- package/cli/templates/project/src/app/shellTexts.js.tpl +16 -0
- package/cli/templates/project/src/core/AppLogo.jsx.tpl +12 -0
- package/cli/templates/project/src/core/accountConnector.js.tpl +36 -0
- package/cli/templates/project/src/core/apiClient.js.tpl +15 -0
- package/cli/templates/project/src/core/appPaths.js.tpl +11 -0
- package/cli/templates/project/src/core/index.js.tpl +8 -0
- package/cli/templates/project/src/fakeServer/networkDelay.js.tpl +40 -0
- package/cli/templates/project/src/fakeServer/serverText.js.tpl +20 -0
- package/cli/templates/project/src/main.jsx.tpl +24 -0
- package/cli/templates/project/src/modules/auth/ForgotPasswordPage.jsx.tpl +14 -0
- package/cli/templates/project/src/modules/auth/ResetPasswordPage.jsx.tpl +15 -0
- package/cli/templates/project/src/modules/auth/SignInPage.jsx.tpl +29 -0
- package/cli/templates/project/src/modules/auth/authTexts.js.tpl +6 -0
- package/cli/templates/project/src/modules/auth/routes.js.tpl +11 -0
- package/cli/templates/project/src/modules/home/HomePage.jsx.tpl +38 -0
- package/cli/templates/project/src/modules/home/homeTexts.js.tpl +29 -0
- package/cli/templates/project/src/modules/home/menu.js.tpl +17 -0
- package/cli/templates/project/src/modules/home/routes.js.tpl +4 -0
- package/cli/templates/project/src/modules/profile/ProfilePage.jsx.tpl +13 -0
- package/cli/templates/project/src/modules/profile/routes.js.tpl +6 -0
- package/cli/templates/project/vite.config.js.tpl +27 -0
- package/dist/DataTable/AuditTrailDialog.js +40 -0
- package/dist/DataTable/AuditTrailDialog.js.map +1 -0
- package/dist/DataTable/AuditTrailTable.js +87 -0
- package/dist/DataTable/AuditTrailTable.js.map +1 -0
- package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js +71 -0
- package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js.map +1 -0
- package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js +50 -0
- package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js.map +1 -0
- package/dist/DataTable/ColumnFilters/SortableFilterHeader.js +54 -0
- package/dist/DataTable/ColumnFilters/SortableFilterHeader.js.map +1 -0
- package/dist/DataTable/ColumnFilters/TextColumnFilter.js +24 -0
- package/dist/DataTable/ColumnFilters/TextColumnFilter.js.map +1 -0
- package/dist/DataTable/EmptyState.js +22 -0
- package/dist/DataTable/EmptyState.js.map +1 -0
- package/dist/DataTable/FilterChips.js +39 -0
- package/dist/DataTable/FilterChips.js.map +1 -0
- package/dist/DataTable/GoToPage.js +62 -0
- package/dist/DataTable/GoToPage.js.map +1 -0
- package/dist/DataTable/ServerTable.js +407 -0
- package/dist/DataTable/ServerTable.js.map +1 -0
- package/dist/DataTable/buildChipConfig.js +27 -0
- package/dist/DataTable/buildChipConfig.js.map +1 -0
- package/dist/DataTable/columns.js +122 -0
- package/dist/DataTable/columns.js.map +1 -0
- package/dist/DataTable/filterContext.js +15 -0
- package/dist/DataTable/filterContext.js.map +1 -0
- package/dist/DataTable/serverTableParams.js +19 -0
- package/dist/DataTable/serverTableParams.js.map +1 -0
- package/dist/DataTable/tableMachine.js +87 -0
- package/dist/DataTable/tableMachine.js.map +1 -0
- package/dist/DataTable/useDebouncedFilter.js +29 -0
- package/dist/DataTable/useDebouncedFilter.js.map +1 -0
- package/dist/DataTable/useTableState.js +132 -0
- package/dist/DataTable/useTableState.js.map +1 -0
- package/dist/access/Can.js +9 -0
- package/dist/access/Can.js.map +1 -0
- package/dist/access/PermissionMatrix.js +83 -0
- package/dist/access/PermissionMatrix.js.map +1 -0
- package/dist/access/RequireAccess.js +14 -0
- package/dist/access/RequireAccess.js.map +1 -0
- package/dist/access/accessRules.js +49 -0
- package/dist/access/accessRules.js.map +1 -0
- package/dist/access/permissionGroups.js +43 -0
- package/dist/access/permissionGroups.js.map +1 -0
- package/dist/access/useCan.js +12 -0
- package/dist/access/useCan.js.map +1 -0
- package/dist/account/AccountProvider.js +58 -0
- package/dist/account/AccountProvider.js.map +1 -0
- package/dist/account/AccountSecuritySection.js +81 -0
- package/dist/account/AccountSecuritySection.js.map +1 -0
- package/dist/account/DemoTotpCodeButton.js +26 -0
- package/dist/account/DemoTotpCodeButton.js.map +1 -0
- package/dist/account/ForgotPasswordScreen.js +26 -0
- package/dist/account/ForgotPasswordScreen.js.map +1 -0
- package/dist/account/ProfileScreen.js +108 -0
- package/dist/account/ProfileScreen.js.map +1 -0
- package/dist/account/ResetPasswordScreen.js +57 -0
- package/dist/account/ResetPasswordScreen.js.map +1 -0
- package/dist/account/SignInScreen.js +101 -0
- package/dist/account/SignInScreen.js.map +1 -0
- package/dist/account/accountConnector.js +31 -0
- package/dist/account/accountConnector.js.map +1 -0
- package/dist/account/demo/createDemoAccountConnector.js +368 -0
- package/dist/account/demo/createDemoAccountConnector.js.map +1 -0
- package/dist/account/demo/totp.js +61 -0
- package/dist/account/demo/totp.js.map +1 -0
- package/dist/account/restAccountConnector.js +117 -0
- package/dist/account/restAccountConnector.js.map +1 -0
- package/dist/account-demo.js +12 -0
- package/dist/account-demo.js.map +1 -0
- package/dist/account.js +25 -0
- package/dist/account.js.map +1 -0
- package/dist/adapters/i18next.js +7 -0
- package/dist/adapters/i18next.js.map +1 -0
- package/dist/adapters/nextNavigation.js +36 -0
- package/dist/adapters/nextNavigation.js.map +1 -0
- package/dist/adapters/reactRouter.js +7 -0
- package/dist/adapters/reactRouter.js.map +1 -0
- package/dist/adapters/reactRouterRoutes.js +48 -0
- package/dist/adapters/reactRouterRoutes.js.map +1 -0
- package/dist/api/ApiError.js +58 -0
- package/dist/api/ApiError.js.map +1 -0
- package/dist/api/createApiClient.js +226 -0
- package/dist/api/createApiClient.js.map +1 -0
- package/dist/api/staleChunks.js +47 -0
- package/dist/api/staleChunks.js.map +1 -0
- package/dist/appShell/AccountMenu.js +86 -0
- package/dist/appShell/AccountMenu.js.map +1 -0
- package/dist/appShell/AppLayout.js +493 -0
- package/dist/appShell/AppLayout.js.map +1 -0
- package/dist/appShell/AppearanceSettings.js +93 -0
- package/dist/appShell/AppearanceSettings.js.map +1 -0
- package/dist/appShell/AuthLayout.js +44 -0
- package/dist/appShell/AuthLayout.js.map +1 -0
- package/dist/appShell/BarActionButton.js +31 -0
- package/dist/appShell/BarActionButton.js.map +1 -0
- package/dist/appShell/BarActions.js +94 -0
- package/dist/appShell/BarActions.js.map +1 -0
- package/dist/appShell/BarCapsule.js +35 -0
- package/dist/appShell/BarCapsule.js.map +1 -0
- package/dist/appShell/HeaderTools.js +53 -0
- package/dist/appShell/HeaderTools.js.map +1 -0
- package/dist/appShell/MobileTabBar.js +346 -0
- package/dist/appShell/MobileTabBar.js.map +1 -0
- package/dist/appShell/SettingsMenu.js +41 -0
- package/dist/appShell/SettingsMenu.js.map +1 -0
- package/dist/appShell/SideMenu.js +217 -0
- package/dist/appShell/SideMenu.js.map +1 -0
- package/dist/appShell/SideMenuEntry.js +140 -0
- package/dist/appShell/SideMenuEntry.js.map +1 -0
- package/dist/appShell/SubmenuActionsMenu.js +71 -0
- package/dist/appShell/SubmenuActionsMenu.js.map +1 -0
- package/dist/appShell/TabBarEditor.js +55 -0
- package/dist/appShell/TabBarEditor.js.map +1 -0
- package/dist/appShell/TopMenu.js +80 -0
- package/dist/appShell/TopMenu.js.map +1 -0
- package/dist/appShell/appMenuContext.js +11 -0
- package/dist/appShell/appMenuContext.js.map +1 -0
- package/dist/appShell/barActionsSlot.js +26 -0
- package/dist/appShell/barActionsSlot.js.map +1 -0
- package/dist/appShell/barMenuPlacement.js +33 -0
- package/dist/appShell/barMenuPlacement.js.map +1 -0
- package/dist/appShell/menuItemText.js +33 -0
- package/dist/appShell/menuItemText.js.map +1 -0
- package/dist/appShell/pageTitle.js +45 -0
- package/dist/appShell/pageTitle.js.map +1 -0
- package/dist/appShell/shellSizes.js +38 -0
- package/dist/appShell/shellSizes.js.map +1 -0
- package/dist/appShell/tabBarRule.js +12 -0
- package/dist/appShell/tabBarRule.js.map +1 -0
- package/dist/appShell/tabBarScroll.js +23 -0
- package/dist/appShell/tabBarScroll.js.map +1 -0
- package/dist/appShell/useDrawerCollapsed.js +29 -0
- package/dist/appShell/useDrawerCollapsed.js.map +1 -0
- package/dist/appShell/useFittingActionCount.js +45 -0
- package/dist/appShell/useFittingActionCount.js.map +1 -0
- package/dist/appShell/usePinnedMobileTabs.js +32 -0
- package/dist/appShell/usePinnedMobileTabs.js.map +1 -0
- package/dist/appShell/useTabBarMinimized.js +33 -0
- package/dist/appShell/useTabBarMinimized.js.map +1 -0
- package/dist/auth/PasswordChecklist.js +44 -0
- package/dist/auth/PasswordChecklist.js.map +1 -0
- package/dist/auth/passwordRules.js +43 -0
- package/dist/auth/passwordRules.js.map +1 -0
- package/dist/calendar/EventCalendar.js +138 -0
- package/dist/calendar/EventCalendar.js.map +1 -0
- package/dist/calendar.js +6 -0
- package/dist/calendar.js.map +1 -0
- package/dist/charts.js +7 -0
- package/dist/charts.js.map +1 -0
- package/dist/date-pickers.js +8 -0
- package/dist/date-pickers.js.map +1 -0
- package/dist/datePickers/DateInput.js +75 -0
- package/dist/datePickers/DateInput.js.map +1 -0
- package/dist/datePickers/FormDateField.js +12 -0
- package/dist/datePickers/FormDateField.js.map +1 -0
- package/dist/dates.js +25 -0
- package/dist/dates.js.map +1 -0
- package/dist/dictionaries/dictionaries.js +48 -0
- package/dist/dictionaries/dictionaries.js.map +1 -0
- package/dist/downloads/DownloadManager.js +201 -0
- package/dist/downloads/DownloadManager.js.map +1 -0
- package/dist/downloads/downloadQueue.js +54 -0
- package/dist/downloads/downloadQueue.js.map +1 -0
- package/dist/downloads/downloadsMachine.js +77 -0
- package/dist/downloads/downloadsMachine.js.map +1 -0
- package/dist/excel/reportWorkbook.js +299 -0
- package/dist/excel/reportWorkbook.js.map +1 -0
- package/dist/excel.js +13 -0
- package/dist/excel.js.map +1 -0
- package/dist/feedback/ConfirmDialog.js +72 -0
- package/dist/feedback/ConfirmDialog.js.map +1 -0
- package/dist/feedback/ModalWaiting.js +23 -0
- package/dist/feedback/ModalWaiting.js.map +1 -0
- package/dist/feedback/NewBuildNotice.js +79 -0
- package/dist/feedback/NewBuildNotice.js.map +1 -0
- package/dist/feedback/StaleBuildBoundary.js +36 -0
- package/dist/feedback/StaleBuildBoundary.js.map +1 -0
- package/dist/feedback/Toaster.js +20 -0
- package/dist/feedback/Toaster.js.map +1 -0
- package/dist/feedback/confirmActionMachine.js +67 -0
- package/dist/feedback/confirmActionMachine.js.map +1 -0
- package/dist/feedback/toast.js +88 -0
- package/dist/feedback/toast.js.map +1 -0
- package/dist/feedback/useConfirmAction.js +40 -0
- package/dist/feedback/useConfirmAction.js.map +1 -0
- package/dist/filepond/FileDropzone.js +254 -0
- package/dist/filepond/FileDropzone.js.map +1 -0
- package/dist/filepond/pondServer.js +48 -0
- package/dist/filepond/pondServer.js.map +1 -0
- package/dist/filepond.js +10 -0
- package/dist/filepond.js.map +1 -0
- package/dist/files.js +43 -0
- package/dist/files.js.map +1 -0
- package/dist/formatting.js +177 -0
- package/dist/formatting.js.map +1 -0
- package/dist/forms/FormCatalogField.js +12 -0
- package/dist/forms/FormCatalogField.js.map +1 -0
- package/dist/forms/FormColorField.js +12 -0
- package/dist/forms/FormColorField.js.map +1 -0
- package/dist/forms/FormNumberField.js +12 -0
- package/dist/forms/FormNumberField.js.map +1 -0
- package/dist/forms/FormProblemAlert.js +15 -0
- package/dist/forms/FormProblemAlert.js.map +1 -0
- package/dist/forms/FormSelectField.js +12 -0
- package/dist/forms/FormSelectField.js.map +1 -0
- package/dist/forms/FormServerProblem.js +23 -0
- package/dist/forms/FormServerProblem.js.map +1 -0
- package/dist/forms/FormTextField.js +12 -0
- package/dist/forms/FormTextField.js.map +1 -0
- package/dist/forms/FormWizard.js +90 -0
- package/dist/forms/FormWizard.js.map +1 -0
- package/dist/forms/SubmitButton.js +14 -0
- package/dist/forms/SubmitButton.js.map +1 -0
- package/dist/forms/applyServerProblem.js +15 -0
- package/dist/forms/applyServerProblem.js.map +1 -0
- package/dist/forms/auth/ChangePasswordForm.js +46 -0
- package/dist/forms/auth/ChangePasswordForm.js.map +1 -0
- package/dist/forms/auth/ForgotPasswordForm.js +50 -0
- package/dist/forms/auth/ForgotPasswordForm.js.map +1 -0
- package/dist/forms/auth/SignInForm.js +48 -0
- package/dist/forms/auth/SignInForm.js.map +1 -0
- package/dist/forms/security/SecondStepForm.js +122 -0
- package/dist/forms/security/SecondStepForm.js.map +1 -0
- package/dist/forms/security/TwoStepVerificationCard.js +336 -0
- package/dist/forms/security/TwoStepVerificationCard.js.map +1 -0
- package/dist/forms/security/securityRules.js +28 -0
- package/dist/forms/security/securityRules.js.map +1 -0
- package/dist/forms/serverProblemFields.js +25 -0
- package/dist/forms/serverProblemFields.js.map +1 -0
- package/dist/forms/useFormikField.js +16 -0
- package/dist/forms/useFormikField.js.map +1 -0
- package/dist/forms/validation.js +55 -0
- package/dist/forms/validation.js.map +1 -0
- package/dist/forms/validationMessages.js +16 -0
- package/dist/forms/validationMessages.js.map +1 -0
- package/dist/forms.js +57 -0
- package/dist/forms.js.map +1 -0
- package/dist/hookForm/FormCatalogField.js +12 -0
- package/dist/hookForm/FormCatalogField.js.map +1 -0
- package/dist/hookForm/FormColorField.js +12 -0
- package/dist/hookForm/FormColorField.js.map +1 -0
- package/dist/hookForm/FormNumberField.js +12 -0
- package/dist/hookForm/FormNumberField.js.map +1 -0
- package/dist/hookForm/FormProblemAlert.js +17 -0
- package/dist/hookForm/FormProblemAlert.js.map +1 -0
- package/dist/hookForm/FormSelectField.js +12 -0
- package/dist/hookForm/FormSelectField.js.map +1 -0
- package/dist/hookForm/FormTextField.js +12 -0
- package/dist/hookForm/FormTextField.js.map +1 -0
- package/dist/hookForm/SubmitButton.js +15 -0
- package/dist/hookForm/SubmitButton.js.map +1 -0
- package/dist/hookForm/applyServerProblem.js +21 -0
- package/dist/hookForm/applyServerProblem.js.map +1 -0
- package/dist/hookForm/useHookFormField.js +19 -0
- package/dist/hookForm/useHookFormField.js.map +1 -0
- package/dist/i18next.js +5 -0
- package/dist/i18next.js.map +1 -0
- package/dist/identifiers.js +8 -0
- package/dist/identifiers.js.map +1 -0
- package/dist/inbox/InboxLayout.js +68 -0
- package/dist/inbox/InboxLayout.js.map +1 -0
- package/dist/inbox/MessageList.js +64 -0
- package/dist/inbox/MessageList.js.map +1 -0
- package/dist/inbox/MessageView.js +53 -0
- package/dist/inbox/MessageView.js.map +1 -0
- package/dist/inbox/inboxDates.js +8 -0
- package/dist/inbox/inboxDates.js.map +1 -0
- package/dist/index.js +383 -0
- package/dist/index.js.map +1 -0
- package/dist/inputs/CatalogInput.js +62 -0
- package/dist/inputs/CatalogInput.js.map +1 -0
- package/dist/inputs/ColorInput.js +108 -0
- package/dist/inputs/ColorInput.js.map +1 -0
- package/dist/inputs/FieldFrame.js +20 -0
- package/dist/inputs/FieldFrame.js.map +1 -0
- package/dist/inputs/FormSection.js +105 -0
- package/dist/inputs/FormSection.js.map +1 -0
- package/dist/inputs/NumberInput.js +69 -0
- package/dist/inputs/NumberInput.js.map +1 -0
- package/dist/inputs/SelectInput.js +66 -0
- package/dist/inputs/SelectInput.js.map +1 -0
- package/dist/inputs/TextInput.js +97 -0
- package/dist/inputs/TextInput.js.map +1 -0
- package/dist/inputs/colorContrast.js +46 -0
- package/dist/inputs/colorContrast.js.map +1 -0
- package/dist/inputs/formLayoutContext.js +9 -0
- package/dist/inputs/formLayoutContext.js.map +1 -0
- package/dist/inputs/numberText.js +48 -0
- package/dist/inputs/numberText.js.map +1 -0
- package/dist/kanban/KanbanBoard.js +113 -0
- package/dist/kanban/KanbanBoard.js.map +1 -0
- package/dist/kanban/kanbanMoves.js +29 -0
- package/dist/kanban/kanbanMoves.js.map +1 -0
- package/dist/kanban.js +9 -0
- package/dist/kanban.js.map +1 -0
- package/dist/laravel/csrfRetry.js +18 -0
- package/dist/laravel/csrfRetry.js.map +1 -0
- package/dist/laravel.js +6 -0
- package/dist/laravel.js.map +1 -0
- package/dist/lastListUrl.js +35 -0
- package/dist/lastListUrl.js.map +1 -0
- package/dist/locales/en.js +714 -0
- package/dist/locales/en.js.map +1 -0
- package/dist/locales/es.js +714 -0
- package/dist/locales/es.js.map +1 -0
- package/dist/maps/MapView.js +96 -0
- package/dist/maps/MapView.js.map +1 -0
- package/dist/maps/mapMarkers.js +19 -0
- package/dist/maps/mapMarkers.js.map +1 -0
- package/dist/maps.js +10 -0
- package/dist/maps.js.map +1 -0
- package/dist/money/money.js +380 -0
- package/dist/money/money.js.map +1 -0
- package/dist/money.js +6 -0
- package/dist/money.js.map +1 -0
- package/dist/navigation/appMenu.js +93 -0
- package/dist/navigation/appMenu.js.map +1 -0
- package/dist/navigation/useMenuBadges.js +45 -0
- package/dist/navigation/useMenuBadges.js.map +1 -0
- package/dist/navigation.js +30 -0
- package/dist/navigation.js.map +1 -0
- package/dist/navigationTrail.js +82 -0
- package/dist/navigationTrail.js.map +1 -0
- package/dist/next.js +5 -0
- package/dist/next.js.map +1 -0
- package/dist/observability/buildWatch.js +19 -0
- package/dist/observability/buildWatch.js.map +1 -0
- package/dist/observability/logger.js +43 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/publishedBuild.js +39 -0
- package/dist/observability/publishedBuild.js.map +1 -0
- package/dist/observability/usePublishedBuildWatch.js +76 -0
- package/dist/observability/usePublishedBuildWatch.js.map +1 -0
- package/dist/passkeys.js +7 -0
- package/dist/passkeys.js.map +1 -0
- package/dist/periodRanges.js +33 -0
- package/dist/periodRanges.js.map +1 -0
- package/dist/problems.js +51 -0
- package/dist/problems.js.map +1 -0
- package/dist/pwa/InstallAppSetting.js +33 -0
- package/dist/pwa/InstallAppSetting.js.map +1 -0
- package/dist/pwa/InstallInstructionsDialog.js +35 -0
- package/dist/pwa/InstallInstructionsDialog.js.map +1 -0
- package/dist/pwa/InstallPromptBanner.js +64 -0
- package/dist/pwa/InstallPromptBanner.js.map +1 -0
- package/dist/pwa/installInstructions.js +60 -0
- package/dist/pwa/installInstructions.js.map +1 -0
- package/dist/pwa/useInstallPrompt.js +70 -0
- package/dist/pwa/useInstallPrompt.js.map +1 -0
- package/dist/react-hook-form.js +30 -0
- package/dist/react-hook-form.js.map +1 -0
- package/dist/react-router.js +10 -0
- package/dist/react-router.js.map +1 -0
- package/dist/security/ActivityLog.js +79 -0
- package/dist/security/ActivityLog.js.map +1 -0
- package/dist/security/RecoveryCodesDialog.js +84 -0
- package/dist/security/RecoveryCodesDialog.js.map +1 -0
- package/dist/security/SessionsCard.js +81 -0
- package/dist/security/SessionsCard.js.map +1 -0
- package/dist/security/passkeys.js +39 -0
- package/dist/security/passkeys.js.map +1 -0
- package/dist/table.js +35 -0
- package/dist/table.js.map +1 -0
- package/dist/theme/androidDevice.js +16 -0
- package/dist/theme/androidDevice.js.map +1 -0
- package/dist/theme/appleTracking.js +34 -0
- package/dist/theme/appleTracking.js.map +1 -0
- package/dist/theme/components/MuiAppBar.js +27 -0
- package/dist/theme/components/MuiAppBar.js.map +1 -0
- package/dist/theme/components/MuiBackdrop.js +13 -0
- package/dist/theme/components/MuiBackdrop.js.map +1 -0
- package/dist/theme/components/MuiButton.js +25 -0
- package/dist/theme/components/MuiButton.js.map +1 -0
- package/dist/theme/components/MuiButtonBase.js +16 -0
- package/dist/theme/components/MuiButtonBase.js.map +1 -0
- package/dist/theme/components/MuiChip.js +30 -0
- package/dist/theme/components/MuiChip.js.map +1 -0
- package/dist/theme/components/MuiDataGrid.js +30 -0
- package/dist/theme/components/MuiDataGrid.js.map +1 -0
- package/dist/theme/components/MuiDrawer.js +18 -0
- package/dist/theme/components/MuiDrawer.js.map +1 -0
- package/dist/theme/components/MuiMenuItem.js +17 -0
- package/dist/theme/components/MuiMenuItem.js.map +1 -0
- package/dist/theme/components/MuiTypography.js +22 -0
- package/dist/theme/components/MuiTypography.js.map +1 -0
- package/dist/theme/components/glassComponents.js +885 -0
- package/dist/theme/components/glassComponents.js.map +1 -0
- package/dist/theme/components/minimalComponents.js +146 -0
- package/dist/theme/components/minimalComponents.js.map +1 -0
- package/dist/theme/components/paletteOf.js +7 -0
- package/dist/theme/components/paletteOf.js.map +1 -0
- package/dist/theme/createToolkitTheme.js +100 -0
- package/dist/theme/createToolkitTheme.js.map +1 -0
- package/dist/theme/glassSurface.js +328 -0
- package/dist/theme/glassSurface.js.map +1 -0
- package/dist/theme/glassToasterStyles.js +50 -0
- package/dist/theme/glassToasterStyles.js.map +1 -0
- package/dist/theme/mergeComponents.js +42 -0
- package/dist/theme/mergeComponents.js.map +1 -0
- package/dist/theme/stackcraftPalette.js +59 -0
- package/dist/theme/stackcraftPalette.js.map +1 -0
- package/dist/theme/toolkitComponents.js +26 -0
- package/dist/theme/toolkitComponents.js.map +1 -0
- package/dist/timeline.js +8 -0
- package/dist/timeline.js.map +1 -0
- package/dist/toolkit/ToolkitProvider.js +49 -0
- package/dist/toolkit/ToolkitProvider.js.map +1 -0
- package/dist/toolkit/browserNavigation.js +34 -0
- package/dist/toolkit/browserNavigation.js.map +1 -0
- package/dist/toolkit/toolkitContext.js +19 -0
- package/dist/toolkit/toolkitContext.js.map +1 -0
- package/dist/toolkit/toolkitSettings.js +87 -0
- package/dist/toolkit/toolkitSettings.js.map +1 -0
- package/dist/toolkit/useToolkitTranslation.js +18 -0
- package/dist/toolkit/useToolkitTranslation.js.map +1 -0
- package/dist/types/DataTable/AuditTrailDialog.d.ts +32 -0
- package/dist/types/DataTable/AuditTrailTable.d.ts +28 -0
- package/dist/types/DataTable/ColumnFilters/HeaderFilterPopover.d.ts +8 -0
- package/dist/types/DataTable/ColumnFilters/MultiSelectColumnFilter.d.ts +16 -0
- package/dist/types/DataTable/ColumnFilters/SortableFilterHeader.d.ts +26 -0
- package/dist/types/DataTable/ColumnFilters/TextColumnFilter.d.ts +8 -0
- package/dist/types/DataTable/ColumnFilters/index.d.ts +4 -0
- package/dist/types/DataTable/EmptyState.d.ts +8 -0
- package/dist/types/DataTable/FilterChips.d.ts +15 -0
- package/dist/types/DataTable/GoToPage.d.ts +8 -0
- package/dist/types/DataTable/ServerTable.d.ts +110 -0
- package/dist/types/DataTable/buildChipConfig.d.ts +22 -0
- package/dist/types/DataTable/columns.d.ts +93 -0
- package/dist/types/DataTable/filterContext.d.ts +13 -0
- package/dist/types/DataTable/index.d.ts +13 -0
- package/dist/types/DataTable/serverTableParams.d.ts +16 -0
- package/dist/types/DataTable/tableMachine.d.ts +41 -0
- package/dist/types/DataTable/useDebouncedFilter.d.ts +8 -0
- package/dist/types/DataTable/useTableState.d.ts +93 -0
- package/dist/types/access/Can.d.ts +11 -0
- package/dist/types/access/PermissionMatrix.d.ts +21 -0
- package/dist/types/access/RequireAccess.d.ts +11 -0
- package/dist/types/access/accessRules.d.ts +24 -0
- package/dist/types/access/permissionGroups.d.ts +56 -0
- package/dist/types/access/useCan.d.ts +11 -0
- package/dist/types/account/AccountProvider.d.ts +27 -0
- package/dist/types/account/AccountSecuritySection.d.ts +7 -0
- package/dist/types/account/DemoTotpCodeButton.d.ts +6 -0
- package/dist/types/account/ForgotPasswordScreen.d.ts +15 -0
- package/dist/types/account/ProfileScreen.d.ts +13 -0
- package/dist/types/account/ResetPasswordScreen.d.ts +19 -0
- package/dist/types/account/SignInScreen.d.ts +25 -0
- package/dist/types/account/accountConnector.d.ts +263 -0
- package/dist/types/account/demo/createDemoAccountConnector.d.ts +30 -0
- package/dist/types/account/demo/totp.d.ts +45 -0
- package/dist/types/account/restAccountConnector.d.ts +49 -0
- package/dist/types/account-demo.d.ts +2 -0
- package/dist/types/account.d.ts +16 -0
- package/dist/types/adapters/i18next.d.ts +11 -0
- package/dist/types/adapters/nextNavigation.d.ts +33 -0
- package/dist/types/adapters/reactRouter.d.ts +6 -0
- package/dist/types/adapters/reactRouterRoutes.d.ts +30 -0
- package/dist/types/api/ApiError.d.ts +42 -0
- package/dist/types/api/createApiClient.d.ts +146 -0
- package/dist/types/api/staleChunks.d.ts +15 -0
- package/dist/types/appShell/AccountMenu.d.ts +28 -0
- package/dist/types/appShell/AppLayout.d.ts +66 -0
- package/dist/types/appShell/AppearanceSettings.d.ts +34 -0
- package/dist/types/appShell/AuthLayout.d.ts +21 -0
- package/dist/types/appShell/BarActionButton.d.ts +15 -0
- package/dist/types/appShell/BarActions.d.ts +18 -0
- package/dist/types/appShell/BarCapsule.d.ts +12 -0
- package/dist/types/appShell/HeaderTools.d.ts +27 -0
- package/dist/types/appShell/MobileTabBar.d.ts +17 -0
- package/dist/types/appShell/SettingsMenu.d.ts +13 -0
- package/dist/types/appShell/SideMenu.d.ts +31 -0
- package/dist/types/appShell/SideMenuEntry.d.ts +17 -0
- package/dist/types/appShell/SubmenuActionsMenu.d.ts +24 -0
- package/dist/types/appShell/TabBarEditor.d.ts +13 -0
- package/dist/types/appShell/TopMenu.d.ts +7 -0
- package/dist/types/appShell/appMenuContext.d.ts +9 -0
- package/dist/types/appShell/barActionsSlot.d.ts +35 -0
- package/dist/types/appShell/barMenuPlacement.d.ts +9 -0
- package/dist/types/appShell/menuItemText.d.ts +55 -0
- package/dist/types/appShell/pageTitle.d.ts +26 -0
- package/dist/types/appShell/shellSizes.d.ts +45 -0
- package/dist/types/appShell/tabBarRule.d.ts +5 -0
- package/dist/types/appShell/tabBarScroll.d.ts +26 -0
- package/dist/types/appShell/useDrawerCollapsed.d.ts +8 -0
- package/dist/types/appShell/useFittingActionCount.d.ts +7 -0
- package/dist/types/appShell/usePinnedMobileTabs.d.ts +7 -0
- package/dist/types/appShell/useTabBarMinimized.d.ts +8 -0
- package/dist/types/auth/PasswordChecklist.d.ts +11 -0
- package/dist/types/auth/passwordRules.d.ts +34 -0
- package/dist/types/calendar/EventCalendar.d.ts +46 -0
- package/dist/types/calendar.d.ts +1 -0
- package/dist/types/charts.d.ts +2 -0
- package/dist/types/date-pickers.d.ts +2 -0
- package/dist/types/datePickers/DateInput.d.ts +39 -0
- package/dist/types/datePickers/FormDateField.d.ts +7 -0
- package/dist/types/dates.d.ts +18 -0
- package/dist/types/dictionaries/dictionaries.d.ts +54 -0
- package/dist/types/downloads/DownloadManager.d.ts +1 -0
- package/dist/types/downloads/downloadQueue.d.ts +45 -0
- package/dist/types/downloads/downloadsMachine.d.ts +10 -0
- package/dist/types/downloads/index.d.ts +3 -0
- package/dist/types/excel/reportWorkbook.d.ts +157 -0
- package/dist/types/excel.d.ts +1 -0
- package/dist/types/feedback/ConfirmDialog.d.ts +29 -0
- package/dist/types/feedback/ModalWaiting.d.ts +8 -0
- package/dist/types/feedback/NewBuildNotice.d.ts +18 -0
- package/dist/types/feedback/StaleBuildBoundary.d.ts +21 -0
- package/dist/types/feedback/Toaster.d.ts +1 -0
- package/dist/types/feedback/confirmActionMachine.d.ts +19 -0
- package/dist/types/feedback/index.d.ts +8 -0
- package/dist/types/feedback/toast.d.ts +100 -0
- package/dist/types/feedback/useConfirmAction.d.ts +33 -0
- package/dist/types/filepond/FileDropzone.d.ts +59 -0
- package/dist/types/filepond/pondServer.d.ts +17 -0
- package/dist/types/filepond.d.ts +3 -0
- package/dist/types/files.d.ts +29 -0
- package/dist/types/formatting.d.ts +106 -0
- package/dist/types/forms/FormCatalogField.d.ts +6 -0
- package/dist/types/forms/FormColorField.d.ts +6 -0
- package/dist/types/forms/FormNumberField.d.ts +6 -0
- package/dist/types/forms/FormProblemAlert.d.ts +6 -0
- package/dist/types/forms/FormSelectField.d.ts +6 -0
- package/dist/types/forms/FormServerProblem.d.ts +8 -0
- package/dist/types/forms/FormTextField.d.ts +6 -0
- package/dist/types/forms/FormWizard.d.ts +20 -0
- package/dist/types/forms/SubmitButton.d.ts +9 -0
- package/dist/types/forms/applyServerProblem.d.ts +9 -0
- package/dist/types/forms/auth/ChangePasswordForm.d.ts +15 -0
- package/dist/types/forms/auth/ForgotPasswordForm.d.ts +12 -0
- package/dist/types/forms/auth/SignInForm.d.ts +18 -0
- package/dist/types/forms/index.d.ts +19 -0
- package/dist/types/forms/security/SecondStepForm.d.ts +28 -0
- package/dist/types/forms/security/TwoStepVerificationCard.d.ts +81 -0
- package/dist/types/forms/security/securityRules.d.ts +24 -0
- package/dist/types/forms/serverProblemFields.d.ts +19 -0
- package/dist/types/forms/useFormikField.d.ts +11 -0
- package/dist/types/forms/validation.d.ts +251 -0
- package/dist/types/forms/validationMessages.d.ts +12 -0
- package/dist/types/forms.d.ts +2 -0
- package/dist/types/hookForm/FormCatalogField.d.ts +8 -0
- package/dist/types/hookForm/FormColorField.d.ts +8 -0
- package/dist/types/hookForm/FormNumberField.d.ts +8 -0
- package/dist/types/hookForm/FormProblemAlert.d.ts +7 -0
- package/dist/types/hookForm/FormSelectField.d.ts +8 -0
- package/dist/types/hookForm/FormTextField.d.ts +8 -0
- package/dist/types/hookForm/SubmitButton.d.ts +21 -0
- package/dist/types/hookForm/applyServerProblem.d.ts +10 -0
- package/dist/types/hookForm/useHookFormField.d.ts +13 -0
- package/dist/types/i18next.d.ts +1 -0
- package/dist/types/identifiers.d.ts +2 -0
- package/dist/types/inbox/InboxLayout.d.ts +26 -0
- package/dist/types/inbox/MessageList.d.ts +27 -0
- package/dist/types/inbox/MessageView.d.ts +23 -0
- package/dist/types/inbox/inboxDates.d.ts +6 -0
- package/dist/types/index.d.ts +84 -0
- package/dist/types/inputs/CatalogInput.d.ts +41 -0
- package/dist/types/inputs/ColorInput.d.ts +28 -0
- package/dist/types/inputs/FieldFrame.d.ts +14 -0
- package/dist/types/inputs/FormSection.d.ts +29 -0
- package/dist/types/inputs/NumberInput.d.ts +36 -0
- package/dist/types/inputs/SelectInput.d.ts +34 -0
- package/dist/types/inputs/TextInput.d.ts +60 -0
- package/dist/types/inputs/colorContrast.d.ts +18 -0
- package/dist/types/inputs/formLayoutContext.d.ts +3 -0
- package/dist/types/inputs/numberText.d.ts +25 -0
- package/dist/types/kanban/KanbanBoard.d.ts +33 -0
- package/dist/types/kanban/kanbanMoves.d.ts +38 -0
- package/dist/types/kanban.d.ts +2 -0
- package/dist/types/laravel/csrfRetry.d.ts +21 -0
- package/dist/types/laravel.d.ts +1 -0
- package/dist/types/lastListUrl.d.ts +20 -0
- package/dist/types/locales/en.d.ts +711 -0
- package/dist/types/locales/es.d.ts +711 -0
- package/dist/types/maps/MapView.d.ts +32 -0
- package/dist/types/maps/mapMarkers.d.ts +23 -0
- package/dist/types/maps.d.ts +2 -0
- package/dist/types/money/money.d.ts +203 -0
- package/dist/types/money.d.ts +1 -0
- package/dist/types/navigation/appMenu.d.ts +92 -0
- package/dist/types/navigation/useMenuBadges.d.ts +16 -0
- package/dist/types/navigation.d.ts +22 -0
- package/dist/types/navigationTrail.d.ts +49 -0
- package/dist/types/next.d.ts +1 -0
- package/dist/types/observability/buildWatch.d.ts +28 -0
- package/dist/types/observability/logger.d.ts +19 -0
- package/dist/types/observability/publishedBuild.d.ts +35 -0
- package/dist/types/observability/usePublishedBuildWatch.d.ts +16 -0
- package/dist/types/passkeys.d.ts +1 -0
- package/dist/types/periodRanges.d.ts +32 -0
- package/dist/types/problems.d.ts +31 -0
- package/dist/types/pwa/InstallAppSetting.d.ts +1 -0
- package/dist/types/pwa/InstallInstructionsDialog.d.ts +18 -0
- package/dist/types/pwa/InstallPromptBanner.d.ts +7 -0
- package/dist/types/pwa/installInstructions.d.ts +52 -0
- package/dist/types/pwa/useInstallPrompt.d.ts +12 -0
- package/dist/types/react-hook-form.d.ts +11 -0
- package/dist/types/react-router.d.ts +2 -0
- package/dist/types/security/ActivityLog.d.ts +31 -0
- package/dist/types/security/RecoveryCodesDialog.d.ts +11 -0
- package/dist/types/security/SessionsCard.d.ts +22 -0
- package/dist/types/security/passkeys.d.ts +18 -0
- package/dist/types/table.d.ts +1 -0
- package/dist/types/theme/androidDevice.d.ts +11 -0
- package/dist/types/theme/appleTracking.d.ts +17 -0
- package/dist/types/theme/components/MuiAppBar.d.ts +13 -0
- package/dist/types/theme/components/MuiBackdrop.d.ts +11 -0
- package/dist/types/theme/components/MuiButton.d.ts +27 -0
- package/dist/types/theme/components/MuiButtonBase.d.ts +14 -0
- package/dist/types/theme/components/MuiChip.d.ts +29 -0
- package/dist/types/theme/components/MuiDataGrid.d.ts +45 -0
- package/dist/types/theme/components/MuiDrawer.d.ts +13 -0
- package/dist/types/theme/components/MuiMenuItem.d.ts +17 -0
- package/dist/types/theme/components/MuiTypography.d.ts +20 -0
- package/dist/types/theme/components/glassComponents.d.ts +8 -0
- package/dist/types/theme/components/minimalComponents.d.ts +22 -0
- package/dist/types/theme/components/paletteOf.d.ts +5 -0
- package/dist/types/theme/createToolkitTheme.d.ts +48 -0
- package/dist/types/theme/glassSurface.d.ts +247 -0
- package/dist/types/theme/glassToasterStyles.d.ts +7 -0
- package/dist/types/theme/mergeComponents.d.ts +15 -0
- package/dist/types/theme/stackcraftPalette.d.ts +142 -0
- package/dist/types/theme/toolkitComponents.d.ts +4 -0
- package/dist/types/timeline.d.ts +2 -0
- package/dist/types/toolkit/ToolkitProvider.d.ts +31 -0
- package/dist/types/toolkit/browserNavigation.d.ts +32 -0
- package/dist/types/toolkit/toolkitContext.d.ts +28 -0
- package/dist/types/toolkit/toolkitSettings.d.ts +68 -0
- package/dist/types/toolkit/useToolkitTranslation.d.ts +10 -0
- package/dist/types/ui/actions/CopyButton.d.ts +13 -0
- package/dist/types/ui/actions/DownloadMenu.d.ts +50 -0
- package/dist/types/ui/actions/SecretField.d.ts +13 -0
- package/dist/types/ui/filters/DateRangeFilter.d.ts +16 -0
- package/dist/types/ui/filters/PeriodRangeSelector.d.ts +28 -0
- package/dist/types/ui/filters/QuickFilters.d.ts +21 -0
- package/dist/types/ui/filters/SegmentedControl.d.ts +44 -0
- package/dist/types/ui/index.d.ts +33 -0
- package/dist/types/ui/labels/DictionaryText.d.ts +7 -0
- package/dist/types/ui/labels/StatusChip.d.ts +21 -0
- package/dist/types/ui/labels/Tag.d.ts +19 -0
- package/dist/types/ui/layout/CollapsibleSection.d.ts +15 -0
- package/dist/types/ui/layout/ContentDialog.d.ts +13 -0
- package/dist/types/ui/layout/DefinitionList.d.ts +15 -0
- package/dist/types/ui/layout/DetailHeader.d.ts +15 -0
- package/dist/types/ui/layout/ErrorPage.d.ts +22 -0
- package/dist/types/ui/layout/FullPageLoader.d.ts +1 -0
- package/dist/types/ui/layout/GlassLensFilter.d.ts +1 -0
- package/dist/types/ui/layout/GlassPanel.d.ts +11 -0
- package/dist/types/ui/layout/PageHeader.d.ts +15 -0
- package/dist/types/ui/layout/PageHeading.d.ts +18 -0
- package/dist/types/ui/layout/ProfileHeader.d.ts +17 -0
- package/dist/types/ui/layout/ScrollableRow.d.ts +33 -0
- package/dist/types/ui/layout/SectionCard.d.ts +11 -0
- package/dist/types/ui/layout/appBarHeight.d.ts +13 -0
- package/dist/types/ui/metrics/BarList.d.ts +19 -0
- package/dist/types/ui/metrics/CalendarHeatmap.d.ts +28 -0
- package/dist/types/ui/metrics/ChartTooltip.d.ts +5 -0
- package/dist/types/ui/metrics/ColumnChart.d.ts +35 -0
- package/dist/types/ui/metrics/MetricCard.d.ts +31 -0
- package/dist/types/ui/metrics/TableToggle.d.ts +7 -0
- package/dist/types/ui/metrics/barListLabels.d.ts +17 -0
- package/dist/types/ui/metrics/heatmapScale.d.ts +45 -0
- package/dist/types/ui/navigation/BackButton.d.ts +11 -0
- package/dist/types/ui/navigation/ColorSchemeToggle.d.ts +7 -0
- package/dist/types/ui/navigation/DocumentTitle.d.ts +6 -0
- package/dist/types/ui/navigation/FontSizeToggle.d.ts +6 -0
- package/dist/types/ui/navigation/LanguageToggle.d.ts +8 -0
- package/dist/types/ui/navigation/PageBreadcrumbs.d.ts +9 -0
- package/dist/types/ui/navigation/colorMode.d.ts +18 -0
- package/dist/types/ui/navigation/fontSizeLevels.d.ts +25 -0
- package/dist/types/ui/navigation/useFontSize.d.ts +10 -0
- package/dist/types/ui/timeline/GroupedTimeline.d.ts +38 -0
- package/dist/types/ui/timeline/timelineDot.d.ts +19 -0
- package/dist/types/upload/FileDropzone.d.ts +34 -0
- package/dist/types/upload/fileRules.d.ts +51 -0
- package/dist/types/upload/uploadMachine.d.ts +23 -0
- package/dist/types/upload/uploadWithProgress.d.ts +16 -0
- package/dist/ui/actions/CopyButton.js +28 -0
- package/dist/ui/actions/CopyButton.js.map +1 -0
- package/dist/ui/actions/DownloadMenu.js +163 -0
- package/dist/ui/actions/DownloadMenu.js.map +1 -0
- package/dist/ui/actions/SecretField.js +57 -0
- package/dist/ui/actions/SecretField.js.map +1 -0
- package/dist/ui/filters/DateRangeFilter.js +86 -0
- package/dist/ui/filters/DateRangeFilter.js.map +1 -0
- package/dist/ui/filters/PeriodRangeSelector.js +56 -0
- package/dist/ui/filters/PeriodRangeSelector.js.map +1 -0
- package/dist/ui/filters/QuickFilters.js +91 -0
- package/dist/ui/filters/QuickFilters.js.map +1 -0
- package/dist/ui/filters/SegmentedControl.js +80 -0
- package/dist/ui/filters/SegmentedControl.js.map +1 -0
- package/dist/ui/labels/DictionaryText.js +11 -0
- package/dist/ui/labels/DictionaryText.js.map +1 -0
- package/dist/ui/labels/StatusChip.js +52 -0
- package/dist/ui/labels/StatusChip.js.map +1 -0
- package/dist/ui/labels/Tag.js +26 -0
- package/dist/ui/labels/Tag.js.map +1 -0
- package/dist/ui/layout/CollapsibleSection.js +48 -0
- package/dist/ui/layout/CollapsibleSection.js.map +1 -0
- package/dist/ui/layout/ContentDialog.js +97 -0
- package/dist/ui/layout/ContentDialog.js.map +1 -0
- package/dist/ui/layout/DefinitionList.js +30 -0
- package/dist/ui/layout/DefinitionList.js.map +1 -0
- package/dist/ui/layout/DetailHeader.js +27 -0
- package/dist/ui/layout/DetailHeader.js.map +1 -0
- package/dist/ui/layout/ErrorPage.js +40 -0
- package/dist/ui/layout/ErrorPage.js.map +1 -0
- package/dist/ui/layout/FullPageLoader.js +13 -0
- package/dist/ui/layout/FullPageLoader.js.map +1 -0
- package/dist/ui/layout/GlassLensFilter.js +53 -0
- package/dist/ui/layout/GlassLensFilter.js.map +1 -0
- package/dist/ui/layout/GlassPanel.js +18 -0
- package/dist/ui/layout/GlassPanel.js.map +1 -0
- package/dist/ui/layout/PageHeader.js +23 -0
- package/dist/ui/layout/PageHeader.js.map +1 -0
- package/dist/ui/layout/PageHeading.js +51 -0
- package/dist/ui/layout/PageHeading.js.map +1 -0
- package/dist/ui/layout/ProfileHeader.js +64 -0
- package/dist/ui/layout/ProfileHeader.js.map +1 -0
- package/dist/ui/layout/ScrollableRow.js +156 -0
- package/dist/ui/layout/ScrollableRow.js.map +1 -0
- package/dist/ui/layout/SectionCard.js +18 -0
- package/dist/ui/layout/SectionCard.js.map +1 -0
- package/dist/ui/layout/appBarHeight.js +42 -0
- package/dist/ui/layout/appBarHeight.js.map +1 -0
- package/dist/ui/metrics/BarList.js +89 -0
- package/dist/ui/metrics/BarList.js.map +1 -0
- package/dist/ui/metrics/CalendarHeatmap.js +131 -0
- package/dist/ui/metrics/CalendarHeatmap.js.map +1 -0
- package/dist/ui/metrics/ChartTooltip.js +16 -0
- package/dist/ui/metrics/ChartTooltip.js.map +1 -0
- package/dist/ui/metrics/ColumnChart.js +110 -0
- package/dist/ui/metrics/ColumnChart.js.map +1 -0
- package/dist/ui/metrics/MetricCard.js +64 -0
- package/dist/ui/metrics/MetricCard.js.map +1 -0
- package/dist/ui/metrics/TableToggle.js +13 -0
- package/dist/ui/metrics/TableToggle.js.map +1 -0
- package/dist/ui/metrics/barListLabels.js +9 -0
- package/dist/ui/metrics/barListLabels.js.map +1 -0
- package/dist/ui/metrics/heatmapScale.js +67 -0
- package/dist/ui/metrics/heatmapScale.js.map +1 -0
- package/dist/ui/navigation/BackButton.js +28 -0
- package/dist/ui/navigation/BackButton.js.map +1 -0
- package/dist/ui/navigation/ColorSchemeToggle.js +37 -0
- package/dist/ui/navigation/ColorSchemeToggle.js.map +1 -0
- package/dist/ui/navigation/DocumentTitle.js +11 -0
- package/dist/ui/navigation/DocumentTitle.js.map +1 -0
- package/dist/ui/navigation/FontSizeToggle.js +40 -0
- package/dist/ui/navigation/FontSizeToggle.js.map +1 -0
- package/dist/ui/navigation/LanguageToggle.js +27 -0
- package/dist/ui/navigation/LanguageToggle.js.map +1 -0
- package/dist/ui/navigation/PageBreadcrumbs.js +51 -0
- package/dist/ui/navigation/PageBreadcrumbs.js.map +1 -0
- package/dist/ui/navigation/colorMode.js +13 -0
- package/dist/ui/navigation/colorMode.js.map +1 -0
- package/dist/ui/navigation/fontSizeLevels.js +24 -0
- package/dist/ui/navigation/fontSizeLevels.js.map +1 -0
- package/dist/ui/navigation/useFontSize.js +44 -0
- package/dist/ui/navigation/useFontSize.js.map +1 -0
- package/dist/ui/timeline/GroupedTimeline.js +104 -0
- package/dist/ui/timeline/GroupedTimeline.js.map +1 -0
- package/dist/ui/timeline/timelineDot.js +20 -0
- package/dist/ui/timeline/timelineDot.js.map +1 -0
- package/dist/upload/FileDropzone.js +143 -0
- package/dist/upload/FileDropzone.js.map +1 -0
- package/dist/upload/fileRules.js +62 -0
- package/dist/upload/fileRules.js.map +1 -0
- package/dist/upload/uploadMachine.js +73 -0
- package/dist/upload/uploadMachine.js.map +1 -0
- package/dist/upload/uploadWithProgress.js +45 -0
- package/dist/upload/uploadWithProgress.js.map +1 -0
- package/package.json +303 -5
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import { ApiError, API_ERROR_STATUS } from "./ApiError.js";
|
|
2
|
+
import { fileNameFromContentDisposition, XLSX_CONTENT_TYPE, isCompleteZip } from "../files.js";
|
|
3
|
+
import { CSRF_TOKEN_MISMATCH_STATUS } from "../laravel/csrfRetry.js";
|
|
4
|
+
import { createLogger } from "../observability/logger.js";
|
|
5
|
+
import { reportPublishedBuild } from "../observability/publishedBuild.js";
|
|
6
|
+
import { toolkitSettings, DEFAULT_LANGUAGE } from "../toolkit/toolkitSettings.js";
|
|
7
|
+
const log = createLogger("api");
|
|
8
|
+
const API_RESPONSE_PARSE = Object.freeze({ json: "json", blob: "blob", response: "response" });
|
|
9
|
+
const DEFAULT_TIMEOUT_MILLISECONDS = 6e4;
|
|
10
|
+
const NO_TIMEOUT = 0;
|
|
11
|
+
const DEFAULT_PUBLISHED_BUILD_HEADER = "X-Frontend-Build";
|
|
12
|
+
const NO_CONTENT_STATUS = 204;
|
|
13
|
+
const SERVER_ERROR_STATUS = 500;
|
|
14
|
+
function apiUrlOf(baseUrl, path, params) {
|
|
15
|
+
const url = /^https?:/i.test(path) ? path : `${baseUrl}${path}`;
|
|
16
|
+
const query = new URLSearchParams();
|
|
17
|
+
for (const [name, value] of Object.entries(params ?? {})) {
|
|
18
|
+
for (const item of [].concat(value)) {
|
|
19
|
+
if (item !== void 0 && item !== null) {
|
|
20
|
+
query.append(name, String(item));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const queryText = query.toString();
|
|
25
|
+
if (!queryText) {
|
|
26
|
+
return url;
|
|
27
|
+
}
|
|
28
|
+
return `${url}${url.includes("?") ? "&" : "?"}${queryText}`;
|
|
29
|
+
}
|
|
30
|
+
function isRawBody(body) {
|
|
31
|
+
return typeof FormData !== "undefined" && body instanceof FormData || typeof Blob !== "undefined" && body instanceof Blob || body instanceof URLSearchParams || body instanceof ArrayBuffer;
|
|
32
|
+
}
|
|
33
|
+
function readCookie(cookieName) {
|
|
34
|
+
if (typeof document === "undefined") {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const prefix = `${cookieName}=`;
|
|
38
|
+
const cookie = document.cookie.split(";").map((part) => part.trim()).find((part) => part.startsWith(prefix));
|
|
39
|
+
return cookie ? decodeURIComponent(cookie.slice(prefix.length)) : null;
|
|
40
|
+
}
|
|
41
|
+
function isSameOrigin(url) {
|
|
42
|
+
if (typeof window === "undefined" || !/^https?:/i.test(url)) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
return new URL(url).origin === window.location.origin;
|
|
46
|
+
}
|
|
47
|
+
function retryAfterSecondsOf(retryAfterHeader) {
|
|
48
|
+
if (!retryAfterHeader) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
if (/^\d+$/.test(retryAfterHeader.trim())) {
|
|
52
|
+
return Number(retryAfterHeader.trim());
|
|
53
|
+
}
|
|
54
|
+
const retryAt = Date.parse(retryAfterHeader);
|
|
55
|
+
return Number.isNaN(retryAt) ? null : Math.max(0, Math.ceil((retryAt - Date.now()) / 1e3));
|
|
56
|
+
}
|
|
57
|
+
async function readProblem(response) {
|
|
58
|
+
try {
|
|
59
|
+
const body = JSON.parse(await response.text());
|
|
60
|
+
return body && typeof body === "object" && !Array.isArray(body) ? body : null;
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function combinedSignalOf(signal, timeoutMilliseconds) {
|
|
66
|
+
const signals = [signal, timeoutMilliseconds > 0 ? AbortSignal.timeout(timeoutMilliseconds) : null].filter(Boolean);
|
|
67
|
+
if (signals.length < 2) {
|
|
68
|
+
return signals[0];
|
|
69
|
+
}
|
|
70
|
+
return AbortSignal.any(signals);
|
|
71
|
+
}
|
|
72
|
+
async function readBlobWithProgress(response, onDownloadProgress) {
|
|
73
|
+
if (!onDownloadProgress || !response.body) {
|
|
74
|
+
return response.blob();
|
|
75
|
+
}
|
|
76
|
+
const total = Number(response.headers.get("content-length")) || null;
|
|
77
|
+
const reader = response.body.getReader();
|
|
78
|
+
const chunks = [];
|
|
79
|
+
let loaded = 0;
|
|
80
|
+
for (let part = await reader.read(); !part.done; part = await reader.read()) {
|
|
81
|
+
chunks.push(part.value);
|
|
82
|
+
loaded += part.value.byteLength;
|
|
83
|
+
onDownloadProgress({ loaded, total });
|
|
84
|
+
}
|
|
85
|
+
return new Blob(chunks, { type: response.headers.get("content-type") ?? "" });
|
|
86
|
+
}
|
|
87
|
+
function createApiClient({
|
|
88
|
+
baseUrl = "",
|
|
89
|
+
credentials = "same-origin",
|
|
90
|
+
getToken,
|
|
91
|
+
headers: commonHeaders = {},
|
|
92
|
+
publishedBuildHeader = DEFAULT_PUBLISHED_BUILD_HEADER,
|
|
93
|
+
csrf = null,
|
|
94
|
+
timeoutMilliseconds: defaultTimeoutMilliseconds = DEFAULT_TIMEOUT_MILLISECONDS,
|
|
95
|
+
onUnauthenticated,
|
|
96
|
+
fetch: fetchImplementation
|
|
97
|
+
} = {}) {
|
|
98
|
+
const fetchOf = () => fetchImplementation ?? globalThis.fetch;
|
|
99
|
+
const csrfCookieName = csrf?.cookieName ?? "XSRF-TOKEN";
|
|
100
|
+
const csrfHeaderName = csrf?.headerName ?? "X-XSRF-TOKEN";
|
|
101
|
+
const headersOf = (url, body, extraHeaders) => {
|
|
102
|
+
const headers = {
|
|
103
|
+
Accept: "application/json",
|
|
104
|
+
"Accept-Language": toolkitSettings().language ?? DEFAULT_LANGUAGE,
|
|
105
|
+
...commonHeaders,
|
|
106
|
+
...extraHeaders
|
|
107
|
+
};
|
|
108
|
+
if (body !== void 0 && !isRawBody(body)) {
|
|
109
|
+
headers["Content-Type"] = "application/json";
|
|
110
|
+
}
|
|
111
|
+
const token = getToken?.();
|
|
112
|
+
if (token) {
|
|
113
|
+
headers.Authorization = `Bearer ${token}`;
|
|
114
|
+
}
|
|
115
|
+
const csrfToken = csrf && isSameOrigin(url) ? readCookie(csrfCookieName) : null;
|
|
116
|
+
if (csrfToken) {
|
|
117
|
+
headers[csrfHeaderName] = csrfToken;
|
|
118
|
+
}
|
|
119
|
+
return headers;
|
|
120
|
+
};
|
|
121
|
+
const send = async (method, url, { body, signal, headers, timeoutMilliseconds }) => {
|
|
122
|
+
const finalHeaders = headersOf(url, body, headers);
|
|
123
|
+
try {
|
|
124
|
+
return await fetchOf()(url, {
|
|
125
|
+
method,
|
|
126
|
+
headers: finalHeaders,
|
|
127
|
+
body: body === void 0 || isRawBody(body) ? body : JSON.stringify(body),
|
|
128
|
+
credentials,
|
|
129
|
+
signal: combinedSignalOf(signal, timeoutMilliseconds)
|
|
130
|
+
});
|
|
131
|
+
} catch (error) {
|
|
132
|
+
if (signal?.aborted) {
|
|
133
|
+
throw error;
|
|
134
|
+
}
|
|
135
|
+
const reason = error?.name === "TimeoutError" ? "se acabó el tiempo" : "la petición no llegó al servidor";
|
|
136
|
+
log.error(reason, { method, url, cause: error?.name });
|
|
137
|
+
throw new ApiError({ status: API_ERROR_STATUS.offline });
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
const request = async (method, path, {
|
|
141
|
+
body,
|
|
142
|
+
params,
|
|
143
|
+
signal,
|
|
144
|
+
headers,
|
|
145
|
+
parse = API_RESPONSE_PARSE.json,
|
|
146
|
+
skipUnauthenticatedHandler = false,
|
|
147
|
+
timeoutMilliseconds = defaultTimeoutMilliseconds
|
|
148
|
+
} = {}) => {
|
|
149
|
+
const url = apiUrlOf(baseUrl, path, params);
|
|
150
|
+
let response = await send(method, url, { body, signal, headers, timeoutMilliseconds });
|
|
151
|
+
if (response.status === CSRF_TOKEN_MISMATCH_STATUS && csrf?.refreshPath) {
|
|
152
|
+
log.info("token CSRF vencido: se renueva y se reintenta", { method, url });
|
|
153
|
+
await send("GET", apiUrlOf(baseUrl, csrf.refreshPath), { signal, timeoutMilliseconds });
|
|
154
|
+
response = await send(method, url, { body, signal, headers, timeoutMilliseconds });
|
|
155
|
+
}
|
|
156
|
+
if (publishedBuildHeader) {
|
|
157
|
+
reportPublishedBuild(response.headers.get(publishedBuildHeader));
|
|
158
|
+
}
|
|
159
|
+
if (!response.ok) {
|
|
160
|
+
const problem = await readProblem(response);
|
|
161
|
+
const requestedLanguage = headersOf(url, void 0, headers)["Accept-Language"];
|
|
162
|
+
const responseLanguage = response.headers.get("content-language");
|
|
163
|
+
const apiError = new ApiError({
|
|
164
|
+
status: response.status,
|
|
165
|
+
problem,
|
|
166
|
+
translatedByServer: !responseLanguage || responseLanguage.startsWith(requestedLanguage),
|
|
167
|
+
retryAfterSeconds: retryAfterSecondsOf(response.headers.get("retry-after"))
|
|
168
|
+
});
|
|
169
|
+
log[response.status >= SERVER_ERROR_STATUS ? "error" : "debug"](`${method} ${url} → ${response.status}`, {
|
|
170
|
+
code: apiError.code,
|
|
171
|
+
requestId: apiError.requestId ?? response.headers.get("x-request-id")
|
|
172
|
+
});
|
|
173
|
+
if (apiError.isUnauthenticated && !skipUnauthenticatedHandler) {
|
|
174
|
+
onUnauthenticated?.(apiError);
|
|
175
|
+
}
|
|
176
|
+
throw apiError;
|
|
177
|
+
}
|
|
178
|
+
if (parse === API_RESPONSE_PARSE.response) {
|
|
179
|
+
return response;
|
|
180
|
+
}
|
|
181
|
+
if (parse === API_RESPONSE_PARSE.blob) {
|
|
182
|
+
return response.blob();
|
|
183
|
+
}
|
|
184
|
+
if (response.status === NO_CONTENT_STATUS) {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
const text = await response.text();
|
|
188
|
+
if (!text) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
try {
|
|
192
|
+
return JSON.parse(text);
|
|
193
|
+
} catch {
|
|
194
|
+
log.error(`${method} ${url} respondió algo que no es JSON`, { contentType: response.headers.get("content-type") });
|
|
195
|
+
throw new ApiError({ status: SERVER_ERROR_STATUS });
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
const download = async (path, { params, signal, onDownloadProgress, fallbackFileName = "descarga", timeoutMilliseconds = NO_TIMEOUT } = {}) => {
|
|
199
|
+
const response = await request("GET", path, { params, signal, parse: API_RESPONSE_PARSE.response, timeoutMilliseconds });
|
|
200
|
+
const blob = await readBlobWithProgress(response, onDownloadProgress);
|
|
201
|
+
const fileName = fileNameFromContentDisposition(response.headers.get("content-disposition"), fallbackFileName);
|
|
202
|
+
const contentType = String(response.headers.get("content-type") ?? "").split(";")[0].trim();
|
|
203
|
+
if (contentType === XLSX_CONTENT_TYPE && !await isCompleteZip(blob)) {
|
|
204
|
+
const requestId = response.headers.get("x-request-id");
|
|
205
|
+
log.error(`GET ${path} → el Excel llegó incompleto: el servidor falló a media escritura`, { requestId, fileName });
|
|
206
|
+
throw new ApiError({ status: SERVER_ERROR_STATUS, problem: { request_id: requestId } });
|
|
207
|
+
}
|
|
208
|
+
return { blob, fileName };
|
|
209
|
+
};
|
|
210
|
+
return {
|
|
211
|
+
request,
|
|
212
|
+
get: (path, options) => request("GET", path, options),
|
|
213
|
+
post: (path, body, options) => request("POST", path, { ...options, body }),
|
|
214
|
+
put: (path, body, options) => request("PUT", path, { ...options, body }),
|
|
215
|
+
patch: (path, body, options) => request("PATCH", path, { ...options, body }),
|
|
216
|
+
delete: (path, options) => request("DELETE", path, options),
|
|
217
|
+
download
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
export {
|
|
221
|
+
API_RESPONSE_PARSE,
|
|
222
|
+
apiUrlOf,
|
|
223
|
+
createApiClient,
|
|
224
|
+
retryAfterSecondsOf
|
|
225
|
+
};
|
|
226
|
+
//# sourceMappingURL=createApiClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createApiClient.js","sources":["../../src/api/createApiClient.js"],"sourcesContent":["// La petición de la casa: TODO lo que habla con el servidor pasa por un cliente armado aquí, con fetch del navegador (sin\n// axios ni otra librería). Lo que resuelve UNA vez y no en cada pantalla:\n// - Accept-Language con el idioma vigente de ToolkitProvider en CADA petición: el servidor responde title y detail ya\n// traducidos. Cambiar el idioma aplica a la siguiente petición sin recargar.\n// - errores como ApiError (ApiError.js): el problema RFC 9457 del servidor con el mensaje ya traducido; si la\n// respuesta llegó en otro idioma (un error que armó nginx), el texto genérico del paquete. Sin red o se acabó el\n// tiempo: un ApiError con status 0, la misma forma, para que la pantalla no tenga dos formas de error.\n// - cancelar NO es un error: el AbortError se relanza intacto (quien canceló ya sabe por qué).\n// - 401 (la sesión se venció a media consulta): avisa a onUnauthenticated, que normalmente lleva a iniciar sesión. Una\n// petición que espera el 401 (preguntar si hay sesión al arrancar, el login) pasa skipUnauthenticatedHandler.\n// - el aviso «Hay una versión nueva»: cada respuesta trae en un header qué compilación del front está publicada y se\n// le entrega a reportPublishedBuild.\n// - Laravel (Sanctum): con csrf, manda la cookie XSRF-TOKEN en su header (solo al mismo origen) y ante un 419 pide una\n// cookie nueva y repite la petición UNA vez.\n// - cuerpo objeto → JSON; FormData, Blob y URLSearchParams van tal cual (el navegador pone su boundary).\n// - descargas: el Blob y el nombre que mandó el servidor, con avance; un Excel que llegó cortado (el servidor falló a\n// media escritura después de responder 200) no se entrega.\n//\n// const api = createApiClient({baseUrl: '/api/v1', onUnauthenticated: () => navigate('/sign-in')});\n// const orders = await api.get('/orders', {params: {page: 2}, signal});\n// await api.post('/orders', {customerId: 7});\n//\n// Se arma uno por proyecto (en su core) y las pantallas lo usan desde su *Api.js.\n//\n// Funciones puras, no renderizan: function (regla de la casa).\nimport {ApiError, API_ERROR_STATUS} from '@/api/ApiError.js';\nimport {XLSX_CONTENT_TYPE, fileNameFromContentDisposition, isCompleteZip} from '@/files.js';\nimport {CSRF_TOKEN_MISMATCH_STATUS} from '@/laravel/csrfRetry.js';\nimport {createLogger} from '@/observability/logger.js';\nimport {reportPublishedBuild} from '@/observability/publishedBuild.js';\nimport {DEFAULT_LANGUAGE, toolkitSettings} from '@/toolkit/toolkitSettings.js';\n\nconst log = createLogger('api');\n\n/** Cómo se lee una respuesta que salió bien. */\nexport const API_RESPONSE_PARSE = Object.freeze({json: 'json', blob: 'blob', response: 'response'});\n\n// Las consultas se cortan a los 60 s; las descargas van sin límite (0): el servidor arma el archivo mientras lo manda y\n// uno grande no cabe en 60 s. No se queda colgada: se cancela desde el panel de descargas.\nconst DEFAULT_TIMEOUT_MILLISECONDS = 60_000;\nconst NO_TIMEOUT = 0;\nconst DEFAULT_PUBLISHED_BUILD_HEADER = 'X-Frontend-Build';\nconst NO_CONTENT_STATUS = 204;\nconst SERVER_ERROR_STATUS = 500;\n\n/**\n * La dirección completa: la base del cliente más el camino, con los parámetros. Un camino que ya trae http(s) va tal cual.\n * Los parámetros vacíos (undefined, null) no viajan; una lista viaja repetida (estado=a&estado=b).\n *\n * @param {string} baseUrl\n * @param {string} path\n * @param {Record<string, unknown>} [params]\n * @returns {string}\n */\nexport function apiUrlOf(baseUrl, path, params) {\n const url = /^https?:/i.test(path) ? path : `${baseUrl}${path}`;\n const query = new URLSearchParams();\n for (const [name, value] of Object.entries(params ?? {})) {\n for (const item of [].concat(value)) {\n if (item !== undefined && item !== null) {\n query.append(name, String(item));\n }\n }\n }\n const queryText = query.toString();\n if (!queryText) {\n return url;\n }\n return `${url}${url.includes('?') ? '&' : '?'}${queryText}`;\n}\n\n/**\n * ¿El cuerpo va tal cual? FormData (archivos), Blob y URLSearchParams los arma el navegador con su propio tipo.\n *\n * @param {unknown} body\n * @returns {boolean}\n */\nfunction isRawBody(body) {\n return (typeof FormData !== 'undefined' && body instanceof FormData)\n || (typeof Blob !== 'undefined' && body instanceof Blob)\n || body instanceof URLSearchParams\n || body instanceof ArrayBuffer;\n}\n\n/**\n * El valor de una cookie del navegador (la XSRF-TOKEN de Laravel), o null.\n *\n * @param {string} cookieName\n * @returns {string|null}\n */\nfunction readCookie(cookieName) {\n if (typeof document === 'undefined') {\n return null;\n }\n const prefix = `${cookieName}=`;\n const cookie = document.cookie.split(';').map((part) => part.trim()).find((part) => part.startsWith(prefix));\n return cookie ? decodeURIComponent(cookie.slice(prefix.length)) : null;\n}\n\n/**\n * ¿La dirección es del mismo origen que la página? El token CSRF solo viaja al servidor propio: mandarlo a otro dominio\n * se lo regalaría.\n *\n * @param {string} url\n * @returns {boolean}\n */\nfunction isSameOrigin(url) {\n if (typeof window === 'undefined' || !/^https?:/i.test(url)) {\n return true;\n }\n return new URL(url).origin === window.location.origin;\n}\n\n/**\n * Retry-After en segundos: el estándar admite segundos o una fecha HTTP.\n *\n * @param {string|null} retryAfterHeader\n * @returns {number|null}\n */\nexport function retryAfterSecondsOf(retryAfterHeader) {\n if (!retryAfterHeader) {\n return null;\n }\n if (/^\\d+$/.test(retryAfterHeader.trim())) {\n return Number(retryAfterHeader.trim());\n }\n const retryAt = Date.parse(retryAfterHeader);\n return Number.isNaN(retryAt) ? null : Math.max(0, Math.ceil((retryAt - Date.now()) / 1000));\n}\n\n/**\n * El cuerpo RFC 9457 de una respuesta de error, o null si no es JSON (un 502 del proxy en HTML).\n *\n * @param {Response} response\n * @returns {Promise<object|null>}\n */\nasync function readProblem(response) {\n try {\n const body = JSON.parse(await response.text());\n return body && typeof body === 'object' && !Array.isArray(body) ? body : null;\n } catch {\n return null;\n }\n}\n\n/**\n * La señal de la petición: la de quien la pidió (para cancelar) y la del tiempo máximo, juntas.\n *\n * @param {AbortSignal|undefined} signal\n * @param {number} timeoutMilliseconds 0 = sin límite\n * @returns {AbortSignal|undefined}\n */\nfunction combinedSignalOf(signal, timeoutMilliseconds) {\n const signals = [signal, timeoutMilliseconds > 0 ? AbortSignal.timeout(timeoutMilliseconds) : null].filter(Boolean);\n if (signals.length < 2) {\n return signals[0];\n }\n return AbortSignal.any(signals);\n}\n\n/**\n * Lee el cuerpo de una descarga avisando cuánto lleva. total viene en null cuando el servidor arma el archivo al vuelo\n * (sin Content-Length).\n *\n * @param {Response} response\n * @param {((progress: {loaded: number, total: number|null}) => void)|undefined} onDownloadProgress\n * @returns {Promise<Blob>}\n */\nasync function readBlobWithProgress(response, onDownloadProgress) {\n if (!onDownloadProgress || !response.body) {\n return response.blob();\n }\n const total = Number(response.headers.get('content-length')) || null;\n const reader = response.body.getReader();\n const chunks = [];\n let loaded = 0;\n for (let part = await reader.read(); !part.done; part = await reader.read()) {\n chunks.push(part.value);\n loaded += part.value.byteLength;\n onDownloadProgress({loaded, total});\n }\n return new Blob(chunks, {type: response.headers.get('content-type') ?? ''});\n}\n\n/**\n * Lo que acepta cada petición.\n *\n * @typedef {object} ApiRequestOptions\n * @property {unknown} [body] objeto → JSON; FormData, Blob o URLSearchParams tal cual\n * @property {Record<string, unknown>} [params] los de la dirección (?page=2)\n * @property {AbortSignal} [signal] para cancelar\n * @property {Record<string, string>} [headers]\n * @property {'json'|'blob'|'response'} [parse] cómo se lee la respuesta (API_RESPONSE_PARSE); por omisión JSON\n * @property {boolean} [skipUnauthenticatedHandler] un 401 que se espera (¿hay sesión?, el login)\n * @property {number} [timeoutMilliseconds] el de esta petición\n */\n\n/**\n * Lo que acepta una descarga.\n *\n * @typedef {object} ApiDownloadOptions\n * @property {Record<string, unknown>} [params]\n * @property {AbortSignal} [signal]\n * @property {(progress: {loaded: number, total: number|null}) => void} [onDownloadProgress]\n * @property {string} [fallbackFileName] si el servidor no manda el nombre\n * @property {number} [timeoutMilliseconds] por omisión sin límite\n */\n\n/**\n * El cliente del proyecto: cada método regresa el JSON de la respuesta (null si vino vacía) o truena con un ApiError.\n *\n * @typedef {object} ApiClient\n * @property {(method: string, path: string, options?: ApiRequestOptions) => Promise<any>} request\n * @property {(path: string, options?: ApiRequestOptions) => Promise<any>} get\n * @property {(path: string, body?: unknown, options?: ApiRequestOptions) => Promise<any>} post\n * @property {(path: string, body?: unknown, options?: ApiRequestOptions) => Promise<any>} put\n * @property {(path: string, body?: unknown, options?: ApiRequestOptions) => Promise<any>} patch\n * @property {(path: string, options?: ApiRequestOptions) => Promise<any>} delete\n * @property {(path: string, options?: ApiDownloadOptions) => Promise<{blob: Blob, fileName: string}>} download\n */\n\n/**\n * Arma el cliente del proyecto.\n *\n * @param {object} [options]\n * @param {string} [options.baseUrl] lo que va antes de cada camino, p. ej. '/api/v1'\n * @param {RequestCredentials} [options.credentials] 'same-origin' (por omisión, la cookie de sesión del mismo dominio) o\n * 'include' (un API en otro dominio con cookies)\n * @param {() => string|null|undefined} [options.getToken] con él cada petición lleva Authorization: Bearer; sin token, va\n * sin el header (el servidor responde 401)\n * @param {Record<string, string>} [options.headers] los que van en todas las peticiones\n * @param {string|null} [options.publishedBuildHeader] el header con la compilación publicada; null para no leerlo\n * @param {{cookieName?: string, headerName?: string, refreshPath?: string}|null} [options.csrf] Laravel Sanctum:\n * {refreshPath: '/auth/csrf-token'}; por omisión la cookie XSRF-TOKEN y el header X-XSRF-TOKEN\n * @param {number} [options.timeoutMilliseconds] el tiempo máximo de una consulta (0 = sin límite); por omisión 60 s\n * @param {(error: ApiError) => void} [options.onUnauthenticated] qué hacer con un 401 (normalmente ir a iniciar sesión)\n * @param {typeof fetch} [options.fetch] para un servidor de mentira o para las pruebas; por omisión el del navegador\n * @returns {ApiClient}\n */\nexport function createApiClient({\n baseUrl = '',\n credentials = 'same-origin',\n getToken,\n headers: commonHeaders = {},\n publishedBuildHeader = DEFAULT_PUBLISHED_BUILD_HEADER,\n csrf = null,\n timeoutMilliseconds: defaultTimeoutMilliseconds = DEFAULT_TIMEOUT_MILLISECONDS,\n onUnauthenticated,\n fetch: fetchImplementation,\n} = {}) {\n // OJO: se lee al pedir, no al armar el cliente: así un servidor de mentira que se conecta después también sirve\n const fetchOf = () => fetchImplementation ?? globalThis.fetch;\n const csrfCookieName = csrf?.cookieName ?? 'XSRF-TOKEN';\n const csrfHeaderName = csrf?.headerName ?? 'X-XSRF-TOKEN';\n\n /** Los headers de una petición: los comunes, el idioma vigente, el token y el CSRF. */\n const headersOf = (url, body, extraHeaders) => {\n const headers = {\n Accept: 'application/json',\n 'Accept-Language': toolkitSettings().language ?? DEFAULT_LANGUAGE,\n ...commonHeaders,\n ...extraHeaders,\n };\n if (body !== undefined && !isRawBody(body)) {\n headers['Content-Type'] = 'application/json';\n }\n const token = getToken?.();\n if (token) {\n headers.Authorization = `Bearer ${token}`;\n }\n const csrfToken = csrf && isSameOrigin(url) ? readCookie(csrfCookieName) : null;\n if (csrfToken) {\n headers[csrfHeaderName] = csrfToken;\n }\n return headers;\n };\n\n /** La petición al servidor, ya con su respuesta o con el ApiError de «sin respuesta». */\n const send = async (method, url, {body, signal, headers, timeoutMilliseconds}) => {\n const finalHeaders = headersOf(url, body, headers);\n try {\n return await fetchOf()(url, {\n method,\n headers: finalHeaders,\n body: body === undefined || isRawBody(body) ? body : JSON.stringify(body),\n credentials,\n signal: combinedSignalOf(signal, timeoutMilliseconds),\n });\n } catch (error) {\n // cancelar no es un error de negocio: quien canceló ya sabe por qué\n if (signal?.aborted) {\n throw error;\n }\n const reason = error?.name === 'TimeoutError' ? 'se acabó el tiempo' : 'la petición no llegó al servidor';\n log.error(reason, {method, url, cause: error?.name});\n throw new ApiError({status: API_ERROR_STATUS.offline});\n }\n };\n\n /**\n * Cualquier petición.\n *\n * @param {string} method 'GET', 'POST', 'PUT', 'PATCH' o 'DELETE'\n * @param {string} path relativo a baseUrl (o completo con http)\n * @param {object} [options]\n * @param {unknown} [options.body] objeto → JSON; FormData, Blob o URLSearchParams tal cual\n * @param {Record<string, unknown>} [options.params] los de la dirección (?page=2)\n * @param {AbortSignal} [options.signal] para cancelar\n * @param {Record<string, string>} [options.headers]\n * @param {'json'|'blob'|'response'} [options.parse] cómo se lee la respuesta (API_RESPONSE_PARSE); por omisión JSON\n * @param {boolean} [options.skipUnauthenticatedHandler] un 401 que se espera (¿hay sesión?, el login)\n * @param {number} [options.timeoutMilliseconds] el de esta petición\n * @returns {Promise<any>} el JSON (null si vino vacío o 204), el Blob o la Response\n */\n const request = async (method, path, {\n body, params, signal, headers, parse = API_RESPONSE_PARSE.json, skipUnauthenticatedHandler = false,\n timeoutMilliseconds = defaultTimeoutMilliseconds,\n } = {}) => {\n const url = apiUrlOf(baseUrl, path, params);\n let response = await send(method, url, {body, signal, headers, timeoutMilliseconds});\n\n // 419 de Laravel: la cookie CSRF venció; se pide una nueva y se repite la MISMA petición una sola vez\n if (response.status === CSRF_TOKEN_MISMATCH_STATUS && csrf?.refreshPath) {\n log.info('token CSRF vencido: se renueva y se reintenta', {method, url});\n await send('GET', apiUrlOf(baseUrl, csrf.refreshPath), {signal, timeoutMilliseconds});\n response = await send(method, url, {body, signal, headers, timeoutMilliseconds});\n }\n\n // cada respuesta (también las de error) dice qué compilación del front está publicada\n if (publishedBuildHeader) {\n reportPublishedBuild(response.headers.get(publishedBuildHeader));\n }\n\n if (!response.ok) {\n const problem = await readProblem(response);\n // un error que armó otro (nginx) puede llegar en otro idioma: ahí se usa el texto genérico del paquete\n const requestedLanguage = headersOf(url, undefined, headers)['Accept-Language'];\n const responseLanguage = response.headers.get('content-language');\n const apiError = new ApiError({\n status: response.status,\n problem,\n translatedByServer: !responseLanguage || responseLanguage.startsWith(requestedLanguage),\n retryAfterSeconds: retryAfterSecondsOf(response.headers.get('retry-after')),\n });\n // los 4xx son parte del flujo (un 422 es un formulario, un 401 al arrancar es «sin sesión»); los 5xx no\n log[response.status >= SERVER_ERROR_STATUS ? 'error' : 'debug'](`${method} ${url} → ${response.status}`, {\n code: apiError.code, requestId: apiError.requestId ?? response.headers.get('x-request-id'),\n });\n if (apiError.isUnauthenticated && !skipUnauthenticatedHandler) {\n onUnauthenticated?.(apiError);\n }\n throw apiError;\n }\n\n if (parse === API_RESPONSE_PARSE.response) {\n return response;\n }\n if (parse === API_RESPONSE_PARSE.blob) {\n return response.blob();\n }\n if (response.status === NO_CONTENT_STATUS) {\n return null;\n }\n // un 200 con el cuerpo vacío pasa de verdad; JSON.parse('') tronaría\n const text = await response.text();\n if (!text) {\n return null;\n }\n try {\n return JSON.parse(text);\n } catch {\n // un 200 que no es JSON: casi siempre la página de la app que respondió en lugar del API (el camino está mal)\n log.error(`${method} ${url} respondió algo que no es JSON`, {contentType: response.headers.get('content-type')});\n throw new ApiError({status: SERVER_ERROR_STATUS});\n }\n };\n\n /**\n * Descarga un archivo: el Blob y el nombre que mandó el servidor, con avance. Un Excel cortado no se entrega.\n *\n * @param {string} path\n * @param {object} [options]\n * @param {Record<string, unknown>} [options.params]\n * @param {AbortSignal} [options.signal]\n * @param {(progress: {loaded: number, total: number|null}) => void} [options.onDownloadProgress]\n * @param {string} [options.fallbackFileName] si el servidor no manda el nombre\n * @param {number} [options.timeoutMilliseconds] por omisión sin límite\n * @returns {Promise<{blob: Blob, fileName: string}>}\n * @throws {ApiError} status 500 si un Excel llegó incompleto\n */\n const download = async (path, {params, signal, onDownloadProgress, fallbackFileName = 'descarga', timeoutMilliseconds = NO_TIMEOUT} = {}) => {\n const response = await request('GET', path, {params, signal, parse: API_RESPONSE_PARSE.response, timeoutMilliseconds});\n const blob = await readBlobWithProgress(response, onDownloadProgress);\n const fileName = fileNameFromContentDisposition(response.headers.get('content-disposition'), fallbackFileName);\n // el tipo puede traer parámetros después del «;» (charset): solo cuenta lo de antes\n const contentType = String(response.headers.get('content-type') ?? '').split(';')[0].trim();\n if (contentType === XLSX_CONTENT_TYPE && !(await isCompleteZip(blob))) {\n const requestId = response.headers.get('x-request-id');\n log.error(`GET ${path} → el Excel llegó incompleto: el servidor falló a media escritura`, {requestId, fileName});\n throw new ApiError({status: SERVER_ERROR_STATUS, problem: {request_id: requestId}});\n }\n return {blob, fileName};\n };\n\n return {\n request,\n get: (path, options) => request('GET', path, options),\n post: (path, body, options) => request('POST', path, {...options, body}),\n put: (path, body, options) => request('PUT', path, {...options, body}),\n patch: (path, body, options) => request('PATCH', path, {...options, body}),\n delete: (path, options) => request('DELETE', path, options),\n download,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createLogger } from "../observability/logger.js";
|
|
2
|
+
const log = createLogger("chunks");
|
|
3
|
+
const RELOAD_STORAGE_KEY = "calcita:chunkReloadAt";
|
|
4
|
+
const RELOAD_COOLDOWN_MILLISECONDS = 15e3;
|
|
5
|
+
const STALE_CHUNK_MESSAGES = Object.freeze([
|
|
6
|
+
"failed to fetch dynamically imported module",
|
|
7
|
+
"error loading dynamically imported module",
|
|
8
|
+
"importing a module script failed",
|
|
9
|
+
"failed to load module script"
|
|
10
|
+
]);
|
|
11
|
+
function isStaleChunkError(error) {
|
|
12
|
+
const message = String(error?.message ?? error ?? "").toLowerCase();
|
|
13
|
+
return STALE_CHUNK_MESSAGES.some((knownMessage) => message.includes(knownMessage));
|
|
14
|
+
}
|
|
15
|
+
function reloadedRecently() {
|
|
16
|
+
try {
|
|
17
|
+
const reloadedAt = Number(window.sessionStorage.getItem(RELOAD_STORAGE_KEY) ?? 0);
|
|
18
|
+
return reloadedAt > 0 && Date.now() - reloadedAt < RELOAD_COOLDOWN_MILLISECONDS;
|
|
19
|
+
} catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function markReload() {
|
|
24
|
+
try {
|
|
25
|
+
window.sessionStorage.setItem(RELOAD_STORAGE_KEY, String(Date.now()));
|
|
26
|
+
} catch {
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function recoverFromStaleChunk(error) {
|
|
30
|
+
if (!isStaleChunkError(error)) {
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
if (reloadedRecently()) {
|
|
34
|
+
log.error("el archivo de la pantalla sigue sin cargar después de recargar", { cause: String(error) });
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
log.warn("archivo de una versión anterior: se recarga la página", { cause: String(error) });
|
|
38
|
+
markReload();
|
|
39
|
+
window.location.reload();
|
|
40
|
+
return new Promise(() => {
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
isStaleChunkError,
|
|
45
|
+
recoverFromStaleChunk
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=staleChunks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleChunks.js","sources":["../../src/api/staleChunks.js"],"sourcesContent":["// Sobrevivir a una publicación con la app abierta.\n//\n// El síntoma (Chrome): «Failed to fetch dynamically imported module: …/assets/orders-LUgRFrRF.js».\n//\n// Qué pasó: cada pantalla viaja en su propio archivo con la huella de su contenido en el nombre. Al publicar, los nombres\n// cambian y los viejos se borran. Quien tenía la app abierta sigue con el índice anterior en memoria: en cuanto entra a\n// una pantalla que no había abierto, pide un archivo que ya no existe. No es un error de red ni de la persona; le pasa a\n// cualquiera que tenga la pestaña abierta durante una publicación.\n//\n// Qué se hace: recargar UNA vez. La página nueva trae los nombres nuevos y la persona ve un parpadeo en lugar de una\n// pantalla rota. El candado contra el ciclo es la hora de la última recarga en sessionStorage: si se recargó hace menos de\n// RELOAD_COOLDOWN_MILLISECONDS, el error sigue su camino (un archivo que de verdad falta dejaría la pestaña recargándose\n// para siempre). La ventana es corta a propósito: otra publicación media hora después se tiene que poder recuperar igual.\n//\n// lazy: () => import('./OrdersPage.jsx').catch(recoverFromStaleChunk)\n//\n// Con react-router, withChunkRecovery(routes) de /react-router lo pone en todas las rutas lazy.\n//\n// Funciones puras, no renderizan: function (regla de la casa).\nimport {createLogger} from '@/observability/logger.js';\n\nconst log = createLogger('chunks');\n\nconst RELOAD_STORAGE_KEY = 'calcita:chunkReloadAt';\nconst RELOAD_COOLDOWN_MILLISECONDS = 15_000;\n\n// Cada navegador lo redacta distinto: Chromium «Failed to fetch dynamically imported module», Firefox «error loading\n// dynamically imported module», Safari «Importing a module script failed».\nconst STALE_CHUNK_MESSAGES = Object.freeze([\n 'failed to fetch dynamically imported module',\n 'error loading dynamically imported module',\n 'importing a module script failed',\n 'failed to load module script',\n]);\n\n/**\n * ¿El error es un archivo de pantalla que ya no existe (se publicó otra versión), y no otra cosa?\n *\n * @param {unknown} error\n * @returns {boolean}\n */\nexport function isStaleChunkError(error) {\n const message = String(error?.message ?? error ?? '').toLowerCase();\n return STALE_CHUNK_MESSAGES.some((knownMessage) => message.includes(knownMessage));\n}\n\n/** ¿Ya se recargó por esto hace poco? Sin sessionStorage no hay candado: mejor recargar una vez que dejar la pantalla rota. */\nfunction reloadedRecently() {\n try {\n const reloadedAt = Number(window.sessionStorage.getItem(RELOAD_STORAGE_KEY) ?? 0);\n return reloadedAt > 0 && Date.now() - reloadedAt < RELOAD_COOLDOWN_MILLISECONDS;\n } catch {\n return false;\n }\n}\n\nfunction markReload() {\n try {\n window.sessionStorage.setItem(RELOAD_STORAGE_KEY, String(Date.now()));\n } catch {\n // almacenamiento bloqueado: se recarga igual, solo sin candado\n }\n}\n\n/**\n * Lo que va en el .catch() de un import dinámico: si el archivo es de una versión vieja, recarga una vez; si no, deja\n * pasar el error tal cual para que lo vea quien corresponda.\n *\n * @param {unknown} error\n * @returns {Promise<never>}\n */\nexport function recoverFromStaleChunk(error) {\n if (!isStaleChunkError(error)) {\n throw error;\n }\n if (reloadedRecently()) {\n // ya se recargó y volvió a fallar: no es una publicación, el archivo de verdad falta. Nunca fallar en silencio\n log.error('el archivo de la pantalla sigue sin cargar después de recargar', {cause: String(error)});\n throw error;\n }\n log.warn('archivo de una versión anterior: se recarga la página', {cause: String(error)});\n markReload();\n window.location.reload();\n // OJO: la promesa NUNCA se resuelve, a propósito: la página ya se está yendo y resolverla haría que se pintara un error\n // un instante antes de recargar\n return new Promise(() => {});\n}\n"],"names":[],"mappings":";AAqBA,MAAM,MAAM,aAAa,QAAQ;AAEjC,MAAM,qBAAqB;AAC3B,MAAM,+BAA+B;AAIrC,MAAM,uBAAuB,OAAO,OAAO;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;AAQM,SAAS,kBAAkB,OAAO;AACrC,QAAM,UAAU,OAAO,OAAO,WAAW,SAAS,EAAE,EAAE,YAAW;AACjE,SAAO,qBAAqB,KAAK,CAAC,iBAAiB,QAAQ,SAAS,YAAY,CAAC;AACrF;AAGA,SAAS,mBAAmB;AACxB,MAAI;AACA,UAAM,aAAa,OAAO,OAAO,eAAe,QAAQ,kBAAkB,KAAK,CAAC;AAChF,WAAO,aAAa,KAAK,KAAK,IAAG,IAAK,aAAa;AAAA,EACvD,QAAQ;AACJ,WAAO;AAAA,EACX;AACJ;AAEA,SAAS,aAAa;AAClB,MAAI;AACA,WAAO,eAAe,QAAQ,oBAAoB,OAAO,KAAK,IAAG,CAAE,CAAC;AAAA,EACxE,QAAQ;AAAA,EAER;AACJ;AASO,SAAS,sBAAsB,OAAO;AACzC,MAAI,CAAC,kBAAkB,KAAK,GAAG;AAC3B,UAAM;AAAA,EACV;AACA,MAAI,iBAAgB,GAAI;AAEpB,QAAI,MAAM,kEAAkE,EAAC,OAAO,OAAO,KAAK,EAAC,CAAC;AAClG,UAAM;AAAA,EACV;AACA,MAAI,KAAK,yDAAyD,EAAC,OAAO,OAAO,KAAK,EAAC,CAAC;AACxF,aAAU;AACV,SAAO,SAAS,OAAM;AAGtB,SAAO,IAAI,QAAQ,MAAM;AAAA,EAAC,CAAC;AAC/B;"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
|
|
5
|
+
import { useToolkitNavigation } from "../toolkit/toolkitContext.js";
|
|
6
|
+
import Avatar from "@mui/material/Avatar";
|
|
7
|
+
import Box from "@mui/material/Box";
|
|
8
|
+
import Divider from "@mui/material/Divider";
|
|
9
|
+
import IconButton from "@mui/material/IconButton";
|
|
10
|
+
import ListItemIcon from "@mui/material/ListItemIcon";
|
|
11
|
+
import ListItemText from "@mui/material/ListItemText";
|
|
12
|
+
import Menu from "@mui/material/Menu";
|
|
13
|
+
import MenuItem from "@mui/material/MenuItem";
|
|
14
|
+
import Tooltip from "@mui/material/Tooltip";
|
|
15
|
+
import Typography from "@mui/material/Typography";
|
|
16
|
+
import LogoutIcon from "@mui/icons-material/Logout";
|
|
17
|
+
import PersonOutlineIcon from "@mui/icons-material/PersonOutline";
|
|
18
|
+
import { initialsOf, menuItemLabelOf } from "./menuItemText.js";
|
|
19
|
+
import { barMenuPlacementOf } from "./barMenuPlacement.js";
|
|
20
|
+
function AccountMenu({ user, profilePath, accountMenuItems = [], onSignOut, isSigningOut = false, settings }) {
|
|
21
|
+
const { t } = useToolkitTranslation("layout");
|
|
22
|
+
const { Link: RouterLink } = useToolkitNavigation();
|
|
23
|
+
const [anchorElement, setAnchorElement] = useState(null);
|
|
24
|
+
const closeMenu = () => setAnchorElement(null);
|
|
25
|
+
const menuLinks = [
|
|
26
|
+
...profilePath ? [{ to: profilePath, labelKey: "layout:account.myProfile", Icon: PersonOutlineIcon }] : [],
|
|
27
|
+
...accountMenuItems
|
|
28
|
+
];
|
|
29
|
+
const placement = barMenuPlacementOf(anchorElement);
|
|
30
|
+
const signOut = () => {
|
|
31
|
+
closeMenu();
|
|
32
|
+
onSignOut();
|
|
33
|
+
};
|
|
34
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
35
|
+
/* @__PURE__ */ jsx(Tooltip, { title: t("account.open"), children: /* @__PURE__ */ jsx(IconButton, { size: "small", "aria-label": t("account.open"), "aria-haspopup": "menu", onClick: (event) => setAnchorElement(event.currentTarget), sx: { p: 0.5 }, children: /* @__PURE__ */ jsx(Avatar, { src: user.avatarUrl, alt: "", sx: { width: 32, height: 32, fontSize: "0.875rem", bgcolor: "secondary.main", color: "secondary.contrastText" }, children: initialsOf(user.name) }) }) }),
|
|
36
|
+
/* @__PURE__ */ jsxs(
|
|
37
|
+
Menu,
|
|
38
|
+
{
|
|
39
|
+
anchorEl: anchorElement,
|
|
40
|
+
open: Boolean(anchorElement),
|
|
41
|
+
onClose: closeMenu,
|
|
42
|
+
anchorOrigin: placement.anchorOrigin,
|
|
43
|
+
transformOrigin: placement.transformOrigin,
|
|
44
|
+
slotProps: { paper: { sx: { minWidth: settings ? 300 : 240, maxWidth: 360, ...placement.gapSx } } },
|
|
45
|
+
children: [
|
|
46
|
+
/* @__PURE__ */ jsxs(Box, { sx: { px: 2, py: 1.25 }, children: [
|
|
47
|
+
/* @__PURE__ */ jsx(Typography, { variant: "subtitle2", noWrap: true, sx: { fontWeight: 600 }, children: user.name }),
|
|
48
|
+
user.email && /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", noWrap: true, children: user.email }),
|
|
49
|
+
user.subtitle && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", component: "p", noWrap: true, children: user.subtitle })
|
|
50
|
+
] }),
|
|
51
|
+
settings && /* @__PURE__ */ jsx(Divider, {}),
|
|
52
|
+
settings && /* @__PURE__ */ jsx(Box, { sx: { py: 0.5 }, children: settings }),
|
|
53
|
+
menuLinks.length > 0 && /* @__PURE__ */ jsx(Divider, {}),
|
|
54
|
+
menuLinks.map((menuLink) => {
|
|
55
|
+
const Icon = menuLink.Icon;
|
|
56
|
+
const linkProps = menuLink.to ? { component: RouterLink, to: menuLink.to } : {};
|
|
57
|
+
return /* @__PURE__ */ jsxs(
|
|
58
|
+
MenuItem,
|
|
59
|
+
{
|
|
60
|
+
...linkProps,
|
|
61
|
+
onClick: () => {
|
|
62
|
+
closeMenu();
|
|
63
|
+
menuLink.onClick?.();
|
|
64
|
+
},
|
|
65
|
+
children: [
|
|
66
|
+
Icon && /* @__PURE__ */ jsx(ListItemIcon, { children: /* @__PURE__ */ jsx(Icon, { fontSize: "small" }) }),
|
|
67
|
+
/* @__PURE__ */ jsx(ListItemText, { primary: menuItemLabelOf(menuLink, t) })
|
|
68
|
+
]
|
|
69
|
+
},
|
|
70
|
+
menuLink.to ?? menuItemLabelOf(menuLink, t)
|
|
71
|
+
);
|
|
72
|
+
}),
|
|
73
|
+
onSignOut && /* @__PURE__ */ jsx(Divider, {}),
|
|
74
|
+
onSignOut && /* @__PURE__ */ jsxs(MenuItem, { onClick: signOut, disabled: isSigningOut, children: [
|
|
75
|
+
/* @__PURE__ */ jsx(ListItemIcon, { children: /* @__PURE__ */ jsx(LogoutIcon, { fontSize: "small" }) }),
|
|
76
|
+
/* @__PURE__ */ jsx(ListItemText, { primary: t("signOut") })
|
|
77
|
+
] })
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
)
|
|
81
|
+
] });
|
|
82
|
+
}
|
|
83
|
+
export {
|
|
84
|
+
AccountMenu as default
|
|
85
|
+
};
|
|
86
|
+
//# sourceMappingURL=AccountMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AccountMenu.js","sources":["../../src/appShell/AccountMenu.jsx"],"sourcesContent":["// La cuenta de quien está dentro, arriba a la derecha (como en las plantillas de MUI): un avatar con sus iniciales (o su\n// foto) que abre un menú con su nombre y correo, Mi perfil, lo que el proyecto agregue (accountMenuItems: Facturación,\n// Mis llaves…) y Salir.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {useToolkitNavigation} from '@/toolkit/toolkitContext.js';\nimport Avatar from '@mui/material/Avatar';\nimport Box from '@mui/material/Box';\nimport Divider from '@mui/material/Divider';\nimport IconButton from '@mui/material/IconButton';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport Menu from '@mui/material/Menu';\nimport MenuItem from '@mui/material/MenuItem';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport LogoutIcon from '@mui/icons-material/Logout';\nimport PersonOutlineIcon from '@mui/icons-material/PersonOutline';\n\nimport {initialsOf, menuItemLabelOf} from '@/appShell/menuItemText.js';\nimport {barMenuPlacementOf} from '@/appShell/barMenuPlacement.js';\n\n/**\n * @param {object} props\n * @param {{name: string, email?: string, subtitle?: string, avatarUrl?: string}} props.user\n * @param {string} [props.profilePath] sin ella no sale «Mi perfil»\n * @param {Array<{to?: string, onClick?: Function, label?: string, labelKey?: string, Icon?: import('react').ElementType}>} [props.accountMenuItems]\n * @param {() => void} [props.onSignOut] sin él no sale «Salir»\n * @param {boolean} [props.isSigningOut]\n * @param {import('react').ReactNode} [props.settings] los ajustes de la app, entre los datos de la persona y sus ligas\n */\nexport default function AccountMenu({user, profilePath, accountMenuItems = [], onSignOut, isSigningOut = false, settings}) {\n const {t} = useToolkitTranslation('layout');\n const {Link: RouterLink} = useToolkitNavigation();\n const [anchorElement, setAnchorElement] = useState(null);\n const closeMenu = () => setAnchorElement(null);\n const menuLinks = [\n ...(profilePath ? [{to: profilePath, labelKey: 'layout:account.myProfile', Icon: PersonOutlineIcon}] : []),\n ...accountMenuItems,\n ];\n\n // hacia arriba si la barra está abajo (teléfono con vidrio)\n const placement = barMenuPlacementOf(anchorElement);\n\n const signOut = () => {\n closeMenu();\n onSignOut();\n };\n\n return (\n <>\n <Tooltip title={t('account.open')}>\n <IconButton size=\"small\" aria-label={t('account.open')} aria-haspopup=\"menu\" onClick={(event) => setAnchorElement(event.currentTarget)} sx={{p: 0.5}}>\n <Avatar src={user.avatarUrl} alt=\"\" sx={{width: 32, height: 32, fontSize: '0.875rem', bgcolor: 'secondary.main', color: 'secondary.contrastText'}}>\n {initialsOf(user.name)}\n </Avatar>\n </IconButton>\n </Tooltip>\n <Menu anchorEl={anchorElement} open={Boolean(anchorElement)} onClose={closeMenu}\n anchorOrigin={placement.anchorOrigin} transformOrigin={placement.transformOrigin}\n slotProps={{paper: {sx: {minWidth: settings ? 300 : 240, maxWidth: 360, ...placement.gapSx}}}}>\n <Box sx={{px: 2, py: 1.25}}>\n <Typography variant=\"subtitle2\" noWrap sx={{fontWeight: 600}}>{user.name}</Typography>\n {user.email && <Typography variant=\"body2\" color=\"text.secondary\" noWrap>{user.email}</Typography>}\n {user.subtitle && <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\" noWrap>{user.subtitle}</Typography>}\n </Box>\n {/* los ajustes de la app (letra, idioma, claro u oscuro y los del proyecto): en la cuenta y no sueltos en la barra */}\n {settings && <Divider />}\n {settings && <Box sx={{py: 0.5}}>{settings}</Box>}\n {menuLinks.length > 0 && <Divider />}\n {menuLinks.map((menuLink) => {\n const Icon = menuLink.Icon;\n const linkProps = menuLink.to ? {component: RouterLink, to: menuLink.to} : {};\n return (\n <MenuItem key={menuLink.to ?? menuItemLabelOf(menuLink, t)} {...linkProps}\n onClick={() => {\n closeMenu();\n menuLink.onClick?.();\n }}>\n {Icon && <ListItemIcon><Icon fontSize=\"small\" /></ListItemIcon>}\n <ListItemText primary={menuItemLabelOf(menuLink, t)} />\n </MenuItem>\n );\n })}\n {onSignOut && <Divider />}\n {onSignOut && (\n <MenuItem onClick={signOut} disabled={isSigningOut}>\n <ListItemIcon><LogoutIcon fontSize=\"small\" /></ListItemIcon>\n <ListItemText primary={t('signOut')} />\n </MenuItem>\n )}\n </Menu>\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|