@stackcraftmx/calcita 0.0.0-stage → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +110 -0
- package/README.md +700 -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 +128 -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 +83 -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 +107 -0
- package/cli/templates/project/src/app/AppShell.jsx.tpl +87 -0
- package/cli/templates/project/src/app/appRouter.jsx.tpl +51 -0
- package/cli/templates/project/src/app/appSettings.js.tpl +27 -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 +14 -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 +9 -0
- package/cli/templates/project/src/core/publicPaths.js.tpl +24 -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 +53 -0
- package/dist/DataTable/AuditTrailDialog.js +40 -0
- package/dist/DataTable/AuditTrailDialog.js.map +1 -0
- package/dist/DataTable/AuditTrailTable.js +89 -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 +51 -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 +63 -0
- package/dist/DataTable/GoToPage.js.map +1 -0
- package/dist/DataTable/ServerTable.js +477 -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/rowSelection.js +61 -0
- package/dist/DataTable/rowSelection.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 +84 -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 +27 -0
- package/dist/account/ForgotPasswordScreen.js.map +1 -0
- package/dist/account/ProfileScreen.js +134 -0
- package/dist/account/ProfileScreen.js.map +1 -0
- package/dist/account/ResetPasswordScreen.js +58 -0
- package/dist/account/ResetPasswordScreen.js.map +1 -0
- package/dist/account/SignInScreen.js +102 -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 +118 -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 +49 -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 +256 -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 +513 -0
- package/dist/appShell/AppLayout.js.map +1 -0
- package/dist/appShell/AppearanceSettings.js +116 -0
- package/dist/appShell/AppearanceSettings.js.map +1 -0
- package/dist/appShell/AuthLayout.js +46 -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 +105 -0
- package/dist/appShell/BarActions.js.map +1 -0
- package/dist/appShell/BarCapsule.js +50 -0
- package/dist/appShell/BarCapsule.js.map +1 -0
- package/dist/appShell/BarSearch.js +92 -0
- package/dist/appShell/BarSearch.js.map +1 -0
- package/dist/appShell/HeaderTools.js +53 -0
- package/dist/appShell/HeaderTools.js.map +1 -0
- package/dist/appShell/MobileTabBar.js +348 -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 +40 -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 +149 -0
- package/dist/calendar/EventCalendar.js.map +1 -0
- package/dist/calendar/EventDetails.js +74 -0
- package/dist/calendar/EventDetails.js.map +1 -0
- package/dist/calendar/calendarEvents.js +31 -0
- package/dist/calendar/calendarEvents.js.map +1 -0
- package/dist/calendar.js +13 -0
- package/dist/calendar.js.map +1 -0
- package/dist/charts.js +16 -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 +76 -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 +195 -0
- package/dist/downloads/DownloadManager.js.map +1 -0
- package/dist/downloads/downloadQueue.js +56 -0
- package/dist/downloads/downloadQueue.js.map +1 -0
- package/dist/downloads/downloadsMachine.js +80 -0
- package/dist/downloads/downloadsMachine.js.map +1 -0
- package/dist/downloads/fileTypes.js +22 -0
- package/dist/downloads/fileTypes.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 +73 -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 +256 -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 +205 -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 +63 -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 +47 -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 +338 -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/FormWizard.js +59 -0
- package/dist/hookForm/FormWizard.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 +104 -0
- package/dist/inbox/InboxLayout.js.map +1 -0
- package/dist/inbox/MessageList.js +114 -0
- package/dist/inbox/MessageList.js.map +1 -0
- package/dist/inbox/MessageView.js +104 -0
- package/dist/inbox/MessageView.js.map +1 -0
- package/dist/inbox/inboxDates.js +9 -0
- package/dist/inbox/inboxDates.js.map +1 -0
- package/dist/index.js +407 -0
- package/dist/index.js.map +1 -0
- package/dist/inputs/CatalogInput.js +66 -0
- package/dist/inputs/CatalogInput.js.map +1 -0
- package/dist/inputs/ColorInput.js +109 -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 +70 -0
- package/dist/inputs/NumberInput.js.map +1 -0
- package/dist/inputs/SelectInput.js +84 -0
- package/dist/inputs/SelectInput.js.map +1 -0
- package/dist/inputs/TextInput.js +101 -0
- package/dist/inputs/TextInput.js.map +1 -0
- package/dist/inputs/WizardLayout.js +54 -0
- package/dist/inputs/WizardLayout.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 +338 -0
- package/dist/kanban/KanbanBoard.js.map +1 -0
- package/dist/kanban/kanbanCards.js +19 -0
- package/dist/kanban/kanbanCards.js.map +1 -0
- package/dist/kanban/kanbanMoves.js +29 -0
- package/dist/kanban/kanbanMoves.js.map +1 -0
- package/dist/kanban.js +15 -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 +787 -0
- package/dist/locales/en.js.map +1 -0
- package/dist/locales/es.js +787 -0
- package/dist/locales/es.js.map +1 -0
- package/dist/maps/MapView.js +116 -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 +77 -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 +34 -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 +70 -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 +71 -0
- package/dist/pwa/useInstallPrompt.js.map +1 -0
- package/dist/react-hook-form.js +32 -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 +80 -0
- package/dist/security/ActivityLog.js.map +1 -0
- package/dist/security/RecoveryCodesDialog.js +85 -0
- package/dist/security/RecoveryCodesDialog.js.map +1 -0
- package/dist/security/SessionsCard.js +83 -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 +37 -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/MuiDialog.js +13 -0
- package/dist/theme/components/MuiDialog.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 +28 -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/ComponentTexts.js +13 -0
- package/dist/toolkit/ComponentTexts.js.map +1 -0
- package/dist/toolkit/ToolkitProvider.js +57 -0
- package/dist/toolkit/ToolkitProvider.js.map +1 -0
- package/dist/toolkit/browserNavigation.js +33 -0
- package/dist/toolkit/browserNavigation.js.map +1 -0
- package/dist/toolkit/componentTextsContext.js +15 -0
- package/dist/toolkit/componentTextsContext.js.map +1 -0
- package/dist/toolkit/hashNavigation.js +40 -0
- package/dist/toolkit/hashNavigation.js.map +1 -0
- package/dist/toolkit/navigationPaths.js +49 -0
- package/dist/toolkit/navigationPaths.js.map +1 -0
- package/dist/toolkit/toolkitContext.js +19 -0
- package/dist/toolkit/toolkitContext.js.map +1 -0
- package/dist/toolkit/toolkitSettings.js +107 -0
- package/dist/toolkit/toolkitSettings.js.map +1 -0
- package/dist/toolkit/useFormatters.js +12 -0
- package/dist/toolkit/useFormatters.js.map +1 -0
- package/dist/toolkit/useToolkitTranslation.js +22 -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 +30 -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 +13 -0
- package/dist/types/DataTable/FilterChips.d.ts +17 -0
- package/dist/types/DataTable/GoToPage.d.ts +13 -0
- package/dist/types/DataTable/SelectionBar.d.ts +32 -0
- package/dist/types/DataTable/ServerTable.d.ts +171 -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/rowSelection.d.ts +113 -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 +23 -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 +9 -0
- package/dist/types/account/DemoTotpCodeButton.d.ts +6 -0
- package/dist/types/account/ForgotPasswordScreen.d.ts +17 -0
- package/dist/types/account/ProfileScreen.d.ts +43 -0
- package/dist/types/account/ResetPasswordScreen.d.ts +21 -0
- package/dist/types/account/SignInScreen.d.ts +27 -0
- package/dist/types/account/accountConnector.d.ts +268 -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 +42 -0
- package/dist/types/api/ApiError.d.ts +42 -0
- package/dist/types/api/createApiClient.d.ts +174 -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 +76 -0
- package/dist/types/appShell/AppearanceSettings.d.ts +41 -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 +23 -0
- package/dist/types/appShell/BarCapsule.d.ts +20 -0
- package/dist/types/appShell/BarSearch.d.ts +24 -0
- package/dist/types/appShell/HeaderTools.d.ts +27 -0
- package/dist/types/appShell/MobileTabBar.d.ts +20 -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 +46 -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 +13 -0
- package/dist/types/auth/passwordRules.d.ts +34 -0
- package/dist/types/calendar/EventCalendar.d.ts +63 -0
- package/dist/types/calendar/EventDetails.d.ts +36 -0
- package/dist/types/calendar/calendarEvents.d.ts +27 -0
- package/dist/types/calendar.d.ts +3 -0
- package/dist/types/charts.d.ts +6 -0
- package/dist/types/date-pickers.d.ts +2 -0
- package/dist/types/datePickers/DateInput.d.ts +41 -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 +7 -0
- package/dist/types/downloads/downloadQueue.d.ts +50 -0
- package/dist/types/downloads/downloadsMachine.d.ts +10 -0
- package/dist/types/downloads/fileTypes.d.ts +39 -0
- package/dist/types/downloads/index.d.ts +4 -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 +31 -0
- package/dist/types/feedback/ModalWaiting.d.ts +13 -0
- package/dist/types/feedback/NewBuildNotice.d.ts +20 -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 +61 -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 +61 -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 +22 -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 +17 -0
- package/dist/types/forms/auth/ForgotPasswordForm.d.ts +14 -0
- package/dist/types/forms/auth/SignInForm.d.ts +20 -0
- package/dist/types/forms/index.d.ts +19 -0
- package/dist/types/forms/security/SecondStepForm.d.ts +30 -0
- package/dist/types/forms/security/TwoStepVerificationCard.d.ts +83 -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/FormWizard.d.ts +22 -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 +38 -0
- package/dist/types/inbox/MessageList.d.ts +52 -0
- package/dist/types/inbox/MessageView.d.ts +55 -0
- package/dist/types/inbox/inboxDates.d.ts +11 -0
- package/dist/types/index.d.ts +91 -0
- package/dist/types/inputs/CatalogInput.d.ts +45 -0
- package/dist/types/inputs/ColorInput.d.ts +30 -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 +38 -0
- package/dist/types/inputs/SelectInput.d.ts +38 -0
- package/dist/types/inputs/TextInput.d.ts +62 -0
- package/dist/types/inputs/WizardLayout.d.ts +34 -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 +88 -0
- package/dist/types/kanban/kanbanCards.d.ts +22 -0
- package/dist/types/kanban/kanbanMoves.d.ts +38 -0
- package/dist/types/kanban.d.ts +3 -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 +788 -0
- package/dist/types/locales/es.d.ts +788 -0
- package/dist/types/maps/MapView.d.ts +41 -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 +18 -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 +7 -0
- package/dist/types/pwa/InstallInstructionsDialog.d.ts +20 -0
- package/dist/types/pwa/InstallPromptBanner.d.ts +16 -0
- package/dist/types/pwa/installInstructions.d.ts +52 -0
- package/dist/types/pwa/useInstallPrompt.d.ts +13 -0
- package/dist/types/react-hook-form.d.ts +12 -0
- package/dist/types/react-router.d.ts +2 -0
- package/dist/types/security/ActivityLog.d.ts +33 -0
- package/dist/types/security/RecoveryCodesDialog.d.ts +16 -0
- package/dist/types/security/SessionsCard.d.ts +24 -0
- package/dist/types/security/passkeys.d.ts +18 -0
- package/dist/types/table.d.ts +3 -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/MuiDialog.d.ts +9 -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/ComponentTexts.d.ts +11 -0
- package/dist/types/toolkit/ToolkitProvider.d.ts +47 -0
- package/dist/types/toolkit/browserNavigation.d.ts +27 -0
- package/dist/types/toolkit/componentTextsContext.d.ts +20 -0
- package/dist/types/toolkit/hashNavigation.d.ts +12 -0
- package/dist/types/toolkit/navigationPaths.d.ts +43 -0
- package/dist/types/toolkit/toolkitContext.d.ts +28 -0
- package/dist/types/toolkit/toolkitSettings.d.ts +113 -0
- package/dist/types/toolkit/useFormatters.d.ts +6 -0
- package/dist/types/toolkit/useToolkitTranslation.d.ts +11 -0
- package/dist/types/ui/actions/ActionsMenu.d.ts +20 -0
- package/dist/types/ui/actions/CopyButton.d.ts +15 -0
- package/dist/types/ui/actions/DownloadMenu.d.ts +55 -0
- package/dist/types/ui/actions/SecretField.d.ts +17 -0
- package/dist/types/ui/actions/SelectionActions.d.ts +39 -0
- package/dist/types/ui/filters/DateRangeFilter.d.ts +18 -0
- package/dist/types/ui/filters/PeriodRangeSelector.d.ts +28 -0
- package/dist/types/ui/filters/QuickFilters.d.ts +23 -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/labels/tagOf.d.ts +13 -0
- package/dist/types/ui/layout/CollapsibleSection.d.ts +18 -0
- package/dist/types/ui/layout/ContentDialog.d.ts +15 -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 +35 -0
- package/dist/types/ui/layout/FullPageLoader.d.ts +7 -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 +20 -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 +25 -0
- package/dist/types/ui/metrics/CalendarHeatmap.d.ts +34 -0
- package/dist/types/ui/metrics/ChartTooltip.d.ts +11 -0
- package/dist/types/ui/metrics/ColumnChart.d.ts +47 -0
- package/dist/types/ui/metrics/LineChart.d.ts +41 -0
- package/dist/types/ui/metrics/MetricCard.d.ts +39 -0
- package/dist/types/ui/metrics/TableToggle.d.ts +14 -0
- package/dist/types/ui/metrics/barListLabels.d.ts +17 -0
- package/dist/types/ui/metrics/chartParts.d.ts +112 -0
- package/dist/types/ui/metrics/heatmapScale.d.ts +45 -0
- package/dist/types/ui/navigation/BackButton.d.ts +13 -0
- package/dist/types/ui/navigation/ColorSchemeToggle.d.ts +13 -0
- package/dist/types/ui/navigation/DocumentTitle.d.ts +6 -0
- package/dist/types/ui/navigation/FontSizeToggle.d.ts +11 -0
- package/dist/types/ui/navigation/LanguageToggle.d.ts +13 -0
- package/dist/types/ui/navigation/PageBreadcrumbs.d.ts +12 -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 +41 -0
- package/dist/types/ui/timeline/timelineDot.d.ts +19 -0
- package/dist/types/upload/FileDropzone.d.ts +36 -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/ActionsMenu.js +51 -0
- package/dist/ui/actions/ActionsMenu.js.map +1 -0
- package/dist/ui/actions/CopyButton.js +28 -0
- package/dist/ui/actions/CopyButton.js.map +1 -0
- package/dist/ui/actions/DownloadMenu.js +162 -0
- package/dist/ui/actions/DownloadMenu.js.map +1 -0
- package/dist/ui/actions/SecretField.js +61 -0
- package/dist/ui/actions/SecretField.js.map +1 -0
- package/dist/ui/actions/SelectionActions.js +142 -0
- package/dist/ui/actions/SelectionActions.js.map +1 -0
- package/dist/ui/filters/DateRangeFilter.js +87 -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/labels/tagOf.js +7 -0
- package/dist/ui/labels/tagOf.js.map +1 -0
- package/dist/ui/layout/CollapsibleSection.js +52 -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 +54 -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 +94 -0
- package/dist/ui/metrics/BarList.js.map +1 -0
- package/dist/ui/metrics/CalendarHeatmap.js +136 -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 +106 -0
- package/dist/ui/metrics/ColumnChart.js.map +1 -0
- package/dist/ui/metrics/LineChart.js +117 -0
- package/dist/ui/metrics/LineChart.js.map +1 -0
- package/dist/ui/metrics/MetricCard.js +97 -0
- package/dist/ui/metrics/MetricCard.js.map +1 -0
- package/dist/ui/metrics/TableToggle.js +15 -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/chartParts.js +93 -0
- package/dist/ui/metrics/chartParts.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 +40 -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 +41 -0
- package/dist/ui/navigation/FontSizeToggle.js.map +1 -0
- package/dist/ui/navigation/LanguageToggle.js +48 -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 +106 -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 +145 -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 +311 -5
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
|
|
5
|
+
import { useToolkitNavigation } from "../toolkit/toolkitContext.js";
|
|
6
|
+
import Box from "@mui/material/Box";
|
|
7
|
+
import Button from "@mui/material/Button";
|
|
8
|
+
import ListItemIcon from "@mui/material/ListItemIcon";
|
|
9
|
+
import ListItemText from "@mui/material/ListItemText";
|
|
10
|
+
import Menu from "@mui/material/Menu";
|
|
11
|
+
import MenuItem from "@mui/material/MenuItem";
|
|
12
|
+
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
|
13
|
+
import { menuItemLabelOf } from "./menuItemText.js";
|
|
14
|
+
const ACTIVE_UNDERLINE_PIXELS = 2;
|
|
15
|
+
function TopMenuEntry({ menuItem, activeItem }) {
|
|
16
|
+
const { t } = useToolkitTranslation("layout");
|
|
17
|
+
const { Link: RouterLink } = useToolkitNavigation();
|
|
18
|
+
const [anchorElement, setAnchorElement] = useState(null);
|
|
19
|
+
const hasChildren = Array.isArray(menuItem.children) && menuItem.children.length > 0;
|
|
20
|
+
const isActive = menuItem === activeItem || hasChildren && menuItem.children.includes(activeItem);
|
|
21
|
+
const Icon = menuItem.Icon;
|
|
22
|
+
const buttonSx = {
|
|
23
|
+
color: "inherit",
|
|
24
|
+
borderRadius: 1,
|
|
25
|
+
px: 1.5,
|
|
26
|
+
whiteSpace: "nowrap",
|
|
27
|
+
fontWeight: isActive ? 600 : 500,
|
|
28
|
+
boxShadow: isActive ? `inset 0 -${ACTIVE_UNDERLINE_PIXELS}px 0 currentColor` : "none"
|
|
29
|
+
};
|
|
30
|
+
if (!hasChildren) {
|
|
31
|
+
return /* @__PURE__ */ jsx(
|
|
32
|
+
Button,
|
|
33
|
+
{
|
|
34
|
+
component: RouterLink,
|
|
35
|
+
to: menuItem.to,
|
|
36
|
+
startIcon: Icon ? /* @__PURE__ */ jsx(Icon, { fontSize: "small" }) : void 0,
|
|
37
|
+
"aria-current": isActive ? "page" : void 0,
|
|
38
|
+
sx: buttonSx,
|
|
39
|
+
children: menuItemLabelOf(menuItem, t)
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
44
|
+
/* @__PURE__ */ jsx(
|
|
45
|
+
Button,
|
|
46
|
+
{
|
|
47
|
+
onClick: (event) => setAnchorElement(event.currentTarget),
|
|
48
|
+
"aria-haspopup": "menu",
|
|
49
|
+
"aria-expanded": Boolean(anchorElement),
|
|
50
|
+
startIcon: Icon ? /* @__PURE__ */ jsx(Icon, { fontSize: "small" }) : void 0,
|
|
51
|
+
endIcon: /* @__PURE__ */ jsx(ExpandMoreIcon, { fontSize: "small" }),
|
|
52
|
+
sx: buttonSx,
|
|
53
|
+
children: menuItemLabelOf(menuItem, t)
|
|
54
|
+
}
|
|
55
|
+
),
|
|
56
|
+
/* @__PURE__ */ jsx(Menu, { anchorEl: anchorElement, open: Boolean(anchorElement), onClose: () => setAnchorElement(null), slotProps: { paper: { sx: { minWidth: 220, mt: 0.5 } } }, children: menuItem.children.map((child) => {
|
|
57
|
+
const ChildIcon = child.Icon;
|
|
58
|
+
return /* @__PURE__ */ jsxs(MenuItem, { component: RouterLink, to: child.to, selected: child === activeItem, onClick: () => setAnchorElement(null), children: [
|
|
59
|
+
ChildIcon && /* @__PURE__ */ jsx(ListItemIcon, { children: /* @__PURE__ */ jsx(ChildIcon, { fontSize: "small" }) }),
|
|
60
|
+
/* @__PURE__ */ jsx(ListItemText, { primary: menuItemLabelOf(child, t) })
|
|
61
|
+
] }, child.to);
|
|
62
|
+
}) })
|
|
63
|
+
] });
|
|
64
|
+
}
|
|
65
|
+
function TopMenu({ menuItems, activeItem }) {
|
|
66
|
+
const { t } = useToolkitTranslation("layout");
|
|
67
|
+
return /* @__PURE__ */ jsx(
|
|
68
|
+
Box,
|
|
69
|
+
{
|
|
70
|
+
component: "nav",
|
|
71
|
+
"aria-label": t("drawer.ariaLabel"),
|
|
72
|
+
sx: { display: { xs: "none", md: "flex" }, alignItems: "stretch", alignSelf: "stretch", gap: 0.5, minWidth: 0, overflowX: "auto" },
|
|
73
|
+
children: menuItems.map((menuItem) => /* @__PURE__ */ jsx(TopMenuEntry, { menuItem, activeItem }, menuItem.to ?? menuItemLabelOf(menuItem, t)))
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
export {
|
|
78
|
+
TopMenu as default
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=TopMenu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TopMenu.js","sources":["../../src/appShell/TopMenu.jsx"],"sourcesContent":["// El menú dentro de la barra (menuPosition=\"top\"), para apps de pocos módulos: cada entrada es un botón; la que tiene\n// submenú abre una lista debajo. Las secciones no se pintan aquí (en una fila no hay dónde); en el teléfono el menú es\n// el mismo cajón del estilo lateral, con sus secciones.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {useToolkitNavigation} from '@/toolkit/toolkitContext.js';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport Menu from '@mui/material/Menu';\nimport MenuItem from '@mui/material/MenuItem';\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\n\nimport {menuItemLabelOf} from '@/appShell/menuItemText.js';\n\n// la entrada abierta se marca con una raya abajo, del color principal (en la barra naranja, del color del texto)\nconst ACTIVE_UNDERLINE_PIXELS = 2;\n\n/**\n * Un botón del menú de arriba, con su lista si tiene submenú.\n *\n * @param {{menuItem: object, activeItem: object|null}} props\n */\nfunction TopMenuEntry({menuItem, activeItem}) {\n const {t} = useToolkitTranslation('layout');\n const {Link: RouterLink} = useToolkitNavigation();\n const [anchorElement, setAnchorElement] = useState(null);\n const hasChildren = Array.isArray(menuItem.children) && menuItem.children.length > 0;\n const isActive = menuItem === activeItem || (hasChildren && menuItem.children.includes(activeItem));\n const Icon = menuItem.Icon;\n const buttonSx = {\n color: 'inherit', borderRadius: 1, px: 1.5, whiteSpace: 'nowrap', fontWeight: isActive ? 600 : 500,\n boxShadow: isActive ? `inset 0 -${ACTIVE_UNDERLINE_PIXELS}px 0 currentColor` : 'none',\n };\n\n if (!hasChildren) {\n return (\n <Button component={RouterLink} to={menuItem.to} startIcon={Icon ? <Icon fontSize=\"small\" /> : undefined}\n aria-current={isActive ? 'page' : undefined} sx={buttonSx}>\n {menuItemLabelOf(menuItem, t)}\n </Button>\n );\n }\n return (\n <>\n <Button onClick={(event) => setAnchorElement(event.currentTarget)} aria-haspopup=\"menu\" aria-expanded={Boolean(anchorElement)}\n startIcon={Icon ? <Icon fontSize=\"small\" /> : undefined} endIcon={<ExpandMoreIcon fontSize=\"small\" />} sx={buttonSx}>\n {menuItemLabelOf(menuItem, t)}\n </Button>\n <Menu anchorEl={anchorElement} open={Boolean(anchorElement)} onClose={() => setAnchorElement(null)} slotProps={{paper: {sx: {minWidth: 220, mt: 0.5}}}}>\n {menuItem.children.map((child) => {\n const ChildIcon = child.Icon;\n return (\n <MenuItem key={child.to} component={RouterLink} to={child.to} selected={child === activeItem} onClick={() => setAnchorElement(null)}>\n {ChildIcon && <ListItemIcon><ChildIcon fontSize=\"small\" /></ListItemIcon>}\n <ListItemText primary={menuItemLabelOf(child, t)} />\n </MenuItem>\n );\n })}\n </Menu>\n </>\n );\n}\n\n/**\n * @param {{menuItems: object[], activeItem: object|null}} props\n */\nexport default function TopMenu({menuItems, activeItem}) {\n const {t} = useToolkitTranslation('layout');\n return (\n <Box component=\"nav\" aria-label={t('drawer.ariaLabel')}\n sx={{display: {xs: 'none', md: 'flex'}, alignItems: 'stretch', alignSelf: 'stretch', gap: 0.5, minWidth: 0, overflowX: 'auto'}}>\n {menuItems.map((menuItem) => (\n <TopMenuEntry key={menuItem.to ?? menuItemLabelOf(menuItem, t)} menuItem={menuItem} activeItem={activeItem} />\n ))}\n </Box>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;AAmBA,MAAM,0BAA0B;AAOhC,SAAS,aAAa,EAAC,UAAU,cAAa;AAC1C,QAAM,EAAC,EAAA,IAAK,sBAAsB,QAAQ;AAC1C,QAAM,EAAC,MAAM,WAAA,IAAc,qBAAA;AAC3B,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,IAAI;AACvD,QAAM,cAAc,MAAM,QAAQ,SAAS,QAAQ,KAAK,SAAS,SAAS,SAAS;AACnF,QAAM,WAAW,aAAa,cAAe,eAAe,SAAS,SAAS,SAAS,UAAU;AACjG,QAAM,OAAO,SAAS;AACtB,QAAM,WAAW;AAAA,IACb,OAAO;AAAA,IAAW,cAAc;AAAA,IAAG,IAAI;AAAA,IAAK,YAAY;AAAA,IAAU,YAAY,WAAW,MAAM;AAAA,IAC/F,WAAW,WAAW,YAAY,uBAAuB,sBAAsB;AAAA,EAAA;AAGnF,MAAI,CAAC,aAAa;AACd,WACI;AAAA,MAAC;AAAA,MAAA;AAAA,QAAO,WAAW;AAAA,QAAY,IAAI,SAAS;AAAA,QAAI,WAAW,OAAO,oBAAC,MAAA,EAAK,UAAS,SAAQ,IAAK;AAAA,QACtF,gBAAc,WAAW,SAAS;AAAA,QAAW,IAAI;AAAA,QACpD,UAAA,gBAAgB,UAAU,CAAC;AAAA,MAAA;AAAA,IAAA;AAAA,EAGxC;AACA,SACI,qBAAA,UAAA,EACI,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QAAO,SAAS,CAAC,UAAU,iBAAiB,MAAM,aAAa;AAAA,QAAG,iBAAc;AAAA,QAAO,iBAAe,QAAQ,aAAa;AAAA,QACpH,WAAW,OAAO,oBAAC,MAAA,EAAK,UAAS,SAAQ,IAAK;AAAA,QAAW,SAAS,oBAAC,gBAAA,EAAe,UAAS,QAAA,CAAQ;AAAA,QAAI,IAAI;AAAA,QAC9G,UAAA,gBAAgB,UAAU,CAAC;AAAA,MAAA;AAAA,IAAA;AAAA,IAEhC,oBAAC,MAAA,EAAK,UAAU,eAAe,MAAM,QAAQ,aAAa,GAAG,SAAS,MAAM,iBAAiB,IAAI,GAAG,WAAW,EAAC,OAAO,EAAC,IAAI,EAAC,UAAU,KAAK,IAAI,IAAA,IAAI,GAC/I,UAAA,SAAS,SAAS,IAAI,CAAC,UAAU;AAC9B,YAAM,YAAY,MAAM;AACxB,aACI,qBAAC,UAAA,EAAwB,WAAW,YAAY,IAAI,MAAM,IAAI,UAAU,UAAU,YAAY,SAAS,MAAM,iBAAiB,IAAI,GAC7H,UAAA;AAAA,QAAA,iCAAc,cAAA,EAAa,UAAA,oBAAC,WAAA,EAAU,UAAS,SAAQ,GAAE;AAAA,4BACzD,cAAA,EAAa,SAAS,gBAAgB,OAAO,CAAC,EAAA,CAAG;AAAA,MAAA,EAAA,GAFvC,MAAM,EAGrB;AAAA,IAER,CAAC,EAAA,CACL;AAAA,EAAA,GACJ;AAER;AAKA,SAAwB,QAAQ,EAAC,WAAW,cAAa;AACrD,QAAM,EAAC,EAAA,IAAK,sBAAsB,QAAQ;AAC1C,SACI;AAAA,IAAC;AAAA,IAAA;AAAA,MAAI,WAAU;AAAA,MAAM,cAAY,EAAE,kBAAkB;AAAA,MAChD,IAAI,EAAC,SAAS,EAAC,IAAI,QAAQ,IAAI,OAAA,GAAS,YAAY,WAAW,WAAW,WAAW,KAAK,KAAK,UAAU,GAAG,WAAW,OAAA;AAAA,MACvH,UAAA,UAAU,IAAI,CAAC,iCACX,cAAA,EAA+D,UAAoB,WAAA,GAAjE,SAAS,MAAM,gBAAgB,UAAU,CAAC,CAA+C,CAC/G;AAAA,IAAA;AAAA,EAAA;AAGb;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
const AppMenuContext = createContext({ menuItems: [] });
|
|
4
|
+
function useAppMenu() {
|
|
5
|
+
return useContext(AppMenuContext);
|
|
6
|
+
}
|
|
7
|
+
export {
|
|
8
|
+
AppMenuContext,
|
|
9
|
+
useAppMenu
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=appMenuContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"appMenuContext.js","sources":["../../src/appShell/appMenuContext.js"],"sourcesContent":["// El menú de la app al alcance de las páginas: AppLayout lo pone y PageHeading lo lee para armar sus migas solas (Inicio ›\n// Sección › Pantalla) sin que cada página las escriba. Fuera de AppLayout el menú está vacío y no hay migas automáticas.\n//\n// Hook genérico del paquete: function (regla de la casa).\nimport {createContext, useContext} from 'react';\n\nexport const AppMenuContext = createContext({menuItems: []});\n\n/**\n * @returns {{menuItems: object[]}} lo que AppLayout recibió de composeMenu\n */\nexport function useAppMenu() {\n return useContext(AppMenuContext);\n}\n"],"names":[],"mappings":";;AAMY,MAAC,iBAAiB,cAAc,EAAC,WAAW,GAAE,CAAC;AAKpD,SAAS,aAAa;AACzB,SAAO,WAAW,cAAc;AACpC;"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
const BAR_ACTIONS_PLACEMENT = Object.freeze({ capsule: "capsule", menu: "menu", inline: "inline" });
|
|
4
|
+
const BarActionsSlotContext = createContext({ slot: null, phoneSlot: null, usesCapsules: false });
|
|
5
|
+
const BarActionsPlacementContext = createContext(BAR_ACTIONS_PLACEMENT.inline);
|
|
6
|
+
const BarActionsMenuCloseContext = createContext(() => {
|
|
7
|
+
});
|
|
8
|
+
function useBarActionsSlot() {
|
|
9
|
+
return useContext(BarActionsSlotContext);
|
|
10
|
+
}
|
|
11
|
+
function useBarActionsPlacement() {
|
|
12
|
+
return useContext(BarActionsPlacementContext);
|
|
13
|
+
}
|
|
14
|
+
function useCloseBarActionsMenu() {
|
|
15
|
+
return useContext(BarActionsMenuCloseContext);
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
BAR_ACTIONS_PLACEMENT,
|
|
19
|
+
BarActionsMenuCloseContext,
|
|
20
|
+
BarActionsPlacementContext,
|
|
21
|
+
BarActionsSlotContext,
|
|
22
|
+
useBarActionsPlacement,
|
|
23
|
+
useBarActionsSlot,
|
|
24
|
+
useCloseBarActionsMenu
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=barActionsSlot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"barActionsSlot.js","sources":["../../src/appShell/barActionsSlot.js"],"sourcesContent":["// Los lugares del marco donde caen las acciones de cada pantalla (BarActions), y cómo va la barra. Los da AppLayout:\n// - slot: en escritorio, dentro de la barra de arriba (null si no hay barra visible, como con la barra fundida al menú);\n// - phoneSlot: en el teléfono con cápsulas, el renglón que flota arriba a la derecha y se queda al bajar (null si no hay).\n// Fuera de AppLayout (una prueba, una pantalla sin marco) no hay lugar y las acciones se quedan donde la pantalla las pone.\n// También dice a lo de adentro dónde quedó, para que un botón se acomode solo (BarActionButton):\n// - en una cápsula (arriba en la barra, flotando en el teléfono o en la pantalla): solo el ícono, con su nombre en el tooltip;\n// - en el menú «⋯» del teléfono (las que ya no caben en el renglón): un renglón del menú con ícono y texto;\n// - suelto (fuera de BarActions): ícono con texto.\n//\n// Contexto del paquete: no renderiza (regla de la casa).\nimport {createContext, useContext} from 'react';\n\n/** Dónde quedó un botón de acción: en una cápsula, en el menú «⋯» o suelto. */\nexport const BAR_ACTIONS_PLACEMENT = Object.freeze({capsule: 'capsule', menu: 'menu', inline: 'inline'});\n\nexport const BarActionsSlotContext = createContext({slot: null, phoneSlot: null, usesCapsules: false});\nexport const BarActionsPlacementContext = createContext(BAR_ACTIONS_PLACEMENT.inline);\n// en el menú «⋯»: cómo cerrarlo después de picar una acción\nexport const BarActionsMenuCloseContext = createContext(() => {});\n\n/**\n * @returns {{slot: Element|null, phoneSlot: Element|null, usesCapsules: boolean}} slot: el lugar de la barra en escritorio;\n * phoneSlot: el renglón flotante del teléfono; usesCapsules: la barra va en cápsulas\n */\nexport function useBarActionsSlot() {\n return useContext(BarActionsSlotContext);\n}\n\n/**\n * Dónde quedó lo que está adentro de BarActions (BAR_ACTIONS_PLACEMENT). Fuera de BarActions, 'inline'.\n *\n * @returns {string}\n */\nexport function useBarActionsPlacement() {\n return useContext(BarActionsPlacementContext);\n}\n\n/**\n * En el menú «⋯» del teléfono, la función que lo cierra (para algo propio que haga su acción y deba cerrarlo); fuera de él\n * no hace nada.\n *\n * @returns {() => void}\n */\nexport function useCloseBarActionsMenu() {\n return useContext(BarActionsMenuCloseContext);\n}\n"],"names":[],"mappings":";;AAaY,MAAC,wBAAwB,OAAO,OAAO,EAAC,SAAS,WAAW,MAAM,QAAQ,QAAQ,SAAQ,CAAC;AAE3F,MAAC,wBAAwB,cAAc,EAAC,MAAM,MAAM,WAAW,MAAM,cAAc,MAAK,CAAC;AACzF,MAAC,6BAA6B,cAAc,sBAAsB,MAAM;AAExE,MAAC,6BAA6B,cAAc,MAAM;AAAC,CAAC;AAMzD,SAAS,oBAAoB;AAChC,SAAO,WAAW,qBAAqB;AAC3C;AAOO,SAAS,yBAAyB;AACrC,SAAO,WAAW,0BAA0B;AAChD;AAQO,SAAS,yBAAyB;AACrC,SAAO,WAAW,0BAA0B;AAChD;"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const MENU_GAP_PIXELS = 8;
|
|
2
|
+
const SIDE_GAP_EXTRA_PIXELS = 10;
|
|
3
|
+
function barMenuPlacementOf(anchorElement) {
|
|
4
|
+
const box = anchorElement && typeof window !== "undefined" ? anchorElement.getBoundingClientRect() : null;
|
|
5
|
+
const isInLowerHalf = Boolean(box) && box.top > window.innerHeight / 2;
|
|
6
|
+
const isOnLeftEdge = Boolean(box) && box.right < window.innerWidth / 4;
|
|
7
|
+
if (isOnLeftEdge) {
|
|
8
|
+
const vertical = isInLowerHalf ? "bottom" : "top";
|
|
9
|
+
return {
|
|
10
|
+
anchorOrigin: { vertical, horizontal: "right" },
|
|
11
|
+
transformOrigin: { vertical, horizontal: "left" },
|
|
12
|
+
gapSx: { ml: `${MENU_GAP_PIXELS + SIDE_GAP_EXTRA_PIXELS}px` }
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
if (isInLowerHalf) {
|
|
16
|
+
const bar = anchorElement.closest("header, nav") ?? anchorElement;
|
|
17
|
+
const insideBarPixels = Math.max(0, box.top - bar.getBoundingClientRect().top);
|
|
18
|
+
return {
|
|
19
|
+
anchorOrigin: { vertical: "top", horizontal: "right" },
|
|
20
|
+
transformOrigin: { vertical: "bottom", horizontal: "right" },
|
|
21
|
+
gapSx: { mt: `-${Math.round(insideBarPixels) + MENU_GAP_PIXELS}px` }
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
anchorOrigin: { vertical: "bottom", horizontal: "right" },
|
|
26
|
+
transformOrigin: { vertical: "top", horizontal: "right" },
|
|
27
|
+
gapSx: { mt: `${MENU_GAP_PIXELS}px` }
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
barMenuPlacementOf
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=barMenuPlacement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"barMenuPlacement.js","sources":["../../src/appShell/barMenuPlacement.js"],"sourcesContent":["// Hacia dónde abre un menú de la barra (la cuenta, los ajustes): hacia abajo si el botón está arriba de la pantalla, hacia\n// ARRIBA si está abajo, y hacia la DERECHA si está en la orilla izquierda (el menú lateral encogido hace de barra). En el\n// teléfono con vidrio la barra flota abajo, como la de Safari en el iPhone; un menú que abría hacia abajo no cabía y MUI lo\n// subía encima del botón, tapándolo.\n//\n// Se decide al abrir (con la posición real del botón), no con el ancho de la pantalla: así sirve igual si la barra está\n// arriba o abajo, y no depende de nada que el servidor no pueda saber.\n//\n// Funciones puras, sin React: function (regla de la casa).\n\n// lo que se separa el menú de su botón (px)\nconst MENU_GAP_PIXELS = 8;\n// abriendo de lado desde el menú encogido: lo que hay del botón a la orilla del panel (10 px), para que salga afuera\nconst SIDE_GAP_EXTRA_PIXELS = 10;\n\n/**\n * @param {Element|null} anchorElement el botón que abre el menú\n * @returns {{anchorOrigin: object, transformOrigin: object, gapSx: object}} para el <Menu> de MUI (gapSx va en el sx del papel)\n */\nexport function barMenuPlacementOf(anchorElement) {\n const box = anchorElement && typeof window !== 'undefined' ? anchorElement.getBoundingClientRect() : null;\n const isInLowerHalf = Boolean(box) && box.top > window.innerHeight / 2;\n // en la orilla izquierda (el menú lateral encogido, que hace también de barra): abre HACIA LA DERECHA, o se saldría de\n // la pantalla. Arriba o abajo según dónde esté el botón\n const isOnLeftEdge = Boolean(box) && box.right < window.innerWidth / 4;\n if (isOnLeftEdge) {\n const vertical = isInLowerHalf ? 'bottom' : 'top';\n return {\n anchorOrigin: {vertical, horizontal: 'right'},\n transformOrigin: {vertical, horizontal: 'left'},\n gapSx: {ml: `${MENU_GAP_PIXELS + SIDE_GAP_EXTRA_PIXELS}px`},\n };\n }\n if (isInLowerHalf) {\n // la separación se cuenta desde la orilla de la BARRA, no del botón (que va adentro): si no, el menú tocaba la barra\n // la barra de arriba (header) o la de pestañas del teléfono (nav)\n const bar = anchorElement.closest('header, nav') ?? anchorElement;\n const insideBarPixels = Math.max(0, box.top - bar.getBoundingClientRect().top);\n return {\n anchorOrigin: {vertical: 'top', horizontal: 'right'},\n transformOrigin: {vertical: 'bottom', horizontal: 'right'},\n gapSx: {mt: `-${Math.round(insideBarPixels) + MENU_GAP_PIXELS}px`},\n };\n }\n return {\n anchorOrigin: {vertical: 'bottom', horizontal: 'right'},\n transformOrigin: {vertical: 'top', horizontal: 'right'},\n gapSx: {mt: `${MENU_GAP_PIXELS}px`},\n };\n}\n"],"names":[],"mappings":"AAWA,MAAM,kBAAkB;AAExB,MAAM,wBAAwB;AAMvB,SAAS,mBAAmB,eAAe;AAC9C,QAAM,MAAM,iBAAiB,OAAO,WAAW,cAAc,cAAc,sBAAqB,IAAK;AACrG,QAAM,gBAAgB,QAAQ,GAAG,KAAK,IAAI,MAAM,OAAO,cAAc;AAGrE,QAAM,eAAe,QAAQ,GAAG,KAAK,IAAI,QAAQ,OAAO,aAAa;AACrE,MAAI,cAAc;AACd,UAAM,WAAW,gBAAgB,WAAW;AAC5C,WAAO;AAAA,MACH,cAAc,EAAC,UAAU,YAAY,QAAO;AAAA,MAC5C,iBAAiB,EAAC,UAAU,YAAY,OAAM;AAAA,MAC9C,OAAO,EAAC,IAAI,GAAG,kBAAkB,qBAAqB,KAAI;AAAA,IACtE;AAAA,EACI;AACA,MAAI,eAAe;AAGf,UAAM,MAAM,cAAc,QAAQ,aAAa,KAAK;AACpD,UAAM,kBAAkB,KAAK,IAAI,GAAG,IAAI,MAAM,IAAI,sBAAqB,EAAG,GAAG;AAC7E,WAAO;AAAA,MACH,cAAc,EAAC,UAAU,OAAO,YAAY,QAAO;AAAA,MACnD,iBAAiB,EAAC,UAAU,UAAU,YAAY,QAAO;AAAA,MACzD,OAAO,EAAC,IAAI,IAAI,KAAK,MAAM,eAAe,IAAI,eAAe,KAAI;AAAA,IAC7E;AAAA,EACI;AACA,SAAO;AAAA,IACH,cAAc,EAAC,UAAU,UAAU,YAAY,QAAO;AAAA,IACtD,iBAAiB,EAAC,UAAU,OAAO,YAAY,QAAO;AAAA,IACtD,OAAO,EAAC,IAAI,GAAG,eAAe,KAAI;AAAA,EAC1C;AACA;"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
function menuItemLabelOf(menuItem, t) {
|
|
2
|
+
return menuItem.label ?? (menuItem.labelKey ? t(menuItem.labelKey) : "");
|
|
3
|
+
}
|
|
4
|
+
function menuItemDescriptionOf(menuItem, t) {
|
|
5
|
+
return menuItem.description ?? (menuItem.descriptionKey ? t(menuItem.descriptionKey) : void 0);
|
|
6
|
+
}
|
|
7
|
+
function menuItemSectionOf(menuItem, t) {
|
|
8
|
+
return menuItem.section ?? (menuItem.sectionKey ? t(menuItem.sectionKey) : void 0);
|
|
9
|
+
}
|
|
10
|
+
function menuSectionsOf(menuItems, t) {
|
|
11
|
+
const sectionsByTitle = /* @__PURE__ */ new Map();
|
|
12
|
+
menuItems.forEach((menuItem) => {
|
|
13
|
+
const title = menuItemSectionOf(menuItem, t);
|
|
14
|
+
if (!sectionsByTitle.has(title)) {
|
|
15
|
+
sectionsByTitle.set(title, { title, menuItems: [] });
|
|
16
|
+
}
|
|
17
|
+
sectionsByTitle.get(title).menuItems.push(menuItem);
|
|
18
|
+
});
|
|
19
|
+
return [...sectionsByTitle.values()];
|
|
20
|
+
}
|
|
21
|
+
const NAME_PARTICLES = /* @__PURE__ */ new Set(["de", "del", "la", "las", "los", "y", "e", "da", "das", "do", "dos", "di", "du", "van", "von", "der", "le"]);
|
|
22
|
+
function initialsOf(fullName) {
|
|
23
|
+
const words = String(fullName ?? "").trim().split(/\s+/).filter((word) => Boolean(word) && !NAME_PARTICLES.has(word.toLowerCase()));
|
|
24
|
+
return words.slice(0, 2).map((word) => word[0]?.toUpperCase() ?? "").join("") || "?";
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
initialsOf,
|
|
28
|
+
menuItemDescriptionOf,
|
|
29
|
+
menuItemLabelOf,
|
|
30
|
+
menuItemSectionOf,
|
|
31
|
+
menuSectionsOf
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=menuItemText.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menuItemText.js","sources":["../../src/appShell/menuItemText.js"],"sourcesContent":["// Los textos de una entrada del menú y de la persona en la barra, ya listos para pintarse.\n//\n// Una entrada del menú puede traer su texto escrito (label, description, section) o la llave para traducirlo (labelKey,\n// descriptionKey, sectionKey): con llave, cambia de idioma junto con la app.\n//\n// Funciones puras, sin React: function (regla de la casa). Se prueban con node --test (menuItemText.test.js).\n\n/**\n * El nombre de una entrada del menú.\n *\n * @param {{label?: string, labelKey?: string}} menuItem\n * @param {(key: string) => string} t el traductor de la pantalla\n * @returns {string}\n */\nexport function menuItemLabelOf(menuItem, t) {\n return menuItem.label ?? (menuItem.labelKey ? t(menuItem.labelKey) : '');\n}\n\n/**\n * Para qué sirve una entrada (para las tarjetas de un inicio).\n *\n * @param {{description?: string, descriptionKey?: string}} menuItem\n * @param {(key: string) => string} t\n * @returns {string|undefined}\n */\nexport function menuItemDescriptionOf(menuItem, t) {\n return menuItem.description ?? (menuItem.descriptionKey ? t(menuItem.descriptionKey) : undefined);\n}\n\n/**\n * El título de la sección del menú lateral donde va la entrada («Operación», «Administración»).\n *\n * @param {{section?: string, sectionKey?: string}} menuItem\n * @param {(key: string) => string} t\n * @returns {string|undefined}\n */\nexport function menuItemSectionOf(menuItem, t) {\n return menuItem.section ?? (menuItem.sectionKey ? t(menuItem.sectionKey) : undefined);\n}\n\n/**\n * Las entradas juntas por sección: las secciones salen en el orden en que aparece su primera entrada, y adentro cada\n * entrada en su orden. Las entradas sin sección forman su propio bloque sin título.\n *\n * Por qué por título y no por vecindad: con vecindad, dos módulos de la misma sección con un `order` de otra en medio\n * partían la sección en dos («Interfaz» salía dos veces). Así cada módulo dice su sección sin coordinar números.\n *\n * @param {object[]} menuItems lo que regresa composeMenu\n * @param {(key: string) => string} t\n * @returns {Array<{title: string|undefined, menuItems: object[]}>}\n */\nexport function menuSectionsOf(menuItems, t) {\n const sectionsByTitle = new Map();\n menuItems.forEach((menuItem) => {\n const title = menuItemSectionOf(menuItem, t);\n if (!sectionsByTitle.has(title)) {\n sectionsByTitle.set(title, {title, menuItems: []});\n }\n sectionsByTitle.get(title).menuItems.push(menuItem);\n });\n return [...sectionsByTitle.values()];\n}\n\n// las partículas de los nombres («María de la Luz», «Juan van Dijk»): no son iniciales. Con ellas, «Usuario de Ejemplo»\n// salía «UD» en el avatar.\nconst NAME_PARTICLES = new Set(['de', 'del', 'la', 'las', 'los', 'y', 'e', 'da', 'das', 'do', 'dos', 'di', 'du', 'van', 'von', 'der', 'le']);\n\n/**\n * Las iniciales para el avatar: «Ana María López» → «AM», «Usuario de Ejemplo» → «UE». Sin nombre, «?».\n *\n * @param {string|null|undefined} fullName\n * @returns {string}\n */\nexport function initialsOf(fullName) {\n const words = String(fullName ?? '').trim().split(/\\s+/).filter((word) => Boolean(word) && !NAME_PARTICLES.has(word.toLowerCase()));\n return words.slice(0, 2).map((word) => word[0]?.toUpperCase() ?? '').join('') || '?';\n}\n"],"names":[],"mappings":"AAcO,SAAS,gBAAgB,UAAU,GAAG;AACzC,SAAO,SAAS,UAAU,SAAS,WAAW,EAAE,SAAS,QAAQ,IAAI;AACzE;AASO,SAAS,sBAAsB,UAAU,GAAG;AAC/C,SAAO,SAAS,gBAAgB,SAAS,iBAAiB,EAAE,SAAS,cAAc,IAAI;AAC3F;AASO,SAAS,kBAAkB,UAAU,GAAG;AAC3C,SAAO,SAAS,YAAY,SAAS,aAAa,EAAE,SAAS,UAAU,IAAI;AAC/E;AAaO,SAAS,eAAe,WAAW,GAAG;AACzC,QAAM,kBAAkB,oBAAI,IAAG;AAC/B,YAAU,QAAQ,CAAC,aAAa;AAC5B,UAAM,QAAQ,kBAAkB,UAAU,CAAC;AAC3C,QAAI,CAAC,gBAAgB,IAAI,KAAK,GAAG;AAC7B,sBAAgB,IAAI,OAAO,EAAC,OAAO,WAAW,CAAA,EAAE,CAAC;AAAA,IACrD;AACA,oBAAgB,IAAI,KAAK,EAAE,UAAU,KAAK,QAAQ;AAAA,EACtD,CAAC;AACD,SAAO,CAAC,GAAG,gBAAgB,QAAQ;AACvC;AAIA,MAAM,iBAAiB,oBAAI,IAAI,CAAC,MAAM,OAAO,MAAM,OAAO,OAAO,KAAK,KAAK,MAAM,OAAO,MAAM,OAAO,MAAM,MAAM,OAAO,OAAO,OAAO,IAAI,CAAC;AAQpI,SAAS,WAAW,UAAU;AACjC,QAAM,QAAQ,OAAO,YAAY,EAAE,EAAE,KAAI,EAAG,MAAM,KAAK,EAAE,OAAO,CAAC,SAAS,QAAQ,IAAI,KAAK,CAAC,eAAe,IAAI,KAAK,YAAW,CAAE,CAAC;AAClI,SAAO,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,SAAS,KAAK,CAAC,GAAG,iBAAiB,EAAE,EAAE,KAAK,EAAE,KAAK;AACrF;"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useEffect, useContext, useState, useMemo } from "react";
|
|
4
|
+
const PageTitleContext = createContext({
|
|
5
|
+
title: null,
|
|
6
|
+
setTitle: () => {
|
|
7
|
+
},
|
|
8
|
+
isTitleVisible: true,
|
|
9
|
+
setTitleVisible: () => {
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
function PageTitleProvider({ children }) {
|
|
13
|
+
const [title, setTitle] = useState(null);
|
|
14
|
+
const [isTitleVisible, setTitleVisible] = useState(true);
|
|
15
|
+
const value = useMemo(() => ({ title, setTitle, isTitleVisible, setTitleVisible }), [title, isTitleVisible]);
|
|
16
|
+
return /* @__PURE__ */ jsx(PageTitleContext.Provider, { value, children });
|
|
17
|
+
}
|
|
18
|
+
function usePageTitle() {
|
|
19
|
+
return useContext(PageTitleContext);
|
|
20
|
+
}
|
|
21
|
+
function useRegisterPageTitle(title, titleRef) {
|
|
22
|
+
const { setTitle, setTitleVisible } = usePageTitle();
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
setTitle(title ?? null);
|
|
25
|
+
return () => setTitle(null);
|
|
26
|
+
}, [title, setTitle]);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
const titleElement = titleRef.current;
|
|
29
|
+
if (!titleElement || typeof IntersectionObserver === "undefined") {
|
|
30
|
+
return void 0;
|
|
31
|
+
}
|
|
32
|
+
const observer = new IntersectionObserver(([entry]) => setTitleVisible(entry.isIntersecting), { threshold: 0 });
|
|
33
|
+
observer.observe(titleElement);
|
|
34
|
+
return () => {
|
|
35
|
+
observer.disconnect();
|
|
36
|
+
setTitleVisible(true);
|
|
37
|
+
};
|
|
38
|
+
}, [titleRef, setTitleVisible]);
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
PageTitleProvider,
|
|
42
|
+
usePageTitle,
|
|
43
|
+
useRegisterPageTitle
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=pageTitle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pageTitle.js","sources":["../../src/appShell/pageTitle.jsx"],"sourcesContent":["// El título de la pantalla abierta, para la barra de arriba (del marco de walk-ot, como Linear):\n// - en escritorio, la barra enseña el título SOLO cuando el título grande de la página ya salió de la vista al deslizar;\n// - en el teléfono, la barra siempre enseña el título (no hay lugar para un encabezado grande y una barra vacía).\n// PageHeader lo registra solo; AppLayout trae el proveedor. Fuera de AppLayout no pasa nada (el contexto por omisión no\n// hace nada).\n//\n// Proveedor y hooks genéricos del paquete: function (regla de la casa).\nimport {createContext, useContext, useEffect, useMemo, useState} from 'react';\n\nconst PageTitleContext = createContext({\n title: null,\n setTitle: () => {},\n isTitleVisible: true,\n setTitleVisible: () => {},\n});\n\n/**\n * @param {{children: import('react').ReactNode}} props\n */\nexport function PageTitleProvider({children}) {\n const [title, setTitle] = useState(null);\n const [isTitleVisible, setTitleVisible] = useState(true);\n const value = useMemo(() => ({title, setTitle, isTitleVisible, setTitleVisible}), [title, isTitleVisible]);\n return <PageTitleContext.Provider value={value}>{children}</PageTitleContext.Provider>;\n}\n\n/**\n * El título registrado y si se está viendo.\n *\n * @returns {{title: string|null, setTitle: Function, isTitleVisible: boolean, setTitleVisible: Function}}\n */\nexport function usePageTitle() {\n return useContext(PageTitleContext);\n}\n\n/**\n * Registra el título de la página y avisa si su elemento se está viendo (para la barra).\n *\n * @param {string|null|undefined} title\n * @param {{current: Element|null}} titleRef el elemento del título grande\n */\nexport function useRegisterPageTitle(title, titleRef) {\n const {setTitle, setTitleVisible} = usePageTitle();\n\n useEffect(() => {\n setTitle(title ?? null);\n return () => setTitle(null);\n }, [title, setTitle]);\n\n useEffect(() => {\n const titleElement = titleRef.current;\n // guard clause: sin elemento o sin IntersectionObserver (pintando en el servidor) no hay nada que observar\n if (!titleElement || typeof IntersectionObserver === 'undefined') {\n return undefined;\n }\n const observer = new IntersectionObserver(([entry]) => setTitleVisible(entry.isIntersecting), {threshold: 0});\n observer.observe(titleElement);\n return () => {\n observer.disconnect();\n setTitleVisible(true);\n };\n }, [titleRef, setTitleVisible]);\n}\n"],"names":[],"mappings":";;;AASA,MAAM,mBAAmB,cAAc;AAAA,EACnC,OAAO;AAAA,EACP,UAAU,MAAM;AAAA,EAAC;AAAA,EACjB,gBAAgB;AAAA,EAChB,iBAAiB,MAAM;AAAA,EAAC;AAC5B,CAAC;AAKM,SAAS,kBAAkB,EAAC,YAAW;AAC1C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,IAAI;AACvC,QAAM,CAAC,gBAAgB,eAAe,IAAI,SAAS,IAAI;AACvD,QAAM,QAAQ,QAAQ,OAAO,EAAC,OAAO,UAAU,gBAAgB,oBAAmB,CAAC,OAAO,cAAc,CAAC;AACzG,SAAO,oBAAC,iBAAiB,UAAjB,EAA0B,OAAe,SAAA,CAAS;AAC9D;AAOO,SAAS,eAAe;AAC3B,SAAO,WAAW,gBAAgB;AACtC;AAQO,SAAS,qBAAqB,OAAO,UAAU;AAClD,QAAM,EAAC,UAAU,gBAAA,IAAmB,aAAA;AAEpC,YAAU,MAAM;AACZ,aAAS,SAAS,IAAI;AACtB,WAAO,MAAM,SAAS,IAAI;AAAA,EAC9B,GAAG,CAAC,OAAO,QAAQ,CAAC;AAEpB,YAAU,MAAM;AACZ,UAAM,eAAe,SAAS;AAE9B,QAAI,CAAC,gBAAgB,OAAO,yBAAyB,aAAa;AAC9D,aAAO;AAAA,IACX;AACA,UAAM,WAAW,IAAI,qBAAqB,CAAC,CAAC,KAAK,MAAM,gBAAgB,MAAM,cAAc,GAAG,EAAC,WAAW,GAAE;AAC5G,aAAS,QAAQ,YAAY;AAC7B,WAAO,MAAM;AACT,eAAS,WAAA;AACT,sBAAgB,IAAI;AAAA,IACxB;AAAA,EACJ,GAAG,CAAC,UAAU,eAAe,CAAC;AAClC;"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { GLASS_INSET_PIXELS } from "../theme/glassSurface.js";
|
|
2
|
+
const MAIN_CONTENT_ID = "main-content";
|
|
3
|
+
const DRAWER_WIDTH_EXPANDED = 240;
|
|
4
|
+
const DRAWER_WIDTH_COLLAPSED = 64;
|
|
5
|
+
const APP_BAR_HEIGHT_PIXELS = 56;
|
|
6
|
+
const GLASS_PANEL_GAP_PIXELS = GLASS_INSET_PIXELS;
|
|
7
|
+
const PHONE_MEDIA_QUERY = "@media (max-width: 899.95px), (max-height: 499.95px)";
|
|
8
|
+
const DESKTOP_MEDIA_QUERY = "@media (min-width: 900px) and (min-height: 500px)";
|
|
9
|
+
const PHONE_LANDSCAPE_MEDIA_QUERY = "@media (max-height: 499.95px)";
|
|
10
|
+
const MOBILE_TAB_BAR_HEIGHT_PIXELS = Object.freeze({ portrait: 60, landscape: 46 });
|
|
11
|
+
const FLOATING_BOTTOM_SPACE_CSS_VARIABLE = "--calcita-floating-bottom-space";
|
|
12
|
+
function aboveMobileTabBarOf(gapPixels) {
|
|
13
|
+
return {
|
|
14
|
+
[PHONE_MEDIA_QUERY]: {
|
|
15
|
+
top: "auto",
|
|
16
|
+
bottom: `calc(${GLASS_PANEL_GAP_PIXELS + MOBILE_TAB_BAR_HEIGHT_PIXELS.portrait + gapPixels}px + env(safe-area-inset-bottom))`
|
|
17
|
+
},
|
|
18
|
+
[PHONE_LANDSCAPE_MEDIA_QUERY]: {
|
|
19
|
+
bottom: `calc(${GLASS_PANEL_GAP_PIXELS + MOBILE_TAB_BAR_HEIGHT_PIXELS.landscape + gapPixels}px + env(safe-area-inset-bottom))`
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function drawerTransitionOf(theme, properties = ["width"]) {
|
|
24
|
+
return theme.transitions.create(properties, { easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.enteringScreen });
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
APP_BAR_HEIGHT_PIXELS,
|
|
28
|
+
DESKTOP_MEDIA_QUERY,
|
|
29
|
+
DRAWER_WIDTH_COLLAPSED,
|
|
30
|
+
DRAWER_WIDTH_EXPANDED,
|
|
31
|
+
FLOATING_BOTTOM_SPACE_CSS_VARIABLE,
|
|
32
|
+
GLASS_PANEL_GAP_PIXELS,
|
|
33
|
+
MAIN_CONTENT_ID,
|
|
34
|
+
MOBILE_TAB_BAR_HEIGHT_PIXELS,
|
|
35
|
+
PHONE_LANDSCAPE_MEDIA_QUERY,
|
|
36
|
+
PHONE_MEDIA_QUERY,
|
|
37
|
+
aboveMobileTabBarOf,
|
|
38
|
+
drawerTransitionOf
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=shellSizes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellSizes.js","sources":["../../src/appShell/shellSizes.js"],"sourcesContent":["// Las medidas y tiempos del marco de la app (AppLayout, del marco de walk-ot), en un solo lugar para que el menú, la barra y\n// el botón flotante se muevan juntos.\n//\n// Funciones puras, sin React: function (regla de la casa).\nimport {GLASS_INSET_PIXELS} from '@/theme/glassSurface.js';\n\n/** El id del contenido: a donde lleva «Saltar al contenido». */\nexport const MAIN_CONTENT_ID = 'main-content';\n\n/** El menú lateral abierto (ícono y nombre; 240 como las plantillas de MUI) y encogido (solo íconos, el rail). */\nexport const DRAWER_WIDTH_EXPANDED = 240;\nexport const DRAWER_WIDTH_COLLAPSED = 64;\n\n/** El alto de la barra de arriba (sin avisos). */\nexport const APP_BAR_HEIGHT_PIXELS = 56;\n\n/**\n * Con vidrio (createToolkitTheme({glass: true})), el menú lateral y la barra flotan separados de la orilla de la ventana\n * y entre ellos, como los paneles de macOS 26: así el contenido pasa por detrás y el vidrio tiene qué desenfocar. Es la\n * misma separación que el tema les da a los cajones y a la hoja de abajo (GLASS_INSET_PIXELS), para que todo flote igual.\n */\nexport const GLASS_PANEL_GAP_PIXELS = GLASS_INSET_PIXELS;\n\n/**\n * Teléfono o escritorio. Teléfono: angosto (menos de 900 px, el «md» de MUI) O bajito (menos de 500 px de alto: un teléfono\n * acostado). Solo con el ancho, un iPhone Pro Max acostado (932 × 430) salía con el marco de escritorio y su menú lateral\n * no cabía (lo reportaron). Van como media queries para usarse en sx: [PHONE_MEDIA_QUERY]: {...}.\n */\nexport const PHONE_MEDIA_QUERY = '@media (max-width: 899.95px), (max-height: 499.95px)';\nexport const DESKTOP_MEDIA_QUERY = '@media (min-width: 900px) and (min-height: 500px)';\n/** El teléfono acostado: la barra de pestañas va compacta (ícono y nombre lado a lado) para dejarle el alto al contenido. */\nexport const PHONE_LANDSCAPE_MEDIA_QUERY = '@media (max-height: 499.95px)';\n\n/** La barra de pestañas del teléfono con vidrio (MobileTabBar): su alto parado y acostado. */\nexport const MOBILE_TAB_BAR_HEIGHT_PIXELS = Object.freeze({portrait: 60, landscape: 46});\n\n// Lo que flota abajo encima de la barra de pestañas y dura un rato (las acciones de los elegidos de una tabla) pide su alto\n// aquí mientras se ve: el marco lo suma al espacio de abajo del contenido y el final de la página (el paginador) no queda\n// tapado. Lo pone quien flota con GlobalStyles; sin nada, vale 0.\nexport const FLOATING_BOTTOM_SPACE_CSS_VARIABLE = '--calcita-floating-bottom-space';\n\n/**\n * Lo que flota abajo al centro en el teléfono con vidrio (el aviso de versión nueva, la invitación a instalar): encima de\n * la barra de pestañas, con la separación de la barra a la orilla, su alto, la separación pedida y la zona del gesto de\n * inicio del iPhone. Para el sx: ...aboveMobileTabBarOf(8).\n *\n * @param {number} gapPixels lo que se separa de la barra de pestañas (px)\n * @returns {object}\n */\nexport function aboveMobileTabBarOf(gapPixels) {\n return {\n [PHONE_MEDIA_QUERY]: {\n top: 'auto',\n bottom: `calc(${GLASS_PANEL_GAP_PIXELS + MOBILE_TAB_BAR_HEIGHT_PIXELS.portrait + gapPixels}px + env(safe-area-inset-bottom))`,\n },\n [PHONE_LANDSCAPE_MEDIA_QUERY]: {\n bottom: `calc(${GLASS_PANEL_GAP_PIXELS + MOBILE_TAB_BAR_HEIGHT_PIXELS.landscape + gapPixels}px + env(safe-area-inset-bottom))`,\n },\n };\n}\n\n/**\n * La transición que comparten el menú, la barra y el botón flotante: si cada uno usara la suya, terminarían en frames\n * distintos y el ojo lo lee como un salto.\n *\n * @param {object} theme el tema de MUI\n * @param {string[]} [properties] lo que se anima\n * @returns {string}\n */\nexport function drawerTransitionOf(theme, properties = ['width']) {\n return theme.transitions.create(properties, {easing: theme.transitions.easing.sharp, duration: theme.transitions.duration.enteringScreen});\n}\n"],"names":[],"mappings":";AAOY,MAAC,kBAAkB;AAGnB,MAAC,wBAAwB;AACzB,MAAC,yBAAyB;AAG1B,MAAC,wBAAwB;AAOzB,MAAC,yBAAyB;AAO1B,MAAC,oBAAoB;AACrB,MAAC,sBAAsB;AAEvB,MAAC,8BAA8B;AAG/B,MAAC,+BAA+B,OAAO,OAAO,EAAC,UAAU,IAAI,WAAW,GAAE,CAAC;AAK3E,MAAC,qCAAqC;AAU3C,SAAS,oBAAoB,WAAW;AAC3C,SAAO;AAAA,IACH,CAAC,iBAAiB,GAAG;AAAA,MACjB,KAAK;AAAA,MACL,QAAQ,QAAQ,yBAAyB,6BAA6B,WAAW,SAAS;AAAA,IACtG;AAAA,IACQ,CAAC,2BAA2B,GAAG;AAAA,MAC3B,QAAQ,QAAQ,yBAAyB,6BAA6B,YAAY,SAAS;AAAA,IACvG;AAAA,EACA;AACA;AAUO,SAAS,mBAAmB,OAAO,aAAa,CAAC,OAAO,GAAG;AAC9D,SAAO,MAAM,YAAY,OAAO,YAAY,EAAC,QAAQ,MAAM,YAAY,OAAO,OAAO,UAAU,MAAM,YAAY,SAAS,eAAc,CAAC;AAC7I;"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { THEME_LOOK, TOP_BAR } from "../theme/createToolkitTheme.js";
|
|
2
|
+
import { isGlassTheme } from "../theme/glassSurface.js";
|
|
3
|
+
function usesMobileTabBar(theme) {
|
|
4
|
+
if (isGlassTheme(theme)) {
|
|
5
|
+
return true;
|
|
6
|
+
}
|
|
7
|
+
return theme.toolkit?.look === THEME_LOOK.minimal && theme.toolkit?.bar === TOP_BAR.capsules;
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
usesMobileTabBar
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=tabBarRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tabBarRule.js","sources":["../../src/appShell/tabBarRule.js"],"sourcesContent":["// Si el teléfono lleva la barra de pestañas de abajo (MobileTabBar, como iOS 26) en lugar de la barra de arriba con la ☰\n// y el cajón: con vidrio siempre, y con el minimalista cuando la barra va en cápsulas (lo pidió el autor: «el mínimo con\n// cápsulas también, con el comportamiento de vidrio en el menú»). Con el minimalista y la franja, la barra de arriba de\n// siempre (estilo Material).\n//\n// Un solo lugar para la regla: la usan el marco (AppLayout) y lo que flota encima de esa barra (la invitación a instalar,\n// el aviso de versión nueva), que tienen que saber si hay barra abajo para no taparla.\n//\n// Funciones puras, no renderizan: function (regla de la casa).\nimport {THEME_LOOK, TOP_BAR} from '@/theme/createToolkitTheme.js';\nimport {isGlassTheme} from '@/theme/glassSurface.js';\n\n/**\n * @param {object} theme el tema de MUI\n * @returns {boolean}\n */\nexport function usesMobileTabBar(theme) {\n if (isGlassTheme(theme)) {\n return true;\n }\n return theme.toolkit?.look === THEME_LOOK.minimal && theme.toolkit?.bar === TOP_BAR.capsules;\n}\n"],"names":[],"mappings":";;AAgBO,SAAS,iBAAiB,OAAO;AACpC,MAAI,aAAa,KAAK,GAAG;AACrB,WAAO;AAAA,EACX;AACA,SAAO,MAAM,SAAS,SAAS,WAAW,WAAW,MAAM,SAAS,QAAQ,QAAQ;AACxF;"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const MINIMIZE_AFTER_PIXELS = 24;
|
|
2
|
+
const ALWAYS_EXPANDED_UNTIL_PIXELS = 60;
|
|
3
|
+
const TAB_BAR_SCROLL_START = Object.freeze({ isMinimized: false, lastY: 0, travel: 0 });
|
|
4
|
+
function tabBarStateAfterScroll(state, scrollY) {
|
|
5
|
+
const delta = scrollY - state.lastY;
|
|
6
|
+
const travel = Math.sign(delta) === Math.sign(state.travel) ? state.travel + delta : delta;
|
|
7
|
+
let isMinimized = state.isMinimized;
|
|
8
|
+
if (scrollY <= ALWAYS_EXPANDED_UNTIL_PIXELS) {
|
|
9
|
+
isMinimized = false;
|
|
10
|
+
} else if (travel >= MINIMIZE_AFTER_PIXELS) {
|
|
11
|
+
isMinimized = true;
|
|
12
|
+
} else if (travel <= -12) {
|
|
13
|
+
isMinimized = false;
|
|
14
|
+
}
|
|
15
|
+
return { isMinimized, lastY: scrollY, travel };
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
ALWAYS_EXPANDED_UNTIL_PIXELS,
|
|
19
|
+
MINIMIZE_AFTER_PIXELS,
|
|
20
|
+
TAB_BAR_SCROLL_START,
|
|
21
|
+
tabBarStateAfterScroll
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=tabBarScroll.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tabBarScroll.js","sources":["../../src/appShell/tabBarScroll.js"],"sourcesContent":["// Cuándo se encoge la barra de pestañas del teléfono (MobileTabBar), como la de iOS 26: al leer hacia abajo se vuelve una\n// cápsula chica con la pestaña donde está la persona, y en cuanto sube un poco regresa completa.\n//\n// - No cuenta cada evento de deslizar sino lo recorrido en la misma dirección: el navegador avisa de a 1 a 3 px y, si\n// se comparara evento contra evento, nunca pasaría del umbral.\n// - Cerca de arriba siempre va completa: ahí todavía no hay nada que leer debajo.\n//\n// Funciones puras, no renderizan: function (regla de la casa). Pruebas en tabBarScroll.test.js; el hook que las usa es\n// useTabBarMinimized.js.\n\n// lo que hay que bajar seguido para encogerla y subir para que regrese (px); subir regresa más rápido, como en iOS\nexport const MINIMIZE_AFTER_PIXELS = 24;\nexport const EXPAND_AFTER_PIXELS = 12;\n// arriba de esto siempre va completa (px): lo alto de la barra\nexport const ALWAYS_EXPANDED_UNTIL_PIXELS = 60;\n\n/** Al abrir la pantalla: completa, arriba y sin recorrido. */\nexport const TAB_BAR_SCROLL_START = Object.freeze({isMinimized: false, lastY: 0, travel: 0});\n\n/**\n * El estado de la barra después de que la página se deslizó a scrollY.\n *\n * @param {{isMinimized: boolean, lastY: number, travel: number}} state travel: lo recorrido en la dirección de ahorita\n * (positivo hacia abajo)\n * @param {number} scrollY cuánto está deslizada la página (window.scrollY)\n * @returns {{isMinimized: boolean, lastY: number, travel: number}}\n */\nexport function tabBarStateAfterScroll(state, scrollY) {\n const delta = scrollY - state.lastY;\n // si cambió de dirección, lo recorrido empieza de nuevo\n const travel = Math.sign(delta) === Math.sign(state.travel) ? state.travel + delta : delta;\n\n let isMinimized = state.isMinimized;\n if (scrollY <= ALWAYS_EXPANDED_UNTIL_PIXELS) {\n isMinimized = false;\n } else if (travel >= MINIMIZE_AFTER_PIXELS) {\n isMinimized = true;\n } else if (travel <= -EXPAND_AFTER_PIXELS) {\n isMinimized = false;\n }\n return {isMinimized, lastY: scrollY, travel};\n}\n"],"names":[],"mappings":"AAWY,MAAC,wBAAwB;AAGzB,MAAC,+BAA+B;AAGhC,MAAC,uBAAuB,OAAO,OAAO,EAAC,aAAa,OAAO,OAAO,GAAG,QAAQ,EAAC,CAAC;AAUpF,SAAS,uBAAuB,OAAO,SAAS;AACnD,QAAM,QAAQ,UAAU,MAAM;AAE9B,QAAM,SAAS,KAAK,KAAK,KAAK,MAAM,KAAK,KAAK,MAAM,MAAM,IAAI,MAAM,SAAS,QAAQ;AAErF,MAAI,cAAc,MAAM;AACxB,MAAI,WAAW,8BAA8B;AACzC,kBAAc;AAAA,EAClB,WAAW,UAAU,uBAAuB;AACxC,kBAAc;AAAA,EAClB,WAAW,UAAU,KAAsB;AACvC,kBAAc;AAAA,EAClB;AACA,SAAO,EAAC,aAAa,OAAO,SAAS,OAAM;AAC/C;"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState, useCallback, useEffect, useLayoutEffect } from "react";
|
|
3
|
+
const STORAGE_KEY = "calcita:drawerCollapsed";
|
|
4
|
+
const useBrowserLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
|
|
5
|
+
function useDrawerCollapsed(defaultCollapsed = false) {
|
|
6
|
+
const [collapsed, setCollapsed] = useState(defaultCollapsed);
|
|
7
|
+
useBrowserLayoutEffect(() => {
|
|
8
|
+
try {
|
|
9
|
+
const storedValue = window.localStorage.getItem(STORAGE_KEY);
|
|
10
|
+
if (storedValue === "true" || storedValue === "false") {
|
|
11
|
+
setCollapsed(storedValue === "true");
|
|
12
|
+
}
|
|
13
|
+
} catch {
|
|
14
|
+
}
|
|
15
|
+
}, []);
|
|
16
|
+
const remember = useCallback((nextCollapsed) => {
|
|
17
|
+
setCollapsed(nextCollapsed);
|
|
18
|
+
try {
|
|
19
|
+
window.localStorage.setItem(STORAGE_KEY, String(nextCollapsed));
|
|
20
|
+
} catch {
|
|
21
|
+
}
|
|
22
|
+
}, []);
|
|
23
|
+
const toggle = useCallback(() => remember(!collapsed), [collapsed, remember]);
|
|
24
|
+
return { collapsed, toggle };
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
useDrawerCollapsed
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=useDrawerCollapsed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDrawerCollapsed.js","sources":["../../src/appShell/useDrawerCollapsed.js"],"sourcesContent":["// Si el menú lateral está encogido (solo íconos), recordado en este navegador (del marco de walk-ot).\n//\n// - La preferencia se lee ANTES del primer pintado del navegador (useLayoutEffect): sin eso, el menú brinca del valor por\n// omisión al que la persona dejó.\n// - En el teléfono no aplica: ahí el menú es un cajón que se abre con la hamburguesa (AppLayout lo elige con CSS).\n// - Sin almacenamiento (ventana privada estricta) se usa el valor por omisión, sin tronar.\n//\n// Hook genérico del paquete: function (regla de la casa).\nimport {useCallback, useEffect, useLayoutEffect, useState} from 'react';\n\nconst STORAGE_KEY = 'calcita:drawerCollapsed';\n// en el servidor useLayoutEffect avisa en consola; ahí no hay nada que leer\nconst useBrowserLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;\n\n/**\n * @param {boolean} [defaultCollapsed]\n * @returns {{collapsed: boolean, toggle: () => void}}\n */\nexport function useDrawerCollapsed(defaultCollapsed = false) {\n const [collapsed, setCollapsed] = useState(defaultCollapsed);\n\n useBrowserLayoutEffect(() => {\n try {\n const storedValue = window.localStorage.getItem(STORAGE_KEY);\n if (storedValue === 'true' || storedValue === 'false') {\n setCollapsed(storedValue === 'true');\n }\n } catch {\n // almacenamiento bloqueado: se queda el valor por omisión\n }\n }, []);\n\n const remember = useCallback((nextCollapsed) => {\n setCollapsed(nextCollapsed);\n try {\n window.localStorage.setItem(STORAGE_KEY, String(nextCollapsed));\n } catch {\n // almacenamiento bloqueado: cambia igual, solo no se recuerda\n }\n }, []);\n\n const toggle = useCallback(() => remember(!collapsed), [collapsed, remember]);\n\n return {collapsed, toggle};\n}\n"],"names":[],"mappings":";;AAUA,MAAM,cAAc;AAEpB,MAAM,yBAAyB,OAAO,WAAW,cAAc,YAAY;AAMpE,SAAS,mBAAmB,mBAAmB,OAAO;AACzD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,gBAAgB;AAE3D,yBAAuB,MAAM;AACzB,QAAI;AACA,YAAM,cAAc,OAAO,aAAa,QAAQ,WAAW;AAC3D,UAAI,gBAAgB,UAAU,gBAAgB,SAAS;AACnD,qBAAa,gBAAgB,MAAM;AAAA,MACvC;AAAA,IACJ,QAAQ;AAAA,IAER;AAAA,EACJ,GAAG,CAAA,CAAE;AAEL,QAAM,WAAW,YAAY,CAAC,kBAAkB;AAC5C,iBAAa,aAAa;AAC1B,QAAI;AACA,aAAO,aAAa,QAAQ,aAAa,OAAO,aAAa,CAAC;AAAA,IAClE,QAAQ;AAAA,IAER;AAAA,EACJ,GAAG,CAAA,CAAE;AAEL,QAAM,SAAS,YAAY,MAAM,SAAS,CAAC,SAAS,GAAG,CAAC,WAAW,QAAQ,CAAC;AAE5E,SAAO,EAAC,WAAW,OAAM;AAC7B;"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState, useLayoutEffect } from "react";
|
|
3
|
+
import { BAR_CAPSULE_HEIGHT_PIXELS } from "./BarCapsule.js";
|
|
4
|
+
const FALLBACK_BUTTON_PIXELS = 40;
|
|
5
|
+
const pixelsOf = (value) => Number.parseFloat(value) || 0;
|
|
6
|
+
const goesBefore = (sibling, capsule) => {
|
|
7
|
+
const siblingOrder = pixelsOf(window.getComputedStyle(sibling).order);
|
|
8
|
+
const capsuleOrder = pixelsOf(window.getComputedStyle(capsule).order);
|
|
9
|
+
if (siblingOrder !== capsuleOrder) {
|
|
10
|
+
return siblingOrder < capsuleOrder;
|
|
11
|
+
}
|
|
12
|
+
return Boolean(sibling.compareDocumentPosition(capsule) & Node.DOCUMENT_POSITION_FOLLOWING);
|
|
13
|
+
};
|
|
14
|
+
const occupiedWidthOf = (sibling) => pixelsOf(window.getComputedStyle(sibling).flexGrow) > 0 ? BAR_CAPSULE_HEIGHT_PIXELS : sibling.getBoundingClientRect().width;
|
|
15
|
+
function useFittingActionCount(slot, capsule, actionCount) {
|
|
16
|
+
const [visibleCount, setVisibleCount] = useState(actionCount);
|
|
17
|
+
useLayoutEffect(() => {
|
|
18
|
+
if (!slot || !capsule) {
|
|
19
|
+
setVisibleCount(actionCount);
|
|
20
|
+
return void 0;
|
|
21
|
+
}
|
|
22
|
+
const measure = () => {
|
|
23
|
+
const rowGap = pixelsOf(window.getComputedStyle(slot).columnGap);
|
|
24
|
+
const siblingsBefore = [...slot.children].filter((sibling) => sibling !== capsule && goesBefore(sibling, capsule));
|
|
25
|
+
const takenBefore = siblingsBefore.reduce((total, sibling) => total + occupiedWidthOf(sibling) + rowGap, 0);
|
|
26
|
+
const freeWidth = slot.clientWidth - takenBefore;
|
|
27
|
+
const capsuleStyle = window.getComputedStyle(capsule);
|
|
28
|
+
const padding = pixelsOf(capsuleStyle.paddingLeft) + pixelsOf(capsuleStyle.paddingRight);
|
|
29
|
+
const buttonGap = pixelsOf(capsuleStyle.columnGap);
|
|
30
|
+
const buttonWidth = capsule.firstElementChild?.getBoundingClientRect().width || FALLBACK_BUTTON_PIXELS;
|
|
31
|
+
const fitting = Math.max(1, Math.floor((freeWidth - padding + buttonGap) / (buttonWidth + buttonGap)));
|
|
32
|
+
setVisibleCount(fitting >= actionCount ? actionCount : fitting - 1);
|
|
33
|
+
};
|
|
34
|
+
measure();
|
|
35
|
+
const observer = new ResizeObserver(measure);
|
|
36
|
+
observer.observe(slot);
|
|
37
|
+
[...slot.children].forEach((sibling) => observer.observe(sibling));
|
|
38
|
+
return () => observer.disconnect();
|
|
39
|
+
}, [slot, capsule, actionCount]);
|
|
40
|
+
return Math.min(visibleCount, actionCount);
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
useFittingActionCount as default
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=useFittingActionCount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFittingActionCount.js","sources":["../../src/appShell/useFittingActionCount.js"],"sourcesContent":["// En el teléfono, cuántos botones de un grupo de acciones (BarActions) caben en el renglón que flota arriba. Lo que no cabe\n// va a un menú «⋯» (guía de Apple, Toolbars: «Create a More menu to include additional items»); si caben todos, no hay «⋯».\n//\n// Cómo se reparte el renglón: los grupos que van ANTES (el de `order` menor, y con el mismo order el que se escribió\n// primero) tienen preferencia; este grupo usa lo que sobra. Así, si no cabe todo, el último grupo es el que manda sus\n// botones al «⋯», y la cuenta no da vueltas: lo de antes no depende de lo de después.\n//\n// OJO: no se mide el ancho de la propia cápsula para decidir (cambia al esconder botones y la cuenta daría vueltas sin fin);\n// se mide el renglón y lo que ocupan los de antes. Un grupo que se estira (el buscador abierto, con flex-grow) cuenta como\n// la lupa chica: si no, al abrir el buscador las acciones se irían al «⋯».\n//\n// Gancho del paquete; no renderiza.\nimport {useLayoutEffect, useState} from 'react';\n\nimport {BAR_CAPSULE_HEIGHT_PIXELS} from '@/appShell/BarCapsule.jsx';\n\n// si todavía no hay botones que medir: lo que mide un IconButton de MUI\nconst FALLBACK_BUTTON_PIXELS = 40;\n\nconst pixelsOf = (value) => Number.parseFloat(value) || 0;\n\n/** ¿El hermano va antes que la cápsula en el renglón? (por su `order` de CSS y, si empatan, por cómo están escritos) */\nconst goesBefore = (sibling, capsule) => {\n const siblingOrder = pixelsOf(window.getComputedStyle(sibling).order);\n const capsuleOrder = pixelsOf(window.getComputedStyle(capsule).order);\n if (siblingOrder !== capsuleOrder) {\n return siblingOrder < capsuleOrder;\n }\n return Boolean(sibling.compareDocumentPosition(capsule) & Node.DOCUMENT_POSITION_FOLLOWING);\n};\n\n/** Lo que ocupa un hermano en el renglón; el que se estira (buscador abierto) cuenta como la lupa chica. */\nconst occupiedWidthOf = (sibling) => (\n pixelsOf(window.getComputedStyle(sibling).flexGrow) > 0 ? BAR_CAPSULE_HEIGHT_PIXELS : sibling.getBoundingClientRect().width\n);\n\n/**\n * @param {Element|null} slot el renglón flotante del teléfono (null: no se mide y se ven todos)\n * @param {HTMLElement|null} capsule la cápsula de este grupo\n * @param {number} actionCount cuántos botones trae el grupo\n * @returns {number} cuántos se ven como ícono; si es menor que actionCount, los demás van al «⋯»\n */\nexport default function useFittingActionCount(slot, capsule, actionCount) {\n const [visibleCount, setVisibleCount] = useState(actionCount);\n\n // antes de pintar (layout effect): así nunca se ve el renglón saliéndose de la pantalla\n useLayoutEffect(() => {\n if (!slot || !capsule) {\n setVisibleCount(actionCount);\n return undefined;\n }\n const measure = () => {\n const rowGap = pixelsOf(window.getComputedStyle(slot).columnGap);\n const siblingsBefore = [...slot.children].filter((sibling) => sibling !== capsule && goesBefore(sibling, capsule));\n const takenBefore = siblingsBefore.reduce((total, sibling) => total + occupiedWidthOf(sibling) + rowGap, 0);\n const freeWidth = slot.clientWidth - takenBefore;\n\n const capsuleStyle = window.getComputedStyle(capsule);\n const padding = pixelsOf(capsuleStyle.paddingLeft) + pixelsOf(capsuleStyle.paddingRight);\n const buttonGap = pixelsOf(capsuleStyle.columnGap);\n const buttonWidth = capsule.firstElementChild?.getBoundingClientRect().width || FALLBACK_BUTTON_PIXELS;\n // cuántos botones caben: relleno + n botones + (n - 1) huecos <= lo libre\n const fitting = Math.max(1, Math.floor((freeWidth - padding + buttonGap) / (buttonWidth + buttonGap)));\n // si no caben todos, uno de esos lugares es para el «⋯»\n setVisibleCount(fitting >= actionCount ? actionCount : fitting - 1);\n };\n measure();\n // se vuelve a medir al girar el teléfono o cuando cambia lo que ocupan los de antes\n const observer = new ResizeObserver(measure);\n observer.observe(slot);\n [...slot.children].forEach((sibling) => observer.observe(sibling));\n return () => observer.disconnect();\n }, [slot, capsule, actionCount]);\n\n return Math.min(visibleCount, actionCount);\n}\n"],"names":[],"mappings":";;;AAiBA,MAAM,yBAAyB;AAE/B,MAAM,WAAW,CAAC,UAAU,OAAO,WAAW,KAAK,KAAK;AAGxD,MAAM,aAAa,CAAC,SAAS,YAAY;AACrC,QAAM,eAAe,SAAS,OAAO,iBAAiB,OAAO,EAAE,KAAK;AACpE,QAAM,eAAe,SAAS,OAAO,iBAAiB,OAAO,EAAE,KAAK;AACpE,MAAI,iBAAiB,cAAc;AAC/B,WAAO,eAAe;AAAA,EAC1B;AACA,SAAO,QAAQ,QAAQ,wBAAwB,OAAO,IAAI,KAAK,2BAA2B;AAC9F;AAGA,MAAM,kBAAkB,CAAC,YACrB,SAAS,OAAO,iBAAiB,OAAO,EAAE,QAAQ,IAAI,IAAI,4BAA4B,QAAQ,wBAAwB;AAS3G,SAAS,sBAAsB,MAAM,SAAS,aAAa;AACtE,QAAM,CAAC,cAAc,eAAe,IAAI,SAAS,WAAW;AAG5D,kBAAgB,MAAM;AAClB,QAAI,CAAC,QAAQ,CAAC,SAAS;AACnB,sBAAgB,WAAW;AAC3B,aAAO;AAAA,IACX;AACA,UAAM,UAAU,MAAM;AAClB,YAAM,SAAS,SAAS,OAAO,iBAAiB,IAAI,EAAE,SAAS;AAC/D,YAAM,iBAAiB,CAAC,GAAG,KAAK,QAAQ,EAAE,OAAO,CAAC,YAAY,YAAY,WAAW,WAAW,SAAS,OAAO,CAAC;AACjH,YAAM,cAAc,eAAe,OAAO,CAAC,OAAO,YAAY,QAAQ,gBAAgB,OAAO,IAAI,QAAQ,CAAC;AAC1G,YAAM,YAAY,KAAK,cAAc;AAErC,YAAM,eAAe,OAAO,iBAAiB,OAAO;AACpD,YAAM,UAAU,SAAS,aAAa,WAAW,IAAI,SAAS,aAAa,YAAY;AACvF,YAAM,YAAY,SAAS,aAAa,SAAS;AACjD,YAAM,cAAc,QAAQ,mBAAmB,sBAAqB,EAAG,SAAS;AAEhF,YAAM,UAAU,KAAK,IAAI,GAAG,KAAK,OAAO,YAAY,UAAU,cAAc,cAAc,UAAU,CAAC;AAErG,sBAAgB,WAAW,cAAc,cAAc,UAAU,CAAC;AAAA,IACtE;AACA,YAAO;AAEP,UAAM,WAAW,IAAI,eAAe,OAAO;AAC3C,aAAS,QAAQ,IAAI;AACrB,KAAC,GAAG,KAAK,QAAQ,EAAE,QAAQ,CAAC,YAAY,SAAS,QAAQ,OAAO,CAAC;AACjE,WAAO,MAAM,SAAS,WAAU;AAAA,EACpC,GAAG,CAAC,MAAM,SAAS,WAAW,CAAC;AAE/B,SAAO,KAAK,IAAI,cAAc,WAAW;AAC7C;"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState, useCallback, useEffect, useLayoutEffect } from "react";
|
|
3
|
+
const STORAGE_KEY = "calcita:mobileTabs";
|
|
4
|
+
const useBrowserLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
|
|
5
|
+
function usePinnedMobileTabs() {
|
|
6
|
+
const [pinnedKeys, setStoredKeys] = useState(null);
|
|
7
|
+
useBrowserLayoutEffect(() => {
|
|
8
|
+
try {
|
|
9
|
+
const stored = JSON.parse(window.localStorage.getItem(STORAGE_KEY) ?? "null");
|
|
10
|
+
if (Array.isArray(stored) && stored.every((key) => typeof key === "string")) {
|
|
11
|
+
setStoredKeys(stored);
|
|
12
|
+
}
|
|
13
|
+
} catch {
|
|
14
|
+
}
|
|
15
|
+
}, []);
|
|
16
|
+
const setPinnedKeys = useCallback((keys) => {
|
|
17
|
+
setStoredKeys(keys);
|
|
18
|
+
try {
|
|
19
|
+
if (keys) {
|
|
20
|
+
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(keys));
|
|
21
|
+
} else {
|
|
22
|
+
window.localStorage.removeItem(STORAGE_KEY);
|
|
23
|
+
}
|
|
24
|
+
} catch {
|
|
25
|
+
}
|
|
26
|
+
}, []);
|
|
27
|
+
return { pinnedKeys, setPinnedKeys };
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
usePinnedMobileTabs
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=usePinnedMobileTabs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePinnedMobileTabs.js","sources":["../../src/appShell/usePinnedMobileTabs.js"],"sourcesContent":["// Las pestañas que la persona fijó en la barra del teléfono (desde «Más» → «Editar la barra»), recordadas en este\n// navegador. La guía de Apple para las barras de pestañas pide dejar que cada quien la acomode a su gusto.\n//\n// - Se lee ANTES del primer pintado (useLayoutEffect): sin eso, la barra brinca de las del proyecto a las suyas.\n// - null = no ha elegido: van las que marca el proyecto (mobileTab en menu.js).\n// - Sin almacenamiento (ventana privada estricta) cambia igual, solo no se recuerda.\n//\n// Hook genérico del paquete: function (regla de la casa).\nimport {useCallback, useEffect, useLayoutEffect, useState} from 'react';\n\nconst STORAGE_KEY = 'calcita:mobileTabs';\n// en el servidor useLayoutEffect avisa en consola; ahí no hay nada que leer\nconst useBrowserLayoutEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;\n\n/**\n * @returns {{pinnedKeys: string[]|null, setPinnedKeys: (keys: string[]|null) => void}} las llaves son menuItemKeyOf\n */\nexport function usePinnedMobileTabs() {\n const [pinnedKeys, setStoredKeys] = useState(null);\n\n useBrowserLayoutEffect(() => {\n try {\n const stored = JSON.parse(window.localStorage.getItem(STORAGE_KEY) ?? 'null');\n // algo editado a mano o de otra versión: se ignora\n if (Array.isArray(stored) && stored.every((key) => typeof key === 'string')) {\n setStoredKeys(stored);\n }\n } catch {\n // almacenamiento bloqueado o texto que no es JSON: van las del proyecto\n }\n }, []);\n\n const setPinnedKeys = useCallback((keys) => {\n setStoredKeys(keys);\n try {\n if (keys) {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(keys));\n } else {\n window.localStorage.removeItem(STORAGE_KEY);\n }\n } catch {\n // almacenamiento bloqueado: cambia igual, solo no se recuerda\n }\n }, []);\n\n return {pinnedKeys, setPinnedKeys};\n}\n"],"names":[],"mappings":";;AAUA,MAAM,cAAc;AAEpB,MAAM,yBAAyB,OAAO,WAAW,cAAc,YAAY;AAKpE,SAAS,sBAAsB;AAClC,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,IAAI;AAEjD,yBAAuB,MAAM;AACzB,QAAI;AACA,YAAM,SAAS,KAAK,MAAM,OAAO,aAAa,QAAQ,WAAW,KAAK,MAAM;AAE5E,UAAI,MAAM,QAAQ,MAAM,KAAK,OAAO,MAAM,CAAC,QAAQ,OAAO,QAAQ,QAAQ,GAAG;AACzE,sBAAc,MAAM;AAAA,MACxB;AAAA,IACJ,QAAQ;AAAA,IAER;AAAA,EACJ,GAAG,CAAA,CAAE;AAEL,QAAM,gBAAgB,YAAY,CAAC,SAAS;AACxC,kBAAc,IAAI;AAClB,QAAI;AACA,UAAI,MAAM;AACN,eAAO,aAAa,QAAQ,aAAa,KAAK,UAAU,IAAI,CAAC;AAAA,MACjE,OAAO;AACH,eAAO,aAAa,WAAW,WAAW;AAAA,MAC9C;AAAA,IACJ,QAAQ;AAAA,IAER;AAAA,EACJ,GAAG,CAAA,CAAE;AAEL,SAAO,EAAC,YAAY,cAAa;AACrC;"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useState, useRef, useEffect, useCallback } from "react";
|
|
3
|
+
import { TAB_BAR_SCROLL_START, tabBarStateAfterScroll } from "./tabBarScroll.js";
|
|
4
|
+
const REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
|
|
5
|
+
function useTabBarMinimized(isEnabled) {
|
|
6
|
+
const [isMinimized, setIsMinimized] = useState(false);
|
|
7
|
+
const scrollState = useRef(TAB_BAR_SCROLL_START);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (!isEnabled || typeof window === "undefined") {
|
|
10
|
+
return void 0;
|
|
11
|
+
}
|
|
12
|
+
const reducedMotion = window.matchMedia?.(REDUCED_MOTION_QUERY);
|
|
13
|
+
scrollState.current = { ...TAB_BAR_SCROLL_START, lastY: window.scrollY };
|
|
14
|
+
const onScroll = () => {
|
|
15
|
+
if (reducedMotion?.matches) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
scrollState.current = tabBarStateAfterScroll(scrollState.current, window.scrollY);
|
|
19
|
+
setIsMinimized(scrollState.current.isMinimized);
|
|
20
|
+
};
|
|
21
|
+
window.addEventListener("scroll", onScroll, { passive: true });
|
|
22
|
+
return () => window.removeEventListener("scroll", onScroll);
|
|
23
|
+
}, [isEnabled]);
|
|
24
|
+
const expand = useCallback(() => {
|
|
25
|
+
scrollState.current = { ...scrollState.current, isMinimized: false, travel: 0 };
|
|
26
|
+
setIsMinimized(false);
|
|
27
|
+
}, []);
|
|
28
|
+
return { isMinimized: isEnabled && isMinimized, expand };
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
useTabBarMinimized
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=useTabBarMinimized.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTabBarMinimized.js","sources":["../../src/appShell/useTabBarMinimized.js"],"sourcesContent":["// Si la barra de pestañas del teléfono va encogida, según cómo se desliza la página (la regla está en tabBarScroll.js).\n//\n// - Con «reducir movimiento» encendido en el equipo no se encoge: la guía de Apple pide que el movimiento sea opcional.\n// - Solo cambia el estado cuando cambia la decisión (encogida o completa), no en cada evento de deslizar.\n// - expand() la regresa completa: es lo que hace tocar la cápsula chica.\n//\n// Hook genérico del paquete: function (regla de la casa).\nimport {useCallback, useEffect, useRef, useState} from 'react';\n\nimport {TAB_BAR_SCROLL_START, tabBarStateAfterScroll} from '@/appShell/tabBarScroll.js';\n\nconst REDUCED_MOTION_QUERY = '(prefers-reduced-motion: reduce)';\n\n/**\n * @param {boolean} isEnabled false: siempre completa\n * @returns {{isMinimized: boolean, expand: () => void}}\n */\nexport function useTabBarMinimized(isEnabled) {\n const [isMinimized, setIsMinimized] = useState(false);\n const scrollState = useRef(TAB_BAR_SCROLL_START);\n\n useEffect(() => {\n // pintando en el servidor no hay ventana que deslizar\n if (!isEnabled || typeof window === 'undefined') {\n return undefined;\n }\n const reducedMotion = window.matchMedia?.(REDUCED_MOTION_QUERY);\n scrollState.current = {...TAB_BAR_SCROLL_START, lastY: window.scrollY};\n const onScroll = () => {\n if (reducedMotion?.matches) {\n return;\n }\n scrollState.current = tabBarStateAfterScroll(scrollState.current, window.scrollY);\n setIsMinimized(scrollState.current.isMinimized);\n };\n window.addEventListener('scroll', onScroll, {passive: true});\n return () => window.removeEventListener('scroll', onScroll);\n }, [isEnabled]);\n\n const expand = useCallback(() => {\n scrollState.current = {...scrollState.current, isMinimized: false, travel: 0};\n setIsMinimized(false);\n }, []);\n\n return {isMinimized: isEnabled && isMinimized, expand};\n}\n"],"names":[],"mappings":";;;AAWA,MAAM,uBAAuB;AAMtB,SAAS,mBAAmB,WAAW;AAC1C,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,cAAc,OAAO,oBAAoB;AAE/C,YAAU,MAAM;AAEZ,QAAI,CAAC,aAAa,OAAO,WAAW,aAAa;AAC7C,aAAO;AAAA,IACX;AACA,UAAM,gBAAgB,OAAO,aAAa,oBAAoB;AAC9D,gBAAY,UAAU,EAAC,GAAG,sBAAsB,OAAO,OAAO,QAAO;AACrE,UAAM,WAAW,MAAM;AACnB,UAAI,eAAe,SAAS;AACxB;AAAA,MACJ;AACA,kBAAY,UAAU,uBAAuB,YAAY,SAAS,OAAO,OAAO;AAChF,qBAAe,YAAY,QAAQ,WAAW;AAAA,IAClD;AACA,WAAO,iBAAiB,UAAU,UAAU,EAAC,SAAS,KAAI,CAAC;AAC3D,WAAO,MAAM,OAAO,oBAAoB,UAAU,QAAQ;AAAA,EAC9D,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,SAAS,YAAY,MAAM;AAC7B,gBAAY,UAAU,EAAC,GAAG,YAAY,SAAS,aAAa,OAAO,QAAQ,EAAC;AAC5E,mBAAe,KAAK;AAAA,EACxB,GAAG,CAAA,CAAE;AAEL,SAAO,EAAC,aAAa,aAAa,aAAa,OAAM;AACzD;"}
|