@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,64 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import Alert from "@mui/material/Alert";
|
|
5
|
+
import Button from "@mui/material/Button";
|
|
6
|
+
import IconButton from "@mui/material/IconButton";
|
|
7
|
+
import Snackbar from "@mui/material/Snackbar";
|
|
8
|
+
import CloseRoundedIcon from "@mui/icons-material/CloseRounded";
|
|
9
|
+
import InstallMobileRoundedIcon from "@mui/icons-material/InstallMobileRounded";
|
|
10
|
+
import { aboveMobileTabBarOf } from "../appShell/shellSizes.js";
|
|
11
|
+
import { usesMobileTabBar } from "../appShell/tabBarRule.js";
|
|
12
|
+
import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
|
|
13
|
+
import { INSTALL_VARIANT } from "./installInstructions.js";
|
|
14
|
+
import InstallInstructionsDialog from "./InstallInstructionsDialog.js";
|
|
15
|
+
import { useInstallPrompt } from "./useInstallPrompt.js";
|
|
16
|
+
const TAB_BAR_GAP_PIXELS = 8;
|
|
17
|
+
function InstallPromptBanner({ message }) {
|
|
18
|
+
const { t } = useToolkitTranslation("common");
|
|
19
|
+
const { variant, dismissed, promptInstall, dismiss } = useInstallPrompt();
|
|
20
|
+
const [stepsOpen, setStepsOpen] = useState(false);
|
|
21
|
+
if (!variant || dismissed) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const isNative = variant === INSTALL_VARIANT.native;
|
|
25
|
+
const handleAction = () => {
|
|
26
|
+
if (isNative) {
|
|
27
|
+
promptInstall();
|
|
28
|
+
} else {
|
|
29
|
+
setStepsOpen(true);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const handleStepsClose = () => {
|
|
33
|
+
setStepsOpen(false);
|
|
34
|
+
dismiss();
|
|
35
|
+
};
|
|
36
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37
|
+
/* @__PURE__ */ jsx(
|
|
38
|
+
Snackbar,
|
|
39
|
+
{
|
|
40
|
+
open: true,
|
|
41
|
+
anchorOrigin: { vertical: "bottom", horizontal: "center" },
|
|
42
|
+
sx: (theme) => usesMobileTabBar(theme) ? aboveMobileTabBarOf(TAB_BAR_GAP_PIXELS) : { mb: "env(safe-area-inset-bottom)" },
|
|
43
|
+
children: /* @__PURE__ */ jsx(
|
|
44
|
+
Alert,
|
|
45
|
+
{
|
|
46
|
+
severity: "info",
|
|
47
|
+
icon: /* @__PURE__ */ jsx(InstallMobileRoundedIcon, {}),
|
|
48
|
+
sx: { width: "100%", alignItems: "center" },
|
|
49
|
+
action: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
50
|
+
/* @__PURE__ */ jsx(Button, { color: "inherit", size: "small", onClick: handleAction, children: isNative ? t("install.action") : t("install.howTo") }),
|
|
51
|
+
/* @__PURE__ */ jsx(IconButton, { size: "small", color: "inherit", "aria-label": t("install.dismiss"), onClick: dismiss, children: /* @__PURE__ */ jsx(CloseRoundedIcon, { fontSize: "small" }) })
|
|
52
|
+
] }),
|
|
53
|
+
children: message ?? t("install.banner")
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
),
|
|
58
|
+
/* @__PURE__ */ jsx(InstallInstructionsDialog, { variant, open: stepsOpen, onClose: handleStepsClose })
|
|
59
|
+
] });
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
InstallPromptBanner as default
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=InstallPromptBanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InstallPromptBanner.js","sources":["../../src/pwa/InstallPromptBanner.jsx"],"sourcesContent":["// La invitación a instalar la app, abajo al centro. Según el equipo (useInstallPrompt): con el diálogo del navegador, el\n// botón «Instalar»; en iPhone, iPad y Firefox de Android, «Cómo instalar» abre los pasos (InstallInstructionsDialog).\n// Ya instalada, sin manera de instalar o después de «Ahora no», no pinta nada; quien se arrepienta la encuentra en el menú\n// de la cuenta (InstallAppSetting).\n//\n// Color de información, no de advertencia: instalar es una sugerencia, no un problema. En el teléfono con vidrio va encima\n// de la barra de pestañas; sin ella, respeta la zona del gesto de inicio del iPhone.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Alert from '@mui/material/Alert';\nimport Button from '@mui/material/Button';\nimport IconButton from '@mui/material/IconButton';\nimport Snackbar from '@mui/material/Snackbar';\nimport CloseRoundedIcon from '@mui/icons-material/CloseRounded';\nimport InstallMobileRoundedIcon from '@mui/icons-material/InstallMobileRounded';\n\nimport {aboveMobileTabBarOf} from '@/appShell/shellSizes.js';\nimport {usesMobileTabBar} from '@/appShell/tabBarRule.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {INSTALL_VARIANT} from '@/pwa/installInstructions.js';\nimport InstallInstructionsDialog from '@/pwa/InstallInstructionsDialog.jsx';\nimport {useInstallPrompt} from '@/pwa/useInstallPrompt.js';\n\n// lo que se separa de la barra de pestañas (px)\nconst TAB_BAR_GAP_PIXELS = 8;\n\n/**\n * @param {object} [props]\n * @param {string} [props.message] ya traducido; por omisión el del paquete con el nombre de la app (appName de ToolkitProvider)\n */\nexport default function InstallPromptBanner({message}) {\n const {t} = useToolkitTranslation('common');\n const {variant, dismissed, promptInstall, dismiss} = useInstallPrompt();\n const [stepsOpen, setStepsOpen] = useState(false);\n\n // nada que ofrecer o ya dijo «Ahora no»\n if (!variant || dismissed) {\n return null;\n }\n\n const isNative = variant === INSTALL_VARIANT.native;\n\n const handleAction = () => {\n if (isNative) {\n promptInstall();\n } else {\n setStepsOpen(true);\n }\n };\n\n // si ya vio los pasos, no se le vuelven a ofrecer en cada visita\n const handleStepsClose = () => {\n setStepsOpen(false);\n dismiss();\n };\n\n return (\n <>\n <Snackbar open anchorOrigin={{vertical: 'bottom', horizontal: 'center'}}\n sx={(theme) => (usesMobileTabBar(theme)\n ? aboveMobileTabBarOf(TAB_BAR_GAP_PIXELS)\n : {mb: 'env(safe-area-inset-bottom)'})}>\n <Alert severity=\"info\" icon={<InstallMobileRoundedIcon />} sx={{width: '100%', alignItems: 'center'}}\n action={(\n <>\n <Button color=\"inherit\" size=\"small\" onClick={handleAction}>\n {isNative ? t('install.action') : t('install.howTo')}\n </Button>\n <IconButton size=\"small\" color=\"inherit\" aria-label={t('install.dismiss')} onClick={dismiss}>\n <CloseRoundedIcon fontSize=\"small\" />\n </IconButton>\n </>\n )}>\n {message ?? t('install.banner')}\n </Alert>\n </Snackbar>\n <InstallInstructionsDialog variant={variant} open={stepsOpen} onClose={handleStepsClose} />\n </>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAyBA,MAAM,qBAAqB;AAM3B,SAAwB,oBAAoB,EAAC,WAAU;AACnD,QAAM,EAAC,EAAA,IAAK,sBAAsB,QAAQ;AAC1C,QAAM,EAAC,SAAS,WAAW,eAAe,QAAA,IAAW,iBAAA;AACrD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAGhD,MAAI,CAAC,WAAW,WAAW;AACvB,WAAO;AAAA,EACX;AAEA,QAAM,WAAW,YAAY,gBAAgB;AAE7C,QAAM,eAAe,MAAM;AACvB,QAAI,UAAU;AACV,oBAAA;AAAA,IACJ,OAAO;AACH,mBAAa,IAAI;AAAA,IACrB;AAAA,EACJ;AAGA,QAAM,mBAAmB,MAAM;AAC3B,iBAAa,KAAK;AAClB,YAAA;AAAA,EACJ;AAEA,SACI,qBAAA,UAAA,EACI,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QAAS,MAAI;AAAA,QAAC,cAAc,EAAC,UAAU,UAAU,YAAY,SAAA;AAAA,QACpD,IAAI,CAAC,UAAW,iBAAiB,KAAK,IAChC,oBAAoB,kBAAkB,IACtC,EAAC,IAAI,8BAAA;AAAA,QACjB,UAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YAAM,UAAS;AAAA,YAAO,0BAAO,0BAAA,EAAyB;AAAA,YAAI,IAAI,EAAC,OAAO,QAAQ,YAAY,SAAA;AAAA,YACpF,QACI,qBAAA,UAAA,EACI,UAAA;AAAA,cAAA,oBAAC,QAAA,EAAO,OAAM,WAAU,MAAK,SAAQ,SAAS,cACzC,UAAA,WAAW,EAAE,gBAAgB,IAAI,EAAE,eAAe,GACvD;AAAA,kCACC,YAAA,EAAW,MAAK,SAAQ,OAAM,WAAU,cAAY,EAAE,iBAAiB,GAAG,SAAS,SAChF,UAAA,oBAAC,kBAAA,EAAiB,UAAS,SAAQ,EAAA,CACvC;AAAA,YAAA,GACJ;AAAA,YAEN,UAAA,WAAW,EAAE,gBAAgB;AAAA,UAAA;AAAA,QAAA;AAAA,MAClC;AAAA,IAAA;AAAA,wBAEH,2BAAA,EAA0B,SAAkB,MAAM,WAAW,SAAS,iBAAA,CAAkB;AAAA,EAAA,GAC7F;AAER;"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const IOS_LIQUID_GLASS_MAJOR = 26;
|
|
2
|
+
const INSTALL_VARIANT = Object.freeze({
|
|
3
|
+
native: "native",
|
|
4
|
+
// iPhone y iPad con iOS 26 o más nuevo
|
|
5
|
+
iosModern: "iosModern",
|
|
6
|
+
// iPhone con iOS 16 a 18
|
|
7
|
+
iosClassic: "iosClassic",
|
|
8
|
+
// Firefox de Android: no avisa, va a mano
|
|
9
|
+
androidFirefox: "androidFirefox"
|
|
10
|
+
});
|
|
11
|
+
function parseIOSMajor(userAgent = "") {
|
|
12
|
+
const fromOS = /OS (\d+)_/.exec(userAgent);
|
|
13
|
+
if (fromOS) {
|
|
14
|
+
return Number(fromOS[1]);
|
|
15
|
+
}
|
|
16
|
+
const fromVersion = /Version\/(\d+)/.exec(userAgent);
|
|
17
|
+
return fromVersion ? Number(fromVersion[1]) : null;
|
|
18
|
+
}
|
|
19
|
+
function detectPlatform(navigatorLike) {
|
|
20
|
+
const userAgent = navigatorLike?.userAgent ?? "";
|
|
21
|
+
const maxTouchPoints = navigatorLike?.maxTouchPoints ?? 0;
|
|
22
|
+
const isIPhone = /iPhone|iPod/i.test(userAgent);
|
|
23
|
+
const isIPad = /iPad/i.test(userAgent) || /Macintosh/i.test(userAgent) && maxTouchPoints > 1;
|
|
24
|
+
return {
|
|
25
|
+
userAgent,
|
|
26
|
+
isIOS: isIPhone || isIPad,
|
|
27
|
+
isIPhone,
|
|
28
|
+
isIPad,
|
|
29
|
+
isAndroid: /Android/i.test(userAgent),
|
|
30
|
+
isFirefox: /Firefox|FxiOS/i.test(userAgent),
|
|
31
|
+
isSamsung: /SamsungBrowser/i.test(userAgent),
|
|
32
|
+
// solo el iPhone trae su versión en el user agent; el iPad queda en null a propósito
|
|
33
|
+
iosMajor: isIPhone ? parseIOSMajor(userAgent) : null
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function resolveInstallVariant({ platform, canPromptNative, isInstalled }) {
|
|
37
|
+
if (isInstalled) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
if (canPromptNative) {
|
|
41
|
+
return INSTALL_VARIANT.native;
|
|
42
|
+
}
|
|
43
|
+
if (platform.isIOS) {
|
|
44
|
+
if (platform.iosMajor !== null && platform.iosMajor < IOS_LIQUID_GLASS_MAJOR) {
|
|
45
|
+
return INSTALL_VARIANT.iosClassic;
|
|
46
|
+
}
|
|
47
|
+
return INSTALL_VARIANT.iosModern;
|
|
48
|
+
}
|
|
49
|
+
if (platform.isAndroid && platform.isFirefox) {
|
|
50
|
+
return INSTALL_VARIANT.androidFirefox;
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
export {
|
|
55
|
+
INSTALL_VARIANT,
|
|
56
|
+
detectPlatform,
|
|
57
|
+
parseIOSMajor,
|
|
58
|
+
resolveInstallVariant
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=installInstructions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installInstructions.js","sources":["../../src/pwa/installInstructions.js"],"sourcesContent":["// Qué instrucciones de «instalar la app» le tocan a cada persona según su equipo. La lógica de walk-ot tal cual (ya\n// probada en iPhone y Android), sin React ni el DOM: recibe el navigator y devuelve datos, así se prueba en node.\n//\n// Por qué hay variantes y no un solo juego de pasos: agregar a la pantalla de inicio NO es igual en todos lados y cambia\n// con el tiempo.\n// - iOS 26 (el rediseño de Liquid Glass) escondió Compartir dentro del botón ⋯:\n// ⋯ → Compartir → Agregar a inicio → «Abrir como app web» prendido → Agregar\n// - iOS 16 a 18 tenían Compartir directo en la barra de abajo: Compartir → Agregar a inicio → Agregar\n// - Android con Chrome, Samsung Internet o Edge avisa con su propio diálogo (beforeinstallprompt): un botón, sin pasos.\n// - Firefox de Android nunca avisa: menú ⋮ → Instalar, a mano.\n// Cuando un navegador cambie su camino (un iOS 27), se agrega UNA variante y sus pasos en los textos, sin reescribir nada.\n//\n// Funciones puras, sin React: function (regla de la casa).\n\n// la versión de iOS que movió Compartir dentro del ⋯\nconst IOS_LIQUID_GLASS_MAJOR = 26;\n\n/**\n * Lo que se le enseña a la persona. `native`: el navegador tiene su propio diálogo de instalar (un botón). Sin manera\n * razonable de instalar (Android con Chromium antes de que avise, Safari o Firefox de escritorio) no hay variante (null)\n * y no se enseña nada.\n */\nexport const INSTALL_VARIANT = Object.freeze({\n native: 'native',\n // iPhone y iPad con iOS 26 o más nuevo\n iosModern: 'iosModern',\n // iPhone con iOS 16 a 18\n iosClassic: 'iosClassic',\n // Firefox de Android: no avisa, va a mano\n androidFirefox: 'androidFirefox',\n});\n\n/**\n * La versión mayor de iOS del user agent del iPhone («CPU iPhone OS 26_0 like Mac OS X» → 26). El iPad (iPadOS 13 en\n * adelante) se presenta como «Macintosh» y no trae versión.\n *\n * @param {string} [userAgent]\n * @returns {number|null} null si no se pudo leer\n */\nexport function parseIOSMajor(userAgent = '') {\n const fromOS = /OS (\\d+)_/.exec(userAgent);\n if (fromOS) {\n return Number(fromOS[1]);\n }\n // algunos user agents traen la versión como «Version/26.0»\n const fromVersion = /Version\\/(\\d+)/.exec(userAgent);\n return fromVersion ? Number(fromVersion[1]) : null;\n}\n\n/**\n * Describe el equipo a partir del navigator. Solo lee; no decide nada.\n *\n * @param {{userAgent?: string, maxTouchPoints?: number}} [navigatorLike] window.navigator o algo con su forma\n * @returns {{userAgent: string, isIOS: boolean, isIPhone: boolean, isIPad: boolean, isAndroid: boolean, isFirefox: boolean, isSamsung: boolean, iosMajor: number|null}}\n */\nexport function detectPlatform(navigatorLike) {\n const userAgent = navigatorLike?.userAgent ?? '';\n const maxTouchPoints = navigatorLike?.maxTouchPoints ?? 0;\n\n const isIPhone = /iPhone|iPod/i.test(userAgent);\n // OJO: el iPad con iPadOS 13 o más nuevo dice «Macintosh»; lo delata la pantalla táctil (una Mac reporta 0 toques).\n // /iPad/ cubre los iPad viejos.\n const isIPad = /iPad/i.test(userAgent) || (/Macintosh/i.test(userAgent) && maxTouchPoints > 1);\n return {\n userAgent,\n isIOS: isIPhone || isIPad,\n isIPhone,\n isIPad,\n isAndroid: /Android/i.test(userAgent),\n isFirefox: /Firefox|FxiOS/i.test(userAgent),\n isSamsung: /SamsungBrowser/i.test(userAgent),\n // solo el iPhone trae su versión en el user agent; el iPad queda en null a propósito\n iosMajor: isIPhone ? parseIOSMajor(userAgent) : null,\n };\n}\n\n/**\n * Qué enseñar.\n *\n * @param {object} options\n * @param {ReturnType<typeof detectPlatform>} options.platform\n * @param {boolean} options.canPromptNative el navegador ya avisó que se puede instalar (beforeinstallprompt)\n * @param {boolean} options.isInstalled ya se abrió como app instalada\n * @returns {string|null} una de INSTALL_VARIANT, o null si no hay nada que ofrecer\n */\nexport function resolveInstallVariant({platform, canPromptNative, isInstalled}) {\n // ya instalada: no se le vuelve a ofrecer\n if (isInstalled) {\n return null;\n }\n if (canPromptNative) {\n return INSTALL_VARIANT.native;\n }\n if (platform.isIOS) {\n // iPhone con versión conocida y anterior a la 26: el camino clásico. Con iOS 26 o más nuevo, iPad o sin versión,\n // el moderno: es el vigente, y en uno viejo el ⋯ no aparece pero los pasos se pueden seguir igual\n if (platform.iosMajor !== null && platform.iosMajor < IOS_LIQUID_GLASS_MAJOR) {\n return INSTALL_VARIANT.iosClassic;\n }\n return INSTALL_VARIANT.iosModern;\n }\n if (platform.isAndroid && platform.isFirefox) {\n return INSTALL_VARIANT.androidFirefox;\n }\n // Android con Chromium que todavía no avisa: esos navegadores SÍ avisan cuando la app ya se puede instalar; enseñar\n // pasos a mano mientras tanto sería molestar. El escritorio sin aviso del navegador, tampoco\n return null;\n}\n"],"names":[],"mappings":"AAeA,MAAM,yBAAyB;AAOnB,MAAC,kBAAkB,OAAO,OAAO;AAAA,EACzC,QAAQ;AAAA;AAAA,EAER,WAAW;AAAA;AAAA,EAEX,YAAY;AAAA;AAAA,EAEZ,gBAAgB;AACpB,CAAC;AASM,SAAS,cAAc,YAAY,IAAI;AAC1C,QAAM,SAAS,YAAY,KAAK,SAAS;AACzC,MAAI,QAAQ;AACR,WAAO,OAAO,OAAO,CAAC,CAAC;AAAA,EAC3B;AAEA,QAAM,cAAc,iBAAiB,KAAK,SAAS;AACnD,SAAO,cAAc,OAAO,YAAY,CAAC,CAAC,IAAI;AAClD;AAQO,SAAS,eAAe,eAAe;AAC1C,QAAM,YAAY,eAAe,aAAa;AAC9C,QAAM,iBAAiB,eAAe,kBAAkB;AAExD,QAAM,WAAW,eAAe,KAAK,SAAS;AAG9C,QAAM,SAAS,QAAQ,KAAK,SAAS,KAAM,aAAa,KAAK,SAAS,KAAK,iBAAiB;AAC5F,SAAO;AAAA,IACH;AAAA,IACA,OAAO,YAAY;AAAA,IACnB;AAAA,IACA;AAAA,IACA,WAAW,WAAW,KAAK,SAAS;AAAA,IACpC,WAAW,iBAAiB,KAAK,SAAS;AAAA,IAC1C,WAAW,kBAAkB,KAAK,SAAS;AAAA;AAAA,IAE3C,UAAU,WAAW,cAAc,SAAS,IAAI;AAAA,EACxD;AACA;AAWO,SAAS,sBAAsB,EAAC,UAAU,iBAAiB,YAAW,GAAG;AAE5E,MAAI,aAAa;AACb,WAAO;AAAA,EACX;AACA,MAAI,iBAAiB;AACjB,WAAO,gBAAgB;AAAA,EAC3B;AACA,MAAI,SAAS,OAAO;AAGhB,QAAI,SAAS,aAAa,QAAQ,SAAS,WAAW,wBAAwB;AAC1E,aAAO,gBAAgB;AAAA,IAC3B;AACA,WAAO,gBAAgB;AAAA,EAC3B;AACA,MAAI,SAAS,aAAa,SAAS,WAAW;AAC1C,WAAO,gBAAgB;AAAA,EAC3B;AAGA,SAAO;AACX;"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState, useEffect, useCallback, useMemo } from "react";
|
|
3
|
+
import { createLogger } from "../observability/logger.js";
|
|
4
|
+
import { detectPlatform, resolveInstallVariant } from "./installInstructions.js";
|
|
5
|
+
const log = createLogger("pwa");
|
|
6
|
+
const DISMISS_STORAGE_KEY = "calcita:installPromptDismissed";
|
|
7
|
+
const DISMISSED = "1";
|
|
8
|
+
function isRunningInstalled() {
|
|
9
|
+
return window.matchMedia?.("(display-mode: standalone)").matches === true || window.navigator.standalone === true;
|
|
10
|
+
}
|
|
11
|
+
function readDismissed() {
|
|
12
|
+
try {
|
|
13
|
+
return window.localStorage.getItem(DISMISS_STORAGE_KEY) === DISMISSED;
|
|
14
|
+
} catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function useInstallPrompt() {
|
|
19
|
+
const [deferredPrompt, setDeferredPrompt] = useState(null);
|
|
20
|
+
const [isInstalled, setIsInstalled] = useState(false);
|
|
21
|
+
const [platform, setPlatform] = useState(null);
|
|
22
|
+
const [dismissed, setDismissed] = useState(true);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
setPlatform(detectPlatform(window.navigator));
|
|
25
|
+
setIsInstalled(isRunningInstalled());
|
|
26
|
+
setDismissed(readDismissed());
|
|
27
|
+
const handleBeforeInstall = (event) => {
|
|
28
|
+
event.preventDefault();
|
|
29
|
+
setDeferredPrompt(event);
|
|
30
|
+
};
|
|
31
|
+
const handleInstalled = () => {
|
|
32
|
+
setIsInstalled(true);
|
|
33
|
+
setDeferredPrompt(null);
|
|
34
|
+
log.info("app instalada");
|
|
35
|
+
};
|
|
36
|
+
window.addEventListener("beforeinstallprompt", handleBeforeInstall);
|
|
37
|
+
window.addEventListener("appinstalled", handleInstalled);
|
|
38
|
+
return () => {
|
|
39
|
+
window.removeEventListener("beforeinstallprompt", handleBeforeInstall);
|
|
40
|
+
window.removeEventListener("appinstalled", handleInstalled);
|
|
41
|
+
};
|
|
42
|
+
}, []);
|
|
43
|
+
const promptInstall = useCallback(async () => {
|
|
44
|
+
if (!deferredPrompt) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
deferredPrompt.prompt();
|
|
48
|
+
const { outcome } = await deferredPrompt.userChoice;
|
|
49
|
+
log.info("respuesta al diálogo de instalar", { outcome });
|
|
50
|
+
setDeferredPrompt(null);
|
|
51
|
+
}, [deferredPrompt]);
|
|
52
|
+
const dismiss = useCallback(() => {
|
|
53
|
+
setDismissed(true);
|
|
54
|
+
try {
|
|
55
|
+
window.localStorage.setItem(DISMISS_STORAGE_KEY, DISMISSED);
|
|
56
|
+
} catch {
|
|
57
|
+
}
|
|
58
|
+
}, []);
|
|
59
|
+
const variant = useMemo(() => {
|
|
60
|
+
if (!platform) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
return resolveInstallVariant({ platform, canPromptNative: deferredPrompt !== null, isInstalled });
|
|
64
|
+
}, [platform, deferredPrompt, isInstalled]);
|
|
65
|
+
return { variant, isInstalled, dismissed, dismiss, promptInstall };
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
useInstallPrompt
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=useInstallPrompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInstallPrompt.js","sources":["../../src/pwa/useInstallPrompt.js"],"sourcesContent":["// La invitación a instalar la app (agregar a la pantalla de inicio): escucha al navegador, decide qué variante enseñar\n// (installInstructions.js) y recuerda el «Ahora no». Es el de walk-ot, ya probado en iPhone y Android.\n//\n// El navegador NO tiene una sola manera de instalar:\n// - Android con Chromium (Chrome, Samsung Internet, Edge) avisa con beforeinstallprompt. Se guarda el aviso (preventDefault\n// quita su barrita) y se lanza desde NUESTRO botón.\n// - Safari de iOS nunca avisa: se instala a mano y el camino cambió en iOS 26.\n// - Firefox de Android tampoco avisa: a mano.\n//\n// El «Ahora no» se guarda en este navegador. Mientras no se lee (en el servidor y en el primer pintado) se supone que ya\n// lo dijo: así la invitación nunca parpadea al cargar ni cambia entre el servidor y el navegador.\n//\n// Es un gancho: function, como los demás del paquete.\nimport {useCallback, useEffect, useMemo, useState} from 'react';\n\nimport {createLogger} from '@/observability/logger.js';\nimport {detectPlatform, resolveInstallVariant} from '@/pwa/installInstructions.js';\n\nconst log = createLogger('pwa');\n\nconst DISMISS_STORAGE_KEY = 'calcita:installPromptDismissed';\nconst DISMISSED = '1';\n\n/** ¿Ya se abrió como app instalada? En el iPhone lo dice navigator.standalone; en los demás, el display-mode. */\nfunction isRunningInstalled() {\n return window.matchMedia?.('(display-mode: standalone)').matches === true || window.navigator.standalone === true;\n}\n\n/** El «Ahora no» guardado; con el almacenamiento bloqueado se toma como no dicho. */\nfunction readDismissed() {\n try {\n return window.localStorage.getItem(DISMISS_STORAGE_KEY) === DISMISSED;\n } catch {\n return false;\n }\n}\n\n/**\n * @returns {{variant: string|null, isInstalled: boolean, dismissed: boolean, dismiss: () => void, promptInstall: () => Promise<void>}}\n * variant: una de INSTALL_VARIANT o null (nada que ofrecer). NO toma en cuenta el «Ahora no»: la invitación sí lo respeta,\n * pero la entrada del menú de la cuenta no, porque ahí la persona la busca a propósito.\n */\nexport function useInstallPrompt() {\n const [deferredPrompt, setDeferredPrompt] = useState(null);\n const [isInstalled, setIsInstalled] = useState(false);\n const [platform, setPlatform] = useState(null);\n // se supone dicho hasta leer el navegador (ver arriba)\n const [dismissed, setDismissed] = useState(true);\n\n useEffect(() => {\n setPlatform(detectPlatform(window.navigator));\n setIsInstalled(isRunningInstalled());\n setDismissed(readDismissed());\n\n const handleBeforeInstall = (event) => {\n // el momento lo elige la persona con nuestro botón, no la barrita del navegador\n event.preventDefault();\n setDeferredPrompt(event);\n };\n const handleInstalled = () => {\n setIsInstalled(true);\n setDeferredPrompt(null);\n log.info('app instalada');\n };\n window.addEventListener('beforeinstallprompt', handleBeforeInstall);\n window.addEventListener('appinstalled', handleInstalled);\n return () => {\n window.removeEventListener('beforeinstallprompt', handleBeforeInstall);\n window.removeEventListener('appinstalled', handleInstalled);\n };\n }, []);\n\n // El diálogo del navegador sirve UNA vez: con cualquier respuesta se suelta. Cancelarlo no es «Ahora no» (eso solo lo\n // dice el botón de la invitación).\n const promptInstall = useCallback(async () => {\n if (!deferredPrompt) {\n return;\n }\n deferredPrompt.prompt();\n const {outcome} = await deferredPrompt.userChoice;\n log.info('respuesta al diálogo de instalar', {outcome});\n setDeferredPrompt(null);\n }, [deferredPrompt]);\n\n const dismiss = useCallback(() => {\n setDismissed(true);\n try {\n window.localStorage.setItem(DISMISS_STORAGE_KEY, DISMISSED);\n } catch {\n // almacenamiento bloqueado: se cierra igual, solo no se recuerda\n }\n }, []);\n\n const variant = useMemo(() => {\n if (!platform) {\n return null;\n }\n return resolveInstallVariant({platform, canPromptNative: deferredPrompt !== null, isInstalled});\n }, [platform, deferredPrompt, isInstalled]);\n\n return {variant, isInstalled, dismissed, dismiss, promptInstall};\n}\n"],"names":[],"mappings":";;;;AAkBA,MAAM,MAAM,aAAa,KAAK;AAE9B,MAAM,sBAAsB;AAC5B,MAAM,YAAY;AAGlB,SAAS,qBAAqB;AAC1B,SAAO,OAAO,aAAa,4BAA4B,EAAE,YAAY,QAAQ,OAAO,UAAU,eAAe;AACjH;AAGA,SAAS,gBAAgB;AACrB,MAAI;AACA,WAAO,OAAO,aAAa,QAAQ,mBAAmB,MAAM;AAAA,EAChE,QAAQ;AACJ,WAAO;AAAA,EACX;AACJ;AAOO,SAAS,mBAAmB;AAC/B,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,IAAI;AACzD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,IAAI;AAE7C,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,IAAI;AAE/C,YAAU,MAAM;AACZ,gBAAY,eAAe,OAAO,SAAS,CAAC;AAC5C,mBAAe,mBAAkB,CAAE;AACnC,iBAAa,cAAa,CAAE;AAE5B,UAAM,sBAAsB,CAAC,UAAU;AAEnC,YAAM,eAAc;AACpB,wBAAkB,KAAK;AAAA,IAC3B;AACA,UAAM,kBAAkB,MAAM;AAC1B,qBAAe,IAAI;AACnB,wBAAkB,IAAI;AACtB,UAAI,KAAK,eAAe;AAAA,IAC5B;AACA,WAAO,iBAAiB,uBAAuB,mBAAmB;AAClE,WAAO,iBAAiB,gBAAgB,eAAe;AACvD,WAAO,MAAM;AACT,aAAO,oBAAoB,uBAAuB,mBAAmB;AACrE,aAAO,oBAAoB,gBAAgB,eAAe;AAAA,IAC9D;AAAA,EACJ,GAAG,CAAA,CAAE;AAIL,QAAM,gBAAgB,YAAY,YAAY;AAC1C,QAAI,CAAC,gBAAgB;AACjB;AAAA,IACJ;AACA,mBAAe,OAAM;AACrB,UAAM,EAAC,QAAO,IAAI,MAAM,eAAe;AACvC,QAAI,KAAK,oCAAoC,EAAC,QAAO,CAAC;AACtD,sBAAkB,IAAI;AAAA,EAC1B,GAAG,CAAC,cAAc,CAAC;AAEnB,QAAM,UAAU,YAAY,MAAM;AAC9B,iBAAa,IAAI;AACjB,QAAI;AACA,aAAO,aAAa,QAAQ,qBAAqB,SAAS;AAAA,IAC9D,QAAQ;AAAA,IAER;AAAA,EACJ,GAAG,CAAA,CAAE;AAEL,QAAM,UAAU,QAAQ,MAAM;AAC1B,QAAI,CAAC,UAAU;AACX,aAAO;AAAA,IACX;AACA,WAAO,sBAAsB,EAAC,UAAU,iBAAiB,mBAAmB,MAAM,YAAW,CAAC;AAAA,EAClG,GAAG,CAAC,UAAU,gBAAgB,WAAW,CAAC;AAE1C,SAAO,EAAC,SAAS,aAAa,WAAW,SAAS,cAAa;AACnE;"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Controller, FormProvider, useForm, useFormContext } from "react-hook-form";
|
|
3
|
+
import { yupResolver } from "@hookform/resolvers/yup";
|
|
4
|
+
import { default as default2 } from "./hookForm/FormCatalogField.js";
|
|
5
|
+
import { default as default3 } from "./hookForm/FormColorField.js";
|
|
6
|
+
import { default as default4 } from "./hookForm/FormNumberField.js";
|
|
7
|
+
import { default as default5 } from "./hookForm/FormProblemAlert.js";
|
|
8
|
+
import { default as default6 } from "./hookForm/FormSelectField.js";
|
|
9
|
+
import { default as default7 } from "./hookForm/FormTextField.js";
|
|
10
|
+
import { default as default8 } from "./hookForm/SubmitButton.js";
|
|
11
|
+
import { SERVER_PROBLEM_ROOT, applyServerProblem } from "./hookForm/applyServerProblem.js";
|
|
12
|
+
import { useHookFormField } from "./hookForm/useHookFormField.js";
|
|
13
|
+
export {
|
|
14
|
+
Controller,
|
|
15
|
+
default2 as FormCatalogField,
|
|
16
|
+
default3 as FormColorField,
|
|
17
|
+
default4 as FormNumberField,
|
|
18
|
+
default5 as FormProblemAlert,
|
|
19
|
+
FormProvider,
|
|
20
|
+
default6 as FormSelectField,
|
|
21
|
+
default7 as FormTextField,
|
|
22
|
+
SERVER_PROBLEM_ROOT,
|
|
23
|
+
default8 as SubmitButton,
|
|
24
|
+
applyServerProblem,
|
|
25
|
+
useForm,
|
|
26
|
+
useFormContext,
|
|
27
|
+
useHookFormField,
|
|
28
|
+
yupResolver
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=react-hook-form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-hook-form.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { reactRouterNavigation } from "./adapters/reactRouter.js";
|
|
2
|
+
import { RouteErrorScreen, useIsNavigating, withAccess, withChunkRecovery } from "./adapters/reactRouterRoutes.js";
|
|
3
|
+
export {
|
|
4
|
+
RouteErrorScreen,
|
|
5
|
+
reactRouterNavigation,
|
|
6
|
+
useIsNavigating,
|
|
7
|
+
withAccess,
|
|
8
|
+
withChunkRecovery
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=react-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-router.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import Alert from "@mui/material/Alert";
|
|
4
|
+
import List from "@mui/material/List";
|
|
5
|
+
import ListItem from "@mui/material/ListItem";
|
|
6
|
+
import ListItemIcon from "@mui/material/ListItemIcon";
|
|
7
|
+
import ListItemText from "@mui/material/ListItemText";
|
|
8
|
+
import Skeleton from "@mui/material/Skeleton";
|
|
9
|
+
import Stack from "@mui/material/Stack";
|
|
10
|
+
import Typography from "@mui/material/Typography";
|
|
11
|
+
import CancelOutlinedIcon from "@mui/icons-material/CancelOutlined";
|
|
12
|
+
import EventNoteOutlinedIcon from "@mui/icons-material/EventNoteOutlined";
|
|
13
|
+
import FingerprintOutlinedIcon from "@mui/icons-material/FingerprintOutlined";
|
|
14
|
+
import KeyOutlinedIcon from "@mui/icons-material/KeyOutlined";
|
|
15
|
+
import LoginOutlinedIcon from "@mui/icons-material/LoginOutlined";
|
|
16
|
+
import LogoutOutlinedIcon from "@mui/icons-material/LogoutOutlined";
|
|
17
|
+
import PasswordOutlinedIcon from "@mui/icons-material/PasswordOutlined";
|
|
18
|
+
import PhonelinkLockOutlinedIcon from "@mui/icons-material/PhonelinkLockOutlined";
|
|
19
|
+
import PhonelinkEraseOutlinedIcon from "@mui/icons-material/PhonelinkEraseOutlined";
|
|
20
|
+
import SyncLockOutlinedIcon from "@mui/icons-material/SyncLockOutlined";
|
|
21
|
+
import { formatDateTime } from "../formatting.js";
|
|
22
|
+
import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
|
|
23
|
+
import SectionCard from "../ui/layout/SectionCard.js";
|
|
24
|
+
const ACCOUNT_EVENT_KIND = Object.freeze({
|
|
25
|
+
signedIn: "signedIn",
|
|
26
|
+
signInFailed: "signInFailed",
|
|
27
|
+
signedOut: "signedOut",
|
|
28
|
+
passwordChanged: "passwordChanged",
|
|
29
|
+
twoStepEnabled: "twoStepEnabled",
|
|
30
|
+
twoStepDisabled: "twoStepDisabled",
|
|
31
|
+
passkeyAdded: "passkeyAdded",
|
|
32
|
+
passkeyRemoved: "passkeyRemoved",
|
|
33
|
+
recoveryCodesGenerated: "recoveryCodesGenerated",
|
|
34
|
+
recoveryCodeUsed: "recoveryCodeUsed",
|
|
35
|
+
sessionsClosed: "sessionsClosed"
|
|
36
|
+
});
|
|
37
|
+
const EVENT_LOOK = Object.freeze({
|
|
38
|
+
[ACCOUNT_EVENT_KIND.signedIn]: { Icon: LoginOutlinedIcon },
|
|
39
|
+
[ACCOUNT_EVENT_KIND.signInFailed]: { Icon: CancelOutlinedIcon, color: "error" },
|
|
40
|
+
[ACCOUNT_EVENT_KIND.signedOut]: { Icon: LogoutOutlinedIcon },
|
|
41
|
+
[ACCOUNT_EVENT_KIND.passwordChanged]: { Icon: PasswordOutlinedIcon },
|
|
42
|
+
[ACCOUNT_EVENT_KIND.twoStepEnabled]: { Icon: PhonelinkLockOutlinedIcon, color: "success" },
|
|
43
|
+
[ACCOUNT_EVENT_KIND.twoStepDisabled]: { Icon: PhonelinkEraseOutlinedIcon, color: "warning" },
|
|
44
|
+
[ACCOUNT_EVENT_KIND.passkeyAdded]: { Icon: FingerprintOutlinedIcon, color: "success" },
|
|
45
|
+
[ACCOUNT_EVENT_KIND.passkeyRemoved]: { Icon: FingerprintOutlinedIcon, color: "warning" },
|
|
46
|
+
[ACCOUNT_EVENT_KIND.recoveryCodesGenerated]: { Icon: KeyOutlinedIcon },
|
|
47
|
+
[ACCOUNT_EVENT_KIND.recoveryCodeUsed]: { Icon: KeyOutlinedIcon, color: "warning" },
|
|
48
|
+
[ACCOUNT_EVENT_KIND.sessionsClosed]: { Icon: SyncLockOutlinedIcon }
|
|
49
|
+
});
|
|
50
|
+
const DEFAULT_LOOK = Object.freeze({ Icon: EventNoteOutlinedIcon });
|
|
51
|
+
const LOADING_HEIGHT_PIXELS = 160;
|
|
52
|
+
function ActivityLog({ events, error = null }) {
|
|
53
|
+
const { t } = useToolkitTranslation("security");
|
|
54
|
+
return /* @__PURE__ */ jsx(SectionCard, { title: t("activity.title"), children: /* @__PURE__ */ jsxs(Stack, { spacing: 2, children: [
|
|
55
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: t("activity.description") }),
|
|
56
|
+
error && /* @__PURE__ */ jsx(Alert, { severity: "error", children: error }),
|
|
57
|
+
!events && !error && /* @__PURE__ */ jsx(Skeleton, { variant: "rounded", height: LOADING_HEIGHT_PIXELS }),
|
|
58
|
+
events?.length === 0 && /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: t("activity.empty") }),
|
|
59
|
+
events?.length > 0 && /* @__PURE__ */ jsx(List, { dense: true, disablePadding: true, children: events.map((event) => {
|
|
60
|
+
const look = EVENT_LOOK[event.kind] ?? DEFAULT_LOOK;
|
|
61
|
+
const where = event.device && event.network ? ` · ${t("activity.from", { device: event.device, network: event.network })}` : "";
|
|
62
|
+
return /* @__PURE__ */ jsxs(ListItem, { disableGutters: true, children: [
|
|
63
|
+
/* @__PURE__ */ jsx(ListItemIcon, { sx: { minWidth: 36 }, children: /* @__PURE__ */ jsx(look.Icon, { fontSize: "small", color: look.color ?? "action" }) }),
|
|
64
|
+
/* @__PURE__ */ jsx(
|
|
65
|
+
ListItemText,
|
|
66
|
+
{
|
|
67
|
+
primary: event.description ?? t(`activity.kinds.${event.kind}`),
|
|
68
|
+
secondary: `${formatDateTime(event.occurredAt)}${where}`
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
] }, event.id);
|
|
72
|
+
}) })
|
|
73
|
+
] }) });
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
ACCOUNT_EVENT_KIND,
|
|
77
|
+
ActivityLog as default
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=ActivityLog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ActivityLog.js","sources":["../../src/security/ActivityLog.jsx"],"sourcesContent":["// La bitácora de la cuenta: lo último que pasó (entró, contraseña equivocada, cambió su contraseña, activó la verificación,\n// agregó una llave…), con la hora, el equipo y la red a medias. Para que la persona reconozca lo que no fue ella.\n//\n// Cada evento llega con su tipo (kind) y el texto sale de los textos del paquete (security:activity.kinds.<kind>); un tipo\n// propio del proyecto trae su texto en description.\n//\n// <ActivityLog events={events} />\n//\n// Genérico del paquete: function (regla de la casa).\nimport Alert from '@mui/material/Alert';\nimport List from '@mui/material/List';\nimport ListItem from '@mui/material/ListItem';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport Skeleton from '@mui/material/Skeleton';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport CancelOutlinedIcon from '@mui/icons-material/CancelOutlined';\nimport EventNoteOutlinedIcon from '@mui/icons-material/EventNoteOutlined';\nimport FingerprintOutlinedIcon from '@mui/icons-material/FingerprintOutlined';\nimport KeyOutlinedIcon from '@mui/icons-material/KeyOutlined';\nimport LoginOutlinedIcon from '@mui/icons-material/LoginOutlined';\nimport LogoutOutlinedIcon from '@mui/icons-material/LogoutOutlined';\nimport PasswordOutlinedIcon from '@mui/icons-material/PasswordOutlined';\nimport PhonelinkLockOutlinedIcon from '@mui/icons-material/PhonelinkLockOutlined';\nimport PhonelinkEraseOutlinedIcon from '@mui/icons-material/PhonelinkEraseOutlined';\nimport SyncLockOutlinedIcon from '@mui/icons-material/SyncLockOutlined';\n\nimport {formatDateTime} from '@/formatting.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport SectionCard from '@/ui/layout/SectionCard.jsx';\n\n/** Los tipos de evento que el paquete conoce, con su texto en security:activity.kinds. */\nexport const ACCOUNT_EVENT_KIND = Object.freeze({\n signedIn: 'signedIn',\n signInFailed: 'signInFailed',\n signedOut: 'signedOut',\n passwordChanged: 'passwordChanged',\n twoStepEnabled: 'twoStepEnabled',\n twoStepDisabled: 'twoStepDisabled',\n passkeyAdded: 'passkeyAdded',\n passkeyRemoved: 'passkeyRemoved',\n recoveryCodesGenerated: 'recoveryCodesGenerated',\n recoveryCodeUsed: 'recoveryCodeUsed',\n sessionsClosed: 'sessionsClosed',\n});\n\n// el ícono de cada tipo, y en rojo lo que pide atención (un intento con contraseña equivocada, quitar protección)\nconst EVENT_LOOK = Object.freeze({\n [ACCOUNT_EVENT_KIND.signedIn]: {Icon: LoginOutlinedIcon},\n [ACCOUNT_EVENT_KIND.signInFailed]: {Icon: CancelOutlinedIcon, color: 'error'},\n [ACCOUNT_EVENT_KIND.signedOut]: {Icon: LogoutOutlinedIcon},\n [ACCOUNT_EVENT_KIND.passwordChanged]: {Icon: PasswordOutlinedIcon},\n [ACCOUNT_EVENT_KIND.twoStepEnabled]: {Icon: PhonelinkLockOutlinedIcon, color: 'success'},\n [ACCOUNT_EVENT_KIND.twoStepDisabled]: {Icon: PhonelinkEraseOutlinedIcon, color: 'warning'},\n [ACCOUNT_EVENT_KIND.passkeyAdded]: {Icon: FingerprintOutlinedIcon, color: 'success'},\n [ACCOUNT_EVENT_KIND.passkeyRemoved]: {Icon: FingerprintOutlinedIcon, color: 'warning'},\n [ACCOUNT_EVENT_KIND.recoveryCodesGenerated]: {Icon: KeyOutlinedIcon},\n [ACCOUNT_EVENT_KIND.recoveryCodeUsed]: {Icon: KeyOutlinedIcon, color: 'warning'},\n [ACCOUNT_EVENT_KIND.sessionsClosed]: {Icon: SyncLockOutlinedIcon},\n});\nconst DEFAULT_LOOK = Object.freeze({Icon: EventNoteOutlinedIcon});\nconst LOADING_HEIGHT_PIXELS = 160;\n\n/**\n * @param {object} props\n * @param {Array<{id: string, kind: string, occurredAt: string, device?: string|null, network?: string|null, description?: string}>|null} props.events\n * del más nuevo al más viejo; null mientras llegan\n * @param {string|null} [props.error] ya traducido si no se pudieron traer\n */\nexport default function ActivityLog({events, error = null}) {\n const {t} = useToolkitTranslation('security');\n\n return (\n <SectionCard title={t('activity.title')}>\n <Stack spacing={2}>\n <Typography variant=\"body2\" color=\"text.secondary\">{t('activity.description')}</Typography>\n {error && <Alert severity=\"error\">{error}</Alert>}\n {!events && !error && <Skeleton variant=\"rounded\" height={LOADING_HEIGHT_PIXELS} />}\n {events?.length === 0 && <Typography variant=\"body2\" color=\"text.secondary\">{t('activity.empty')}</Typography>}\n {events?.length > 0 && (\n <List dense disablePadding>\n {events.map((event) => {\n const look = EVENT_LOOK[event.kind] ?? DEFAULT_LOOK;\n const where = event.device && event.network ? ` · ${t('activity.from', {device: event.device, network: event.network})}` : '';\n return (\n <ListItem key={event.id} disableGutters>\n <ListItemIcon sx={{minWidth: 36}}><look.Icon fontSize=\"small\" color={look.color ?? 'action'} /></ListItemIcon>\n <ListItemText primary={event.description ?? t(`activity.kinds.${event.kind}`)}\n secondary={`${formatDateTime(event.occurredAt)}${where}`} />\n </ListItem>\n );\n })}\n </List>\n )}\n </Stack>\n </SectionCard>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import Alert from "@mui/material/Alert";
|
|
5
|
+
import Box from "@mui/material/Box";
|
|
6
|
+
import Button from "@mui/material/Button";
|
|
7
|
+
import Checkbox from "@mui/material/Checkbox";
|
|
8
|
+
import Dialog from "@mui/material/Dialog";
|
|
9
|
+
import DialogActions from "@mui/material/DialogActions";
|
|
10
|
+
import DialogContent from "@mui/material/DialogContent";
|
|
11
|
+
import DialogTitle from "@mui/material/DialogTitle";
|
|
12
|
+
import FormControlLabel from "@mui/material/FormControlLabel";
|
|
13
|
+
import Stack from "@mui/material/Stack";
|
|
14
|
+
import DownloadIcon from "@mui/icons-material/Download";
|
|
15
|
+
import { saveBlob } from "../files.js";
|
|
16
|
+
import { useToolkitSettings } from "../toolkit/toolkitContext.js";
|
|
17
|
+
import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
|
|
18
|
+
import CopyButton from "../ui/actions/CopyButton.js";
|
|
19
|
+
const CODE_FONT = "ui-monospace, SFMono-Regular, Menlo, monospace";
|
|
20
|
+
function todayText() {
|
|
21
|
+
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
22
|
+
}
|
|
23
|
+
function RecoveryCodesDialog({ codes, account = "", onClose }) {
|
|
24
|
+
const { t } = useToolkitTranslation("security");
|
|
25
|
+
const { appName } = useToolkitSettings();
|
|
26
|
+
const [isSaved, setIsSaved] = useState(false);
|
|
27
|
+
const isOpen = Boolean(codes?.length);
|
|
28
|
+
const download = () => {
|
|
29
|
+
const date = todayText();
|
|
30
|
+
const lines = [
|
|
31
|
+
t("recoveryCodes.fileTitle", { appName }),
|
|
32
|
+
t("recoveryCodes.fileAccount", { account }),
|
|
33
|
+
t("recoveryCodes.fileGenerated", { date }),
|
|
34
|
+
"",
|
|
35
|
+
t("recoveryCodes.fileHowTo"),
|
|
36
|
+
t("recoveryCodes.fileKeepSafe"),
|
|
37
|
+
"",
|
|
38
|
+
...codes,
|
|
39
|
+
""
|
|
40
|
+
];
|
|
41
|
+
saveBlob(new Blob([lines.join("\n")], { type: "text/plain;charset=utf-8" }), t("recoveryCodes.fileName", { date }));
|
|
42
|
+
};
|
|
43
|
+
const close = () => {
|
|
44
|
+
setIsSaved(false);
|
|
45
|
+
onClose();
|
|
46
|
+
};
|
|
47
|
+
return (
|
|
48
|
+
// ni Esc ni un clic afuera lo cierran: solo «Listo», después de marcar que los guardó
|
|
49
|
+
/* @__PURE__ */ jsxs(Dialog, { open: isOpen, maxWidth: "xs", fullWidth: true, disableEscapeKeyDown: true, onClose: () => {
|
|
50
|
+
}, children: [
|
|
51
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: t("recoveryCodes.title") }),
|
|
52
|
+
/* @__PURE__ */ jsx(DialogContent, { children: /* @__PURE__ */ jsxs(Stack, { spacing: 2, children: [
|
|
53
|
+
/* @__PURE__ */ jsx(Alert, { severity: "warning", children: t("recoveryCodes.warning") }),
|
|
54
|
+
/* @__PURE__ */ jsx(Box, { component: "ol", sx: {
|
|
55
|
+
m: 0,
|
|
56
|
+
p: 2,
|
|
57
|
+
pl: 5,
|
|
58
|
+
borderRadius: 2,
|
|
59
|
+
bgcolor: "action.hover",
|
|
60
|
+
fontFamily: CODE_FONT,
|
|
61
|
+
fontSize: 15,
|
|
62
|
+
columns: 2,
|
|
63
|
+
columnGap: 4
|
|
64
|
+
}, children: (codes ?? []).map((code) => /* @__PURE__ */ jsx("li", { children: code }, code)) }),
|
|
65
|
+
/* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, sx: { alignItems: "center" }, children: [
|
|
66
|
+
/* @__PURE__ */ jsx(CopyButton, { value: (codes ?? []).join("\n"), label: t("recoveryCodes.copyAll") }),
|
|
67
|
+
/* @__PURE__ */ jsx(Button, { size: "small", startIcon: /* @__PURE__ */ jsx(DownloadIcon, {}), onClick: download, children: t("recoveryCodes.download") })
|
|
68
|
+
] }),
|
|
69
|
+
/* @__PURE__ */ jsx(
|
|
70
|
+
FormControlLabel,
|
|
71
|
+
{
|
|
72
|
+
control: /* @__PURE__ */ jsx(Checkbox, { checked: isSaved, onChange: (event) => setIsSaved(event.target.checked) }),
|
|
73
|
+
label: t("recoveryCodes.saved")
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
] }) }),
|
|
77
|
+
/* @__PURE__ */ jsx(DialogActions, { children: /* @__PURE__ */ jsx(Button, { variant: "contained", disabled: !isSaved, onClick: close, children: t("recoveryCodes.done") }) })
|
|
78
|
+
] })
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
export {
|
|
82
|
+
RecoveryCodesDialog as default
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=RecoveryCodesDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecoveryCodesDialog.js","sources":["../../src/security/RecoveryCodesDialog.jsx"],"sourcesContent":["// Los códigos de recuperación, que se enseñan UNA sola vez (el servidor solo guarda su huella, no los códigos).\n//\n// No se puede cerrar sin marcar «Ya los guardé»: es la única salida que tiene la persona el día que pierda su teléfono,\n// y un aviso que se cierra con Esc o con un clic afuera se cierra sin leer. Se pueden copiar todos o bajar en un .txt con\n// el nombre de la app, la cuenta y la fecha.\n//\n// <RecoveryCodesDialog codes={codes} account={session.email} onClose={() => setCodes(null)} />\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Alert from '@mui/material/Alert';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Checkbox from '@mui/material/Checkbox';\nimport Dialog from '@mui/material/Dialog';\nimport DialogActions from '@mui/material/DialogActions';\nimport DialogContent from '@mui/material/DialogContent';\nimport DialogTitle from '@mui/material/DialogTitle';\nimport FormControlLabel from '@mui/material/FormControlLabel';\nimport Stack from '@mui/material/Stack';\nimport DownloadIcon from '@mui/icons-material/Download';\n\nimport {saveBlob} from '@/files.js';\nimport {useToolkitSettings} from '@/toolkit/toolkitContext.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport CopyButton from '@/ui/actions/CopyButton.jsx';\n\nconst CODE_FONT = 'ui-monospace, SFMono-Regular, Menlo, monospace';\n\n/**\n * La fecha de hoy como AAAA-MM-DD, para el nombre y el encabezado del archivo.\n *\n * @returns {string}\n */\nfunction todayText() {\n return new Date().toISOString().slice(0, 10);\n}\n\n/**\n * @param {object} props\n * @param {string[]|null} props.codes los códigos recién generados; sin códigos el diálogo está cerrado\n * @param {string} [props.account] la cuenta (normalmente el correo), para el archivo\n * @param {() => void} props.onClose solo se llama después de «Ya los guardé»\n */\nexport default function RecoveryCodesDialog({codes, account = '', onClose}) {\n const {t} = useToolkitTranslation('security');\n const {appName} = useToolkitSettings();\n const [isSaved, setIsSaved] = useState(false);\n const isOpen = Boolean(codes?.length);\n\n const download = () => {\n const date = todayText();\n const lines = [\n t('recoveryCodes.fileTitle', {appName}),\n t('recoveryCodes.fileAccount', {account}),\n t('recoveryCodes.fileGenerated', {date}),\n '',\n t('recoveryCodes.fileHowTo'),\n t('recoveryCodes.fileKeepSafe'),\n '',\n ...codes,\n '',\n ];\n saveBlob(new Blob([lines.join('\\n')], {type: 'text/plain;charset=utf-8'}), t('recoveryCodes.fileName', {date}));\n };\n\n const close = () => {\n setIsSaved(false);\n onClose();\n };\n\n return (\n // ni Esc ni un clic afuera lo cierran: solo «Listo», después de marcar que los guardó\n <Dialog open={isOpen} maxWidth=\"xs\" fullWidth disableEscapeKeyDown onClose={() => {}}>\n <DialogTitle>{t('recoveryCodes.title')}</DialogTitle>\n <DialogContent>\n <Stack spacing={2}>\n <Alert severity=\"warning\">{t('recoveryCodes.warning')}</Alert>\n <Box component=\"ol\" sx={{\n m: 0, p: 2, pl: 5, borderRadius: 2, bgcolor: 'action.hover', fontFamily: CODE_FONT, fontSize: 15,\n columns: 2, columnGap: 4,\n }}>\n {(codes ?? []).map((code) => <li key={code}>{code}</li>)}\n </Box>\n <Stack direction=\"row\" spacing={1} sx={{alignItems: 'center'}}>\n <CopyButton value={(codes ?? []).join('\\n')} label={t('recoveryCodes.copyAll')} />\n <Button size=\"small\" startIcon={<DownloadIcon />} onClick={download}>{t('recoveryCodes.download')}</Button>\n </Stack>\n <FormControlLabel control={<Checkbox checked={isSaved} onChange={(event) => setIsSaved(event.target.checked)} />}\n label={t('recoveryCodes.saved')} />\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button variant=\"contained\" disabled={!isSaved} onClick={close}>{t('recoveryCodes.done')}</Button>\n </DialogActions>\n </Dialog>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AA2BA,MAAM,YAAY;AAOlB,SAAS,YAAY;AACjB,8BAAW,QAAO,cAAc,MAAM,GAAG,EAAE;AAC/C;AAQA,SAAwB,oBAAoB,EAAC,OAAO,UAAU,IAAI,WAAU;AACxE,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU;AAC5C,QAAM,EAAC,QAAA,IAAW,mBAAA;AAClB,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,SAAS,QAAQ,OAAO,MAAM;AAEpC,QAAM,WAAW,MAAM;AACnB,UAAM,OAAO,UAAA;AACb,UAAM,QAAQ;AAAA,MACV,EAAE,2BAA2B,EAAC,SAAQ;AAAA,MACtC,EAAE,6BAA6B,EAAC,SAAQ;AAAA,MACxC,EAAE,+BAA+B,EAAC,MAAK;AAAA,MACvC;AAAA,MACA,EAAE,yBAAyB;AAAA,MAC3B,EAAE,4BAA4B;AAAA,MAC9B;AAAA,MACA,GAAG;AAAA,MACH;AAAA,IAAA;AAEJ,aAAS,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,GAAG,EAAC,MAAM,2BAAA,CAA2B,GAAG,EAAE,0BAA0B,EAAC,KAAA,CAAK,CAAC;AAAA,EAClH;AAEA,QAAM,QAAQ,MAAM;AAChB,eAAW,KAAK;AAChB,YAAA;AAAA,EACJ;AAEA;AAAA;AAAA,IAEI,qBAAC,QAAA,EAAO,MAAM,QAAQ,UAAS,MAAK,WAAS,MAAC,sBAAoB,MAAC,SAAS,MAAM;AAAA,IAAC,GAC/E,UAAA;AAAA,MAAA,oBAAC,aAAA,EAAa,UAAA,EAAE,qBAAqB,EAAA,CAAE;AAAA,MACvC,oBAAC,eAAA,EACG,UAAA,qBAAC,OAAA,EAAM,SAAS,GACZ,UAAA;AAAA,QAAA,oBAAC,OAAA,EAAM,UAAS,WAAW,UAAA,EAAE,uBAAuB,GAAE;AAAA,QACtD,oBAAC,KAAA,EAAI,WAAU,MAAK,IAAI;AAAA,UACpB,GAAG;AAAA,UAAG,GAAG;AAAA,UAAG,IAAI;AAAA,UAAG,cAAc;AAAA,UAAG,SAAS;AAAA,UAAgB,YAAY;AAAA,UAAW,UAAU;AAAA,UAC9F,SAAS;AAAA,UAAG,WAAW;AAAA,QAAA,GAErB,WAAA,SAAS,CAAA,GAAI,IAAI,CAAC,SAAS,oBAAC,MAAA,EAAe,UAAA,KAAA,GAAP,IAAY,CAAK,EAAA,CAC3D;AAAA,QACA,qBAAC,OAAA,EAAM,WAAU,OAAM,SAAS,GAAG,IAAI,EAAC,YAAY,SAAA,GAChD,UAAA;AAAA,UAAA,oBAAC,YAAA,EAAW,QAAQ,SAAS,CAAA,GAAI,KAAK,IAAI,GAAG,OAAO,EAAE,uBAAuB,EAAA,CAAG;AAAA,UAChF,oBAAC,QAAA,EAAO,MAAK,SAAQ,WAAW,oBAAC,cAAA,CAAA,CAAa,GAAI,SAAS,UAAW,UAAA,EAAE,wBAAwB,EAAA,CAAE;AAAA,QAAA,GACtG;AAAA,QACA;AAAA,UAAC;AAAA,UAAA;AAAA,YAAiB,SAAS,oBAAC,UAAA,EAAS,SAAS,SAAS,UAAU,CAAC,UAAU,WAAW,MAAM,OAAO,OAAO,EAAA,CAAG;AAAA,YAC5F,OAAO,EAAE,qBAAqB;AAAA,UAAA;AAAA,QAAA;AAAA,MAAG,EAAA,CACvD,EAAA,CACJ;AAAA,MACA,oBAAC,eAAA,EACG,UAAA,oBAAC,QAAA,EAAO,SAAQ,aAAY,UAAU,CAAC,SAAS,SAAS,OAAQ,UAAA,EAAE,oBAAoB,GAAE,EAAA,CAC7F;AAAA,IAAA,EAAA,CACJ;AAAA;AAER;"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
|
+
import Alert from "@mui/material/Alert";
|
|
4
|
+
import Button from "@mui/material/Button";
|
|
5
|
+
import Divider from "@mui/material/Divider";
|
|
6
|
+
import List from "@mui/material/List";
|
|
7
|
+
import ListItem from "@mui/material/ListItem";
|
|
8
|
+
import ListItemIcon from "@mui/material/ListItemIcon";
|
|
9
|
+
import ListItemText from "@mui/material/ListItemText";
|
|
10
|
+
import Skeleton from "@mui/material/Skeleton";
|
|
11
|
+
import Stack from "@mui/material/Stack";
|
|
12
|
+
import Typography from "@mui/material/Typography";
|
|
13
|
+
import ComputerOutlinedIcon from "@mui/icons-material/ComputerOutlined";
|
|
14
|
+
import PhoneIphoneOutlinedIcon from "@mui/icons-material/PhoneIphoneOutlined";
|
|
15
|
+
import ConfirmDialog from "../feedback/ConfirmDialog.js";
|
|
16
|
+
import { toastSuccess } from "../feedback/toast.js";
|
|
17
|
+
import { useConfirmAction } from "../feedback/useConfirmAction.js";
|
|
18
|
+
import { formatDateTime } from "../formatting.js";
|
|
19
|
+
import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
|
|
20
|
+
import Tag from "../ui/labels/Tag.js";
|
|
21
|
+
import SectionCard from "../ui/layout/SectionCard.js";
|
|
22
|
+
const LOADING_HEIGHT_PIXELS = 96;
|
|
23
|
+
function SessionRow({ session }) {
|
|
24
|
+
const { t } = useToolkitTranslation("security");
|
|
25
|
+
const DeviceIcon = session.isMobile ? PhoneIphoneOutlinedIcon : ComputerOutlinedIcon;
|
|
26
|
+
const device = t("sessions.device", {
|
|
27
|
+
browser: session.browser ?? t("sessions.otherBrowser"),
|
|
28
|
+
platform: session.platform ?? t("sessions.otherPlatform")
|
|
29
|
+
});
|
|
30
|
+
const details = [t("sessions.since", { date: formatDateTime(session.startedAt) })];
|
|
31
|
+
if (session.network) {
|
|
32
|
+
details.push(t("sessions.network", { network: session.network }));
|
|
33
|
+
}
|
|
34
|
+
return /* @__PURE__ */ jsxs(ListItem, { disableGutters: true, alignItems: "flex-start", sx: { gap: 1 }, children: [
|
|
35
|
+
/* @__PURE__ */ jsx(ListItemIcon, { sx: { minWidth: 36, mt: 0.5 }, children: /* @__PURE__ */ jsx(DeviceIcon, {}) }),
|
|
36
|
+
/* @__PURE__ */ jsx(ListItemText, { primary: /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, useFlexGap: true, sx: { alignItems: "center", flexWrap: "wrap" }, children: [
|
|
37
|
+
/* @__PURE__ */ jsx("span", { children: device }),
|
|
38
|
+
session.isCurrent && /* @__PURE__ */ jsx(Tag, { label: t("sessions.current"), color: "success" })
|
|
39
|
+
] }), secondary: details.join(" · "), slotProps: { primary: { sx: { fontWeight: 600 } } } })
|
|
40
|
+
] });
|
|
41
|
+
}
|
|
42
|
+
function SessionsCard({ sessions, error = null, onCloseOthers, onClosed }) {
|
|
43
|
+
const { t } = useToolkitTranslation("security");
|
|
44
|
+
const othersCount = (sessions ?? []).filter((session) => !session.isCurrent).length;
|
|
45
|
+
const confirmation = useConfirmAction({
|
|
46
|
+
run: () => onCloseOthers(),
|
|
47
|
+
onDone: (closedCount) => {
|
|
48
|
+
toastSuccess(closedCount ? t("sessions.closed", { count: closedCount }) : t("sessions.noneClosed"));
|
|
49
|
+
onClosed?.();
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return /* @__PURE__ */ jsxs(SectionCard, { title: t("sessions.title"), children: [
|
|
53
|
+
/* @__PURE__ */ jsxs(Stack, { spacing: 2, children: [
|
|
54
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: t("sessions.description") }),
|
|
55
|
+
error && /* @__PURE__ */ jsx(Alert, { severity: "error", children: error }),
|
|
56
|
+
!sessions && !error && /* @__PURE__ */ jsx(Skeleton, { variant: "rounded", height: LOADING_HEIGHT_PIXELS }),
|
|
57
|
+
sessions && /* @__PURE__ */ jsx(List, { disablePadding: true, children: sessions.map((session, index) => /* @__PURE__ */ jsxs("li", { children: [
|
|
58
|
+
index > 0 && /* @__PURE__ */ jsx(Divider, { component: "div" }),
|
|
59
|
+
/* @__PURE__ */ jsx(SessionRow, { session })
|
|
60
|
+
] }, session.id)) }),
|
|
61
|
+
/* @__PURE__ */ jsxs(Stack, { spacing: 1, sx: { alignItems: "flex-start" }, children: [
|
|
62
|
+
sessions && othersCount === 0 && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: t("sessions.onlyThis") }),
|
|
63
|
+
/* @__PURE__ */ jsx(Button, { variant: "outlined", color: "warning", disabled: !sessions || othersCount === 0, onClick: () => confirmation.open({}), children: t("sessions.closeOthers") })
|
|
64
|
+
] })
|
|
65
|
+
] }),
|
|
66
|
+
/* @__PURE__ */ jsx(
|
|
67
|
+
ConfirmDialog,
|
|
68
|
+
{
|
|
69
|
+
...confirmation.dialogProps,
|
|
70
|
+
tone: "warning",
|
|
71
|
+
title: t("sessions.confirmTitle"),
|
|
72
|
+
description: t("sessions.confirmText", { count: othersCount }),
|
|
73
|
+
confirmLabel: t("sessions.confirm")
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
] });
|
|
77
|
+
}
|
|
78
|
+
export {
|
|
79
|
+
SessionsCard as default
|
|
80
|
+
};
|
|
81
|
+
//# sourceMappingURL=SessionsCard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionsCard.js","sources":["../../src/security/SessionsCard.jsx"],"sourcesContent":["// «Mis sesiones»: los equipos donde la cuenta sigue abierta (este, marcado) y «Cerrar la sesión en los demás equipos».\n//\n// No pide la contraseña: cerrar sesiones no da acceso a nada, solo lo quita. Nunca se pinta la IP completa ni el user\n// agent: el servidor manda el navegador, el sistema y la red a medias (p. ej. «187.190.x.x»), que bastan para reconocer\n// un equipo sin exponer datos.\n//\n// <SessionsCard sessions={sessions} onCloseOthers={async () => (await api.post('/sessions/close-others')).closed} />\n//\n// Genérico del paquete: function (regla de la casa).\nimport Alert from '@mui/material/Alert';\nimport Button from '@mui/material/Button';\nimport Divider from '@mui/material/Divider';\nimport List from '@mui/material/List';\nimport ListItem from '@mui/material/ListItem';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport Skeleton from '@mui/material/Skeleton';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport ComputerOutlinedIcon from '@mui/icons-material/ComputerOutlined';\nimport PhoneIphoneOutlinedIcon from '@mui/icons-material/PhoneIphoneOutlined';\n\nimport ConfirmDialog from '@/feedback/ConfirmDialog.jsx';\nimport {toastSuccess} from '@/feedback/toast.jsx';\nimport {useConfirmAction} from '@/feedback/useConfirmAction.js';\nimport {formatDateTime} from '@/formatting.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Tag from '@/ui/labels/Tag.jsx';\nimport SectionCard from '@/ui/layout/SectionCard.jsx';\n\nconst LOADING_HEIGHT_PIXELS = 96;\n\n/**\n * Un renglón: el equipo (navegador en sistema), desde cuándo y su red a medias.\n *\n * @param {{session: object}} props\n */\nfunction SessionRow({session}) {\n const {t} = useToolkitTranslation('security');\n const DeviceIcon = session.isMobile ? PhoneIphoneOutlinedIcon : ComputerOutlinedIcon;\n const device = t('sessions.device', {\n browser: session.browser ?? t('sessions.otherBrowser'), platform: session.platform ?? t('sessions.otherPlatform'),\n });\n const details = [t('sessions.since', {date: formatDateTime(session.startedAt)})];\n if (session.network) {\n details.push(t('sessions.network', {network: session.network}));\n }\n\n return (\n <ListItem disableGutters alignItems=\"flex-start\" sx={{gap: 1}}>\n <ListItemIcon sx={{minWidth: 36, mt: 0.5}}><DeviceIcon /></ListItemIcon>\n <ListItemText primary={(\n <Stack direction=\"row\" spacing={1} useFlexGap sx={{alignItems: 'center', flexWrap: 'wrap'}}>\n <span>{device}</span>\n {session.isCurrent && <Tag label={t('sessions.current')} color=\"success\" />}\n </Stack>\n )} secondary={details.join(' · ')} slotProps={{primary: {sx: {fontWeight: 600}}}} />\n </ListItem>\n );\n}\n\n/**\n * @param {object} props\n * @param {Array<{id: string, browser?: string|null, platform?: string|null, isMobile?: boolean, startedAt: string, network?: string|null, isCurrent?: boolean}>|null} props.sessions\n * null mientras llegan\n * @param {string|null} [props.error] ya traducido (ApiError.message) si no se pudieron traer\n * @param {() => Promise<number>} props.onCloseOthers cierra las demás; regresa cuántas cerró\n * @param {() => void} [props.onClosed] p. ej. volver a pedir la lista\n */\nexport default function SessionsCard({sessions, error = null, onCloseOthers, onClosed}) {\n const {t} = useToolkitTranslation('security');\n const othersCount = (sessions ?? []).filter((session) => !session.isCurrent).length;\n const confirmation = useConfirmAction({\n run: () => onCloseOthers(),\n onDone: (closedCount) => {\n toastSuccess(closedCount ? t('sessions.closed', {count: closedCount}) : t('sessions.noneClosed'));\n onClosed?.();\n },\n });\n\n return (\n <SectionCard title={t('sessions.title')}>\n <Stack spacing={2}>\n <Typography variant=\"body2\" color=\"text.secondary\">{t('sessions.description')}</Typography>\n {error && <Alert severity=\"error\">{error}</Alert>}\n {!sessions && !error && <Skeleton variant=\"rounded\" height={LOADING_HEIGHT_PIXELS} />}\n {sessions && (\n <List disablePadding>\n {sessions.map((session, index) => (\n <li key={session.id}>\n {index > 0 && <Divider component=\"div\" />}\n <SessionRow session={session} />\n </li>\n ))}\n </List>\n )}\n <Stack spacing={1} sx={{alignItems: 'flex-start'}}>\n {sessions && othersCount === 0 && <Typography variant=\"caption\" color=\"text.secondary\">{t('sessions.onlyThis')}</Typography>}\n <Button variant=\"outlined\" color=\"warning\" disabled={!sessions || othersCount === 0} onClick={() => confirmation.open({})}>\n {t('sessions.closeOthers')}\n </Button>\n </Stack>\n </Stack>\n <ConfirmDialog {...confirmation.dialogProps} tone=\"warning\" title={t('sessions.confirmTitle')}\n description={t('sessions.confirmText', {count: othersCount})} confirmLabel={t('sessions.confirm')} />\n </SectionCard>\n );\n}\n"],"names":[],"mappings":"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"}
|