@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
package/README.md
CHANGED
|
@@ -1,3 +1,701 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Calcita
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@stackcraftmx/calcita` · un framework de React sobre MUI 7 con el vidrio líquido de Apple. La calcita es el cristal
|
|
4
|
+
transparente famoso por doblar la luz, y eso es lo que define al vidrio líquido: su lente.
|
|
5
|
+
|
|
6
|
+
Arranca un proyecto sin copiar y volver a probar lo de siempre: el marco de la app con menú y permisos, tabla de servidor,
|
|
7
|
+
diálogos de confirmación, avisos, descargas, formularios, formatos de número y fecha, errores RFC 9457, reportes en Excel,
|
|
8
|
+
la cuenta completa, mapa, calendario, tablero kanban, bandeja tipo correo y el tema con vidrio líquido, interpretado
|
|
9
|
+
componente por componente según la guía de Apple.
|
|
10
|
+
|
|
11
|
+
JavaScript con sus tipos generados: se usa igual desde un proyecto en TypeScript. Sirve para un proyecto nuevo y también
|
|
12
|
+
para meterlo por pedazos en un sistema que ya existe (ver «En un sistema que ya existe»).
|
|
13
|
+
|
|
14
|
+
> **Versiones:** Calcita está hecha y probada con **MUI 7** (Material 7.3, MUI X 8), React 19 y react-router 7. MUI 9 ya
|
|
15
|
+
> existe, pero cambia piezas que Calcita usa: todavía no está soportado. Con MUI 9 en el proyecto, quédese en MUI 7 por
|
|
16
|
+
> ahora.
|
|
17
|
+
|
|
18
|
+
## Arrancar un proyecto con el CLI
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm dlx @stackcraftmx/calcita new mi-tienda # o: npx @stackcraftmx/calcita new mi-tienda
|
|
22
|
+
cd mi-tienda
|
|
23
|
+
pnpm install
|
|
24
|
+
pnpm dev
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Pregunta cómo lo quiere (Enter acepta lo recomendado): el menú a un lado o arriba; vidrio, sin vidrio o minimalista; claro
|
|
28
|
+
y oscuro o solo claro; los colores de Stackcraft, los de MUI o uno propio; formik o react-hook-form; los textos de Calcita o
|
|
29
|
+
i18next; las pantallas de entrar, «¿Olvidó su contraseña?» y Mi perfil; y si se puede instalar como app (PWA). Con `--yes`
|
|
30
|
+
no pregunta, y cada respuesta también va como opción (`--forms=react-hook-form`, `--menu-position=top`…;
|
|
31
|
+
`calcita --help` las dice todas).
|
|
32
|
+
|
|
33
|
+
Sale un proyecto de Vite con la forma de los ejemplos: `src/app` (el único lugar donde se conecta el framework),
|
|
34
|
+
`src/core` (lo que comparten los módulos), `src/fakeServer` (el servidor de mentira, con la forma del API de verdad) y
|
|
35
|
+
`src/modules/<módulo>`, cada uno con su menú, sus rutas, sus pantallas, su API y sus textos en español e inglés, que se
|
|
36
|
+
descubren solos. Trae un módulo de ejemplo (Contactos: lista, formulario, errores del servidor en su campo) y
|
|
37
|
+
`src/core/apiClient.js` listo para cambiar el servidor de mentira por el de verdad.
|
|
38
|
+
|
|
39
|
+
Para crecerlo, dentro del proyecto:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pnpm exec calcita make:module purchase-orders --label-es "Órdenes de compra" --label-en "Purchase orders"
|
|
43
|
+
pnpm exec calcita make:page purchase-orders OrderDetail # la pantalla y su ruta en routes.js del módulo
|
|
44
|
+
pnpm exec calcita make:form purchase-orders SupplierForm # con la librería del proyecto (calcita.json)
|
|
45
|
+
pnpm exec calcita make:component StatusBadge # en src/core, y en su puerta
|
|
46
|
+
pnpm exec calcita make:component OrderTotals --module purchase-orders
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
El CLI nunca pisa un archivo que ya existe. Sus plantillas son los archivos tal cual (`cli/templates`), con
|
|
50
|
+
`//#if pwa` … `//#endif` en lo que depende de una respuesta.
|
|
51
|
+
|
|
52
|
+
## Arrancar en un proyecto que ya existe
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pnpm add @stackcraftmx/calcita @mui/material @mui/icons-material @emotion/react @emotion/styled xstate @xstate/react sonner
|
|
56
|
+
pnpm add formik yup # solo si usa /forms o /account
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Con npm es igual, con `npm install` en lugar de `pnpm add`. Desde la 0.25, formik y yup los pone el proyecto: Calcita usa
|
|
60
|
+
la versión que ya tenga, no se casa con una.
|
|
61
|
+
|
|
62
|
+
```jsx
|
|
63
|
+
import {ThemeProvider, createTheme} from '@mui/material/styles';
|
|
64
|
+
import {ToolkitProvider, Toaster} from '@stackcraftmx/calcita';
|
|
65
|
+
|
|
66
|
+
const theme = createTheme(); // el tema lo arma cada proyecto; sin él, los colores por omisión de MUI
|
|
67
|
+
|
|
68
|
+
export const App = () => (
|
|
69
|
+
<ThemeProvider theme={theme}>
|
|
70
|
+
<ToolkitProvider appName="Mi aplicación">
|
|
71
|
+
<Toaster />
|
|
72
|
+
{/* las pantallas */}
|
|
73
|
+
</ToolkitProvider>
|
|
74
|
+
</ThemeProvider>
|
|
75
|
+
);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Sin nada más, todo sale en español, con la zona horaria del navegador, montos en pesos y la navegación del navegador.
|
|
79
|
+
|
|
80
|
+
## Lo que se conecta en ToolkitProvider
|
|
81
|
+
|
|
82
|
+
| Prop | Para qué | Por omisión |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| `language`, `onLanguageChange` | idioma activo y a quién avisar cuando se cambia | `es` |
|
|
85
|
+
| `languages` | los idiomas que ofrece la app, con su nombre y su locale (`{code: 'pt', label: 'Português', locale: 'pt-BR'}`); sus traducciones van en `texts` | español e inglés |
|
|
86
|
+
| `texts` | cambiar textos del paquete, por idioma: `{es: {common: {actions: {back: 'Volver'}}}}` | los del paquete |
|
|
87
|
+
| `translate` | un traductor propio, por ejemplo i18next | ninguno |
|
|
88
|
+
| `timeZone` | zona en que se pintan las horas | la del navegador |
|
|
89
|
+
| `currency` | moneda de los montos (ISO 4217) | `MXN` |
|
|
90
|
+
| `appName` | nombre en el título de la pestaña | ninguno |
|
|
91
|
+
| `navigation` | el router: `{useNavigate, useLocation, Link}` | la del navegador |
|
|
92
|
+
| `canAccess` | quién ve qué (menú, rutas, botones): la regla del proyecto, normalmente `createAccessChecker(...)` | solo lo que no tiene regla |
|
|
93
|
+
| `buildId` | la compilación del front que corre en la pestaña, para el aviso de versión nueva | ninguna (sin aviso) |
|
|
94
|
+
| `fileTypes` | tipos de archivo propios para las descargas (su ícono y su color), además de Excel, CSV y PDF | los de la casa |
|
|
95
|
+
|
|
96
|
+
Un `ToolkitProvider` dentro de otro (una parte de la app en otro idioma, una vista previa) toma del de afuera lo que no le
|
|
97
|
+
digan, y lo de adentro usa el suyo: el más cercano. No le cambia nada al resto de la app. Dentro de un componente,
|
|
98
|
+
`useFormatters()` da los formatos (`formatDate`, `formatCurrency`…) con el idioma, la zona y la moneda del proveedor más
|
|
99
|
+
cercano; los sueltos usan los del proveedor de la raíz.
|
|
100
|
+
|
|
101
|
+
Con react-router y i18next:
|
|
102
|
+
|
|
103
|
+
```jsx
|
|
104
|
+
import {reactRouterNavigation} from '@stackcraftmx/calcita/react-router';
|
|
105
|
+
import {translateWithI18next} from '@stackcraftmx/calcita/i18next';
|
|
106
|
+
|
|
107
|
+
<ToolkitProvider
|
|
108
|
+
navigation={reactRouterNavigation}
|
|
109
|
+
language={i18n.resolvedLanguage}
|
|
110
|
+
onLanguageChange={(language) => i18n.changeLanguage(language)}
|
|
111
|
+
translate={translateWithI18next(i18n)}
|
|
112
|
+
>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Aviso de versión nueva
|
|
116
|
+
|
|
117
|
+
Una pestaña abierta desde hace horas sigue corriendo el front con que se abrió. Si el servidor anuncia en sus
|
|
118
|
+
respuestas qué compilación está publicada, el paquete enseña una franja «Hay una versión nueva» con su botón
|
|
119
|
+
«Recargar». No recarga solo: la persona decide cuándo.
|
|
120
|
+
|
|
121
|
+
```jsx
|
|
122
|
+
import {NewBuildNotice, reportPublishedBuild} from '@stackcraftmx/calcita';
|
|
123
|
+
|
|
124
|
+
// 1. la compilación de esta pestaña (por ejemplo, de una variable de entorno al construir)
|
|
125
|
+
<ToolkitProvider buildId={import.meta.env.VITE_BUILD_ID}>
|
|
126
|
+
|
|
127
|
+
// 2. el cliente HTTP entrega la que anuncia el servidor en cada respuesta (aquí, en un header)
|
|
128
|
+
axiosClient.interceptors.response.use((response) => {
|
|
129
|
+
reportPublishedBuild(response.headers['x-frontend-build']);
|
|
130
|
+
return response;
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// 3. la franja, donde se vea siempre (normalmente dentro del AppBar); sin versión nueva no ocupa lugar
|
|
134
|
+
<NewBuildNotice />
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Con `AppLayout` no hace falta el paso 3: el marco ya lo pone. Con vidrio no es franja sino una cápsula que flota aparte
|
|
138
|
+
de la barra (`variant="floating"`): en escritorio, centrada debajo de la barra de arriba; en el teléfono, encima de la
|
|
139
|
+
barra de abajo, como el reproductor chico que Apple pone encima de las pestañas.
|
|
140
|
+
|
|
141
|
+
Sin API que anuncie la versión, o con la app anclada al inicio del iPhone (al abrirla, el iPhone no vuelve a pedir la
|
|
142
|
+
página: retoma la que tenía en memoria, aunque haya pasado un día), `usePublishedBuildWatch` se entera sola. El build deja
|
|
143
|
+
un archivo con su versión y la app lo vuelve a leer cada vez que regresa del segundo plano y cada tanto. Si estuvo fuera
|
|
144
|
+
15 minutos o más, se recarga sola con lo nuevo; si solo salió un momento (a copiar un código del SMS), sale el aviso con su
|
|
145
|
+
botón, para no borrar lo que llevaba escrito.
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
// vite.config.js: la versión va dentro de la app y en dist/version.json
|
|
149
|
+
const BUILD_ID = process.env.VITE_BUILD_ID || new Date().toISOString();
|
|
150
|
+
export default defineConfig({
|
|
151
|
+
plugins: [react(), {
|
|
152
|
+
name: 'build-version', apply: 'build',
|
|
153
|
+
generateBundle() { this.emitFile({type: 'asset', fileName: 'version.json', source: JSON.stringify({buildId: BUILD_ID})}); },
|
|
154
|
+
}],
|
|
155
|
+
define: {'import.meta.env.VITE_BUILD_ID': JSON.stringify(BUILD_ID)},
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
// en la raíz de la app, una vez (en desarrollo no hay archivo: sin url no hace nada)
|
|
159
|
+
usePublishedBuildWatch({url: import.meta.env.PROD ? `${import.meta.env.BASE_URL}version.json` : null, buildId: import.meta.env.VITE_BUILD_ID});
|
|
160
|
+
// opciones: checkEveryMinutes (5), reloadAfterHiddenMinutes (15; null = nunca recarga sola), onReload
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
El servidor no debe guardar `version.json` (con `Cache-Control: no-cache`, como el `index.html`).
|
|
164
|
+
|
|
165
|
+
## Qué trae cada puerta
|
|
166
|
+
|
|
167
|
+
Cada puerta pide solo sus librerías; un proyecto instala lo que usa.
|
|
168
|
+
|
|
169
|
+
| Importar de | Trae | Pide además |
|
|
170
|
+
|---|---|---|
|
|
171
|
+
| `@stackcraftmx/calcita` | proveedor, marco de la app, diálogos, avisos, descargas, encabezados, filtros, chips, métricas, formatos (`useFormatters`), fechas, errores RFC 9457, la petición de la casa (`createApiClient`), la recuperación de versión vieja, la navegación sin router (`createBrowserNavigation`, `createHashNavigation`), la búsqueda de la barra (`BarSearch`), el menú «⋯» (`ActionsMenu`), las acciones de lo elegido (`SelectionActions`), la seguridad de la cuenta (códigos de recuperación, sesiones, bitácora) y la bandeja tipo correo (`InboxLayout`, `MessageList` con selección, `MessageView` con la conversación) | — |
|
|
172
|
+
| `@stackcraftmx/calcita/table` | `ServerTable`: paginada, filtrada y ordenada en el servidor, con su estado en la URL | `@mui/x-data-grid`, `nuqs` |
|
|
173
|
+
| `@stackcraftmx/calcita/forms` | campos de formik (texto, lista de una o varias opciones, número con miles, catálogo, color), formulario por pasos, aviso de arriba, errores del servidor pegados a cada campo | `formik`, `yup` |
|
|
174
|
+
| `@stackcraftmx/calcita/react-hook-form` | los mismos campos con los mismos nombres, conectados a react-hook-form, su formulario por pasos y `yupResolver` | `react-hook-form`, `@hookform/resolvers` (y `yup` si valida con yup) |
|
|
175
|
+
| `@stackcraftmx/calcita/date-pickers` | la fecha con el DatePicker de MUI X (`DateInput`, `FormDateField`); viaja `AAAA-MM-DD` | `@mui/x-date-pickers` 8, `dayjs` |
|
|
176
|
+
| `@stackcraftmx/calcita/charts` | barras, columnas y líneas (una serie o varias), cada una con su vista de tabla, y `ChartTooltip` para las propias | `recharts` |
|
|
177
|
+
| `@stackcraftmx/calcita/timeline` | línea de tiempo por grupos | `@mui/lab` |
|
|
178
|
+
| `@stackcraftmx/calcita/excel` | reporte en Excel (Resumen y Datos) y CSV | `exceljs`, que se le pasa al llamarlo |
|
|
179
|
+
| `@stackcraftmx/calcita/react-router` | el adaptador de navegación | `react-router` |
|
|
180
|
+
| `@stackcraftmx/calcita/i18next` | el adaptador de textos | `i18next` (la instancia del proyecto) |
|
|
181
|
+
| `@stackcraftmx/calcita/laravel` | el reintento del 419 de Sanctum | — |
|
|
182
|
+
| `@stackcraftmx/calcita/filepond` | `FileDropzone` con FilePond: el mismo uso que la de la puerta principal, más varios archivos, avance por archivo y `createPondServer` | `filepond`, `react-filepond`, `filepond-plugin-file-validate-type`, `filepond-plugin-file-validate-size` |
|
|
183
|
+
| `@stackcraftmx/calcita/next` | la navegación de Next.js (App Router) para ToolkitProvider; los componentes ya vienen marcados con `'use client'` y los puros sirven en el servidor | `next` |
|
|
184
|
+
| `@stackcraftmx/calcita/money` | `Money`: dinero exacto en centavos enteros, con suma, resta, multiplicación, división, potencia, raíz y su formato con la moneda | — |
|
|
185
|
+
| `@stackcraftmx/calcita/passkeys` | llaves de acceso (passkeys): crearlas y firmar con ellas, con los errores del navegador en palabras de la persona | `@simplewebauthn/browser` 14 |
|
|
186
|
+
| `@stackcraftmx/calcita/account` | la cuenta completa: `SignInScreen` (con el segundo paso), `ForgotPasswordScreen`, `ResetPasswordScreen`, `ProfileScreen` (con campos y pestañas propias), `AccountSecuritySection`, `AccountProvider` y `createRestAccountConnector` | `@simplewebauthn/browser` 14, `formik`, `yup` |
|
|
187
|
+
| `@stackcraftmx/calcita/account-demo` | `createDemoAccountConnector`: la cuenta en el navegador, sin backend (y los códigos TOTP) | — |
|
|
188
|
+
| `@stackcraftmx/calcita/maps` | `MapView`: mapa con marcadores del color del tema, el elegido con su globo, se acomoda solo; en oscuro, mosaicos oscuros | `leaflet`, `react-leaflet` 5 |
|
|
189
|
+
| `@stackcraftmx/calcita/calendar` | `EventCalendar`: mes, semana, día y lista, con la barra del framework; arrastrar cambia la cita y regresa si el servidor dice que no. `EventDetails`: el detalle de una cita (lugar, liga de la reunión, invitados con su respuesta, recordatorio, notas) | `@fullcalendar/react`, `core`, `daygrid`, `timegrid`, `list`, `interaction` 6.1 |
|
|
190
|
+
| `@stackcraftmx/calcita/kanban` | `KanbanBoard`: columnas con tope (y que se encogen, como un congelador) y tarjetas de producto (etiquetas, responsables, fecha, pendientes, terminar) que se arrastran con el ratón, el dedo o el teclado; `moveCard` para ver la movida al instante | `@hello-pangea/dnd` 18 |
|
|
191
|
+
|
|
192
|
+
## El tema
|
|
193
|
+
|
|
194
|
+
`createToolkitTheme()` es opcional (ToolkitProvider funciona con cualquier tema de MUI) y trae el estilo de Stackcraft:
|
|
195
|
+
claro y oscuro con variables CSS, letra base de 16 px (con menos, el iPhone hace zoom al entrar a un campo), tamaños que
|
|
196
|
+
se ajustan al ancho, transiciones de 220 ms, esquinas de 8 px, botones sin mayúsculas y contorno de foco visible.
|
|
197
|
+
|
|
198
|
+
```js
|
|
199
|
+
const theme = createToolkitTheme(); // los colores de Stackcraft
|
|
200
|
+
const theme = createToolkitTheme({glass: true}); // vidrio líquido en lo que flota y en los controles
|
|
201
|
+
const theme = createToolkitTheme({colorSchemes: {light: {palette: {primary: {main: '#0B5FFF'}}}, dark: {palette: {…}}}});
|
|
202
|
+
const theme = createToolkitTheme({components: {MuiCard: {…}}}); // se SUMA a los ajustes del framework
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
El vidrio es la versión en CSS del Liquid Glass de Apple (60 % de opacidad por omisión). Va en lo que flota sobre el
|
|
206
|
+
contenido y en los controles, como pide su guía:
|
|
207
|
+
|
|
208
|
+
- la barra y el menú lateral, que en escritorio flotan a 8 px de la orilla;
|
|
209
|
+
- los menús, las listas de opciones, el calendario, los menús de la tabla, los diálogos, los tooltips, los avisos, el
|
|
210
|
+
panel de descargas, el botón flotante y la barra de pestañas de abajo;
|
|
211
|
+
- la «gota» que marca lo elegido en las pestañas y en los botones de opción, que se desliza a la opción nueva;
|
|
212
|
+
- botones en píldora que se hunden al apretarlos;
|
|
213
|
+
- un lienzo con manchas tenues de color, para que el vidrio tenga algo que desenfocar.
|
|
214
|
+
|
|
215
|
+
Las tarjetas del contenido se quedan sólidas, para que el texto largo se lea, salvo que el proyecto las pida de vidrio.
|
|
216
|
+
Todo se pinta sólido si la persona pidió en su equipo «Reducir transparencia» o «Aumentar contraste». La refracción (el
|
|
217
|
+
lente que dobla lo de atrás en la orilla del vidrio) sale en Chrome y sus parientes (Edge, Brave, Arc) con
|
|
218
|
+
`GlassLensFilter`, que `AppLayout` y `AuthLayout` ya ponen; Safari y Firefox no pintan ese filtro y ahí el vidrio se queda
|
|
219
|
+
esmerilado.
|
|
220
|
+
|
|
221
|
+
```js
|
|
222
|
+
const theme = createToolkitTheme({glass: {opacity: 0.7}}); // más transparente (0 a 1)
|
|
223
|
+
const theme = createToolkitTheme({glass: {surfaces: true}}); // también las tarjetas del contenido
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
`surfaces` se puede usar, pero avisa en la consola: cada tarjeta de vidrio desenfoca lo que tiene detrás (pesa más en
|
|
227
|
+
equipos modestos) y la guía de Apple pide el contenido sin vidrio. Va bien en una portada o una demostración, no en
|
|
228
|
+
pantallas de trabajo.
|
|
229
|
+
|
|
230
|
+
La barra de arriba va sin franja, como las ventanas de macOS Tahoe: la ☰ con el nombre, el menú y la cuenta en cápsulas,
|
|
231
|
+
y el título suelto. Con vidrio las cápsulas son de vidrio y el contenido pasa por debajo, desenfocado en la orilla para
|
|
232
|
+
que todo se lea (`scrollEdgeStylesOf`); con el minimalista son bloques del tono de las tarjetas, también en el teléfono.
|
|
233
|
+
Con cápsulas, el menú encogido deja la cuenta arriba en su cápsula, y en el teléfono el minimalista también lleva la
|
|
234
|
+
barra de pestañas de abajo (sólida, del gris 5 de Apple). Quien prefiera la franja de lado a lado la pide;
|
|
235
|
+
está en el mismo alto y el mismo lugar, así que nada más se mueve. El estilo de Stackcraft sin vidrio sigue con su barra.
|
|
236
|
+
|
|
237
|
+
```js
|
|
238
|
+
const theme = createToolkitTheme({glass: true, bar: TOP_BAR.band}); // la franja; por omisión TOP_BAR.capsules
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Cada pantalla puede poner sus propias cápsulas en la barra (buscar, agregar, exportar) con `BarActions`: las escribe en
|
|
242
|
+
su código donde quiera y, en escritorio con cápsulas, el marco las sube a la barra; con la franja entran a la franja, y en
|
|
243
|
+
el teléfono, con cápsulas, flotan arriba a la derecha y se quedan al bajar: las que caben, solo con ícono, y las que no,
|
|
244
|
+
en un menú «⋯». Las `actions` de `PageHeading` ya suben solas, y `ServerTable` sube su búsqueda con
|
|
245
|
+
`searchInBar`. «Hecho en Calcita» → «Marco y menú» lo enseña vivo.
|
|
246
|
+
|
|
247
|
+
```jsx
|
|
248
|
+
<BarActions label="Buscar en pedidos" order={1}>
|
|
249
|
+
<IconButton aria-label="Buscar" onClick={openSearch}><SearchRoundedIcon /></IconButton>
|
|
250
|
+
</BarActions>
|
|
251
|
+
<BarActions label="Acciones de pedidos" order={2}> {/* otro grupo, otra cápsula */}
|
|
252
|
+
{/* en la cápsula, solo el ícono con su nombre en el tooltip */}
|
|
253
|
+
<BarActionButton label="Agregar pedido" icon={<AddRoundedIcon />} onClick={openNew} />
|
|
254
|
+
</BarActions>
|
|
255
|
+
<BarCapsule aria-label="Zoom">…</BarCapsule> {/* la misma cápsula, fuera de la barra */}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
En Android conviene arrancar con el minimalista: el vidrio es el estilo de Apple (allá se ve ajeno) y el desenfoque pesa
|
|
259
|
+
en los teléfonos baratos. `isAndroidDevice()` lo dice; con Next, desde el servidor, se le pasa la identificación del
|
|
260
|
+
navegador: `isAndroidDevice({userAgent: headers.get('user-agent')})`. Sirve para elegir un estilo, no para seguridad.
|
|
261
|
+
|
|
262
|
+
```js
|
|
263
|
+
const theme = isAndroidDevice() ? createToolkitTheme({look: THEME_LOOK.minimal}) : createToolkitTheme({glass: true});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Para lo que el proyecto quiera hacer flotar (los botones encima de un mapa, una barra de acciones): `GlassPanel`, que es
|
|
267
|
+
de vidrio si el tema lo trae y una tarjeta con sombra si no. Para algo propio: `sx={(theme) => glassStylesOf(theme)}` e
|
|
268
|
+
`isGlassTheme(theme)`. Cada ajuste vive en su archivo (`src/theme/components/MuiButton.js`…).
|
|
269
|
+
|
|
270
|
+
## El marco de la app, el menú y los permisos
|
|
271
|
+
|
|
272
|
+
`AppLayout` es el marco de las plantillas de MUI: la barra a todo lo ancho, con el logo y el nombre de la app; debajo,
|
|
273
|
+
el menú lateral por secciones, que la ☰ encoge a solo íconos (y lo recuerda). La barra trae el título de la página
|
|
274
|
+
cuando el grande sale de la vista, el tamaño de letra, el idioma, claro u oscuro y la cuenta (Mi perfil, lo que agregue
|
|
275
|
+
el proyecto y Salir). Con `menuPosition="top"` el menú va dentro de la barra. En el teléfono, la hamburguesa abre el menú
|
|
276
|
+
en un cajón y los ajustes se juntan detrás de un engrane. Con vidrio, en el teléfono las secciones van en una barra de
|
|
277
|
+
pestañas abajo que se encoge al leer hacia abajo y regresa al subir, como en iOS 26 (`minimizeTabBarOnScroll={false}` la
|
|
278
|
+
deja fija). Van las que el `menu.js` marca con `mobileTab: true`, y en «Más» → «Editar la barra» cada quien elige las suyas
|
|
279
|
+
(se recuerda en su navegador; «Como venía» regresa a las del proyecto). Van tantas como quepan a lo ancho sin cortar su
|
|
280
|
+
nombre; las demás, en «Más».
|
|
281
|
+
|
|
282
|
+
Claro u oscuro tiene tres opciones en el menú de la cuenta: Claro, Oscuro y Automático, que sigue lo que diga el equipo y
|
|
283
|
+
es lo de omisión. El botón de la barra fija claro u oscuro; Automático es la forma de volver a seguir al equipo.
|
|
284
|
+
|
|
285
|
+
El menú no se escribe en una lista central: cada módulo trae su `menu.js` y `composeMenu` los junta, los ordena y deja
|
|
286
|
+
solo los que la sesión puede ver (también dentro de los submenús).
|
|
287
|
+
|
|
288
|
+
```js
|
|
289
|
+
// modules/orders/menu.js
|
|
290
|
+
export const order = 10;
|
|
291
|
+
export const access = {ability: 'orders.view'}; // o {role}, {anyOf}, {policy: 'sameOrganization'}, {check}
|
|
292
|
+
export function buildMenuItem() {
|
|
293
|
+
return {
|
|
294
|
+
to: '/orders', labelKey: 'orders:menu.label', sectionKey: 'app:sections.operation', Icon: ReceiptLongIcon,
|
|
295
|
+
badge: 3, // opcional
|
|
296
|
+
children: [{to: '/orders/returns', labelKey: 'orders:menu.returns', access: {ability: 'returns.view'}}], // opcional
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
```jsx
|
|
302
|
+
const canAccess = createAccessChecker({abilities: session.abilities, roles: session.roles, policies, context: {session}});
|
|
303
|
+
const menuItems = composeMenu(import.meta.glob('@/modules/*/menu.js', {eager: true}), {canAccess});
|
|
304
|
+
|
|
305
|
+
<ToolkitProvider canAccess={canAccess}>
|
|
306
|
+
<AppLayout logo={<Logo />} menuItems={menuItems} user={session.user} profilePath="/me" onSignOut={signOut}
|
|
307
|
+
headerActions={<MiBoton />} sidebarFooter={<MiTarjeta />} accountMenuItems={[{to: '/billing', label: 'Facturación'}]}>
|
|
308
|
+
…
|
|
309
|
+
</AppLayout>
|
|
310
|
+
</ToolkitProvider>
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
En cada pantalla, `PageHeading` pone el título, la descripción y los botones, y arma las migas solo desde el menú
|
|
314
|
+
(Inicio › Sección › Pantalla). `PageHeader` es el encabezado centrado de una portada y `DetailHeader` el de un registro.
|
|
315
|
+
|
|
316
|
+
La misma regla protege las rutas (`withAccess(access, routes)` de `/react-router`: quien no puede ve «sin permiso», o la
|
|
317
|
+
página propia que se pase en `{fallback}`) y
|
|
318
|
+
los botones (`<Can access={…}>`, `useCan`). El framework no sabe de roles: RBAC por permisos o roles y ABAC por políticas
|
|
319
|
+
con nombre o reglas escritas ahí mismo, como cada proyecto las necesite. Lo que se pinta no protege nada: el backend
|
|
320
|
+
vuelve a revisar cada petición. `ErrorPage` trae las pantallas de 404, 403 y 500, y se extiende sin tocarla: botones
|
|
321
|
+
propios junto a los de la casa (`extraActions`) o en su lugar (`actions`), algo debajo del texto (`children`), otro ícono y
|
|
322
|
+
`onGoHome`.
|
|
323
|
+
|
|
324
|
+
El marco avisa cuando la persona encoge el menú (`onMenuCollapse`), abre el menú del teléfono (`onMobileMenuChange`) o elige
|
|
325
|
+
sus pestañas (`onMobileTabsChange`), para guardar esas preferencias en el servidor del proyecto si se quiere; sus textos se
|
|
326
|
+
cambian con `texts`.
|
|
327
|
+
|
|
328
|
+
## Eventos y textos de cada componente
|
|
329
|
+
|
|
330
|
+
Cada componente de la casa avisa hacia afuera todo lo que pasa adentro (`onSelect`, `onChange`, `onViewChange`,
|
|
331
|
+
`onMenuCollapse`, `onCardComplete`, `onDatesChange`…) y nunca llama un servidor propio: el proyecto decide qué hacer. Así se
|
|
332
|
+
mide, se guarda una preferencia en el servidor del proyecto o se conecta un sistema viejo sin tocar Calcita.
|
|
333
|
+
|
|
334
|
+
Cada texto también se cambia desde afuera: el componente recibe `texts` con la forma de su namespace en los textos del
|
|
335
|
+
paquete (`src/locales/es.js`), y `ComponentTexts` los cambia para todo lo que va adentro (un módulo con su propio
|
|
336
|
+
vocabulario):
|
|
337
|
+
|
|
338
|
+
```jsx
|
|
339
|
+
<ServerTable texts={{count: {records_one: '{{total}} pedido', records_other: '{{total}} pedidos'}}} … />
|
|
340
|
+
|
|
341
|
+
<ComponentTexts namespace="table" texts={{emptyState: {title: 'Sin pedidos'}}}>
|
|
342
|
+
<OrdersModule />
|
|
343
|
+
</ComponentTexts>
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
## En un sistema que ya existe
|
|
347
|
+
|
|
348
|
+
Calcita entra por pedazos en un sistema hecho en PHP, JSP o .NET, sin reescribirlo: cada pedazo es una «isla» de React en
|
|
349
|
+
un `<div>` de la página vieja, con su propio `ToolkitProvider`.
|
|
350
|
+
|
|
351
|
+
- **Sin router:** `createHashNavigation()` pone las pantallas después del `#` (`/app.php#/ventas`): cambiar de pantalla no
|
|
352
|
+
recarga, atrás y adelante funcionan y recargar no le pide nada nuevo al servidor viejo. Con la app bajo un prefijo y sin
|
|
353
|
+
router, `createBrowserNavigation({basePath: '/portal'})`.
|
|
354
|
+
- **Su tema de MUI tal cual:** Calcita lee los colores del tema, con o sin variables CSS y con el prefijo que traiga
|
|
355
|
+
(`cssVarPrefix`).
|
|
356
|
+
- **Varias islas, cada una con lo suyo:** dos islas pueden ir en idiomas y monedas distintas; `useFormatters()` escribe con
|
|
357
|
+
los de su isla.
|
|
358
|
+
- **Un backend que contesta a su manera:** `createApiClient({toProblem, mapResponse})` convierte sus errores a RFC 9457
|
|
359
|
+
(Laravel manda `{message, errors}`) y desenvuelve sus respuestas (`{data: …}`); `onError` recibe cada error en un lugar.
|
|
360
|
+
|
|
361
|
+
```jsx
|
|
362
|
+
const hashNavigation = createHashNavigation(); // una vez, fuera de los componentes
|
|
363
|
+
|
|
364
|
+
document.querySelectorAll('[data-calcita="sales"]').forEach((element) => {
|
|
365
|
+
createRoot(element).render(
|
|
366
|
+
<ThemeProvider theme={legacyTheme}>
|
|
367
|
+
<ToolkitProvider language={element.lang || 'es'} navigation={hashNavigation}>
|
|
368
|
+
<SalesOfTheDay onOpen={() => element.dispatchEvent(new CustomEvent('calcita:open-sales', {bubbles: true}))} />
|
|
369
|
+
</ToolkitProvider>
|
|
370
|
+
</ThemeProvider>,
|
|
371
|
+
);
|
|
372
|
+
});
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
## Detrás de un proxy con prefijo
|
|
376
|
+
|
|
377
|
+
Para publicar la app en una ruta y no en un subdominio (`miempresa.com/ventas/`), el prefijo se da una vez al construir,
|
|
378
|
+
`ASSET_URL=/ventas`, la misma línea del `.env` del servidor. El proyecto que arma `calcita new` ya lo trae:
|
|
379
|
+
|
|
380
|
+
1. `vite.config.js`: `base` con el prefijo; Vite se lo pone a sus archivos y a las rutas de `index.html`;
|
|
381
|
+
2. el router con el mismo prefijo (`createBrowserRouter(routes, {basename})`): las pantallas siguen escribiendo sus rutas
|
|
382
|
+
desde la raíz;
|
|
383
|
+
3. lo de `public/` y `version.json` con `import.meta.env.BASE_URL` (una dirección escrita desde la raíz se rompe detrás del
|
|
384
|
+
proxy) y el manifiesto con rutas relativas;
|
|
385
|
+
4. el servidor: cada dirección bajo el prefijo que no sea un archivo regresa su `index.html`.
|
|
386
|
+
|
|
387
|
+
```nginx
|
|
388
|
+
location /ventas/ {
|
|
389
|
+
try_files $uri $uri/ /ventas/index.html;
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
## La petición de la casa
|
|
394
|
+
|
|
395
|
+
Todo lo que habla con el servidor pasa por un cliente, armado una vez por proyecto con `fetch` del navegador (sin axios):
|
|
396
|
+
|
|
397
|
+
```js
|
|
398
|
+
import {createApiClient} from '@stackcraftmx/calcita';
|
|
399
|
+
|
|
400
|
+
export const api = createApiClient({
|
|
401
|
+
baseUrl: '/api/v1',
|
|
402
|
+
csrf: {refreshPath: '/auth/csrf-token'}, // Laravel Sanctum: la cookie XSRF-TOKEN y el reintento del 419
|
|
403
|
+
onUnauthenticated: () => navigate('/sign-in'), // un 401 a media consulta
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
const orders = await api.get('/orders', {params: {page: 2}, signal});
|
|
407
|
+
await api.post('/orders', {customerId: 7});
|
|
408
|
+
const {blob, fileName} = await api.download('/orders/export', {onDownloadProgress});
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
- Cada petición lleva el idioma vigente (`Accept-Language`): el servidor responde sus mensajes ya traducidos.
|
|
412
|
+
- Un error es siempre un `ApiError`: el problema RFC 9457 del servidor con su mensaje ya traducido, su status, su
|
|
413
|
+
`requestId` para soporte y los errores por campo de un 422 (los formularios los ponen en su campo). Sin red es la misma
|
|
414
|
+
forma (status 0); cancelar no es un error.
|
|
415
|
+
- Cada respuesta le avisa al aviso de versión nueva qué compilación está publicada (header `X-Frontend-Build`).
|
|
416
|
+
- Un Excel que llegó cortado no se entrega.
|
|
417
|
+
|
|
418
|
+
Si se publica otra versión con la pestaña abierta, la pantalla que no se había abierto pide un archivo que ya no existe.
|
|
419
|
+
`withChunkRecovery` (de `/react-router`) recarga una vez y `RouteErrorScreen` dice «Hay una versión nueva» con su botón;
|
|
420
|
+
sin router de datos, `recoverFromStaleChunk` en el `.catch()` del import y `StaleBuildBoundary` alrededor de las pantallas.
|
|
421
|
+
|
|
422
|
+
## La cuenta completa: conectar su backend
|
|
423
|
+
|
|
424
|
+
Entrar (con el segundo paso), «¿Olvidó su contraseña?», elegir una contraseña nueva, Mi perfil (sus datos, seguridad y
|
|
425
|
+
preferencias) y la seguridad de la cuenta (llaves de acceso, app autenticadora, códigos de recuperación, sesiones abiertas y
|
|
426
|
+
bitácora) vienen hechos en `@stackcraftmx/calcita/account`. El proyecto **solo escribe el conector**: las llamadas a su
|
|
427
|
+
backend. Pide `@simplewebauthn/browser` (las llaves de acceso).
|
|
428
|
+
|
|
429
|
+
```jsx
|
|
430
|
+
import {AccountProvider, ProfileScreen, SignInScreen, createRestAccountConnector} from '@stackcraftmx/calcita/account';
|
|
431
|
+
|
|
432
|
+
// 1. el conector: si el backend sigue el contrato de abajo, es una línea
|
|
433
|
+
const accountConnector = createRestAccountConnector(apiClient);
|
|
434
|
+
|
|
435
|
+
// 2. el proveedor, por fuera de ToolkitProvider (le pasa la regla de permisos de quien está dentro)
|
|
436
|
+
<AccountProvider connector={accountConnector}>
|
|
437
|
+
{(canAccess) => <ToolkitProvider canAccess={canAccess} …>…</ToolkitProvider>}
|
|
438
|
+
</AccountProvider>
|
|
439
|
+
|
|
440
|
+
// 3. las pantallas, en sus rutas
|
|
441
|
+
{path: '/sign-in', element: <SignInScreen forgotPasswordPath="/forgot-password" logo={<AppLogo />} />}
|
|
442
|
+
{path: '/forgot-password', element: <ForgotPasswordScreen signInPath="/sign-in" />}
|
|
443
|
+
{path: '/reset-password', element: <ResetPasswordScreen signInPath="/sign-in" />} // el enlace del correo: ?token=…
|
|
444
|
+
{path: '/profile', element: <ProfileScreen />}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
`useAccount()` da `{session, refreshSession, signOut}` para la barra y las pantallas propias.
|
|
448
|
+
|
|
449
|
+
**Sin backend todavía:** `createDemoAccountConnector()` de `@stackcraftmx/calcita/account-demo` (todo en el navegador,
|
|
450
|
+
con la verificación en dos pasos funcionando con su teléfono de verdad). Con `toQrImageUrl` sale el QR de la app; el
|
|
451
|
+
proyecto que arma `calcita new` usa la demostración mientras no tenga `VITE_API_URL` y el REST en cuanto la tiene (la
|
|
452
|
+
demostración ni siquiera viaja en lo construido).
|
|
453
|
+
|
|
454
|
+
**Si el backend es distinto:** se cambia la ruta en `paths` o solo la función que no coincida; TypeScript (o el editor,
|
|
455
|
+
con el JSDoc) avisa si una función no regresa lo que piden las pantallas (`AccountConnector`).
|
|
456
|
+
|
|
457
|
+
```js
|
|
458
|
+
const accountConnector = {
|
|
459
|
+
...createRestAccountConnector(apiClient, {paths: {session: '/me'}}),
|
|
460
|
+
signIn: async ({email, password, remember}) => {
|
|
461
|
+
const response = await apiClient.post('/login', {username: email, password, remember});
|
|
462
|
+
return {secondStep: response.mfa_required ? {methods: ['totp']} : null};
|
|
463
|
+
},
|
|
464
|
+
};
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
El contrato REST (`ACCOUNT_REST_PATHS`; llaves en snake_case, errores RFC 9457 con `errors` por campo):
|
|
468
|
+
|
|
469
|
+
| Petición | Manda | Responde |
|
|
470
|
+
|---|---|---|
|
|
471
|
+
| `GET /auth/session` | — | `{user: {id, name, email, subtitle, phone}, roles, abilities, labels}`; 401 si nadie está dentro |
|
|
472
|
+
| `POST /auth/sign-in` | `{email, password, remember}` | `{second_step: {methods: ['passkey', 'totp', 'recovery_code']} \| null}` |
|
|
473
|
+
| `POST /auth/second-step` | `{method: 'totp' \| 'recovery_code', code}` | 204; 401 con `remaining_attempts`, 423 `account_locked` |
|
|
474
|
+
| `GET /auth/second-step/passkey-options` | — | las opciones de WebAuthn para firmar |
|
|
475
|
+
| `POST /auth/second-step/passkey` | `{credential}` | 204 |
|
|
476
|
+
| `POST /auth/sign-out` | — | 204 |
|
|
477
|
+
| `POST /auth/forgot-password` | `{email}` | 204, exista o no el correo |
|
|
478
|
+
| `POST /auth/reset-password` | `{token, new_password}` | 204 |
|
|
479
|
+
| `PUT /account` | `{name, phone}` | `{message?}` |
|
|
480
|
+
| `PUT /account/password` | `{current_password, new_password}` | 204 |
|
|
481
|
+
| `GET /account/security` | — | `{is_enabled, enabled_at, passkeys: [{id, name, created_at, last_used_at}], totp: {is_enabled, enabled_at}, recovery_codes_remaining}` |
|
|
482
|
+
| `POST /account/security/totp` | — | `{secret, qr_image_url}` |
|
|
483
|
+
| `POST /account/security/totp/confirm` | `{code}` | `{security, recovery_codes?}` |
|
|
484
|
+
| `DELETE /account/security/totp` | `{password}` | `{security}` |
|
|
485
|
+
| `GET /account/security/passkeys/registration-options` | — | las opciones de WebAuthn para crear |
|
|
486
|
+
| `POST /account/security/passkeys` | `{name, credential}` | `{security, recovery_codes?}` |
|
|
487
|
+
| `DELETE /account/security/passkeys/{id}` | `{password}` | `{security}` |
|
|
488
|
+
| `POST /account/security/recovery-codes` | `{password}` | `{security, recovery_codes}` |
|
|
489
|
+
| `GET /account/sessions` | — | `[{id, browser, platform, is_mobile, started_at, network, is_current}]` |
|
|
490
|
+
| `POST /account/sessions/close-others` | — | `{closed}` |
|
|
491
|
+
| `GET /account/activity` | — | `[{id, kind, occurred_at, device, network}]` |
|
|
492
|
+
|
|
493
|
+
Las opciones y la firma de WebAuthn viajan tal cual: las arma y las revisa la librería del servidor (py_webauthn,
|
|
494
|
+
@simplewebauthn/server, web-auth/webauthn-lib). Lo que quita protección pide la contraseña; `recovery_codes` se enseña una
|
|
495
|
+
sola vez. `kind` de la bitácora es uno de `ACCOUNT_EVENT_KIND`.
|
|
496
|
+
|
|
497
|
+
## Seguridad de la cuenta (las piezas sueltas)
|
|
498
|
+
|
|
499
|
+
Las mismas piezas de la cuenta completa, para armar pantallas propias:
|
|
500
|
+
- En `/forms`, `TwoStepVerificationCard`: llaves de acceso, app autenticadora y códigos de recuperación. Lo que quita
|
|
501
|
+
protección pide la contraseña. El proyecto conecta las acciones con su API; la tarjeta no sabe del servidor.
|
|
502
|
+
- En `/forms`, `SecondStepForm`: el segundo paso al entrar (llave, código de la app o de recuperación), con los intentos
|
|
503
|
+
que quedan.
|
|
504
|
+
- `RecoveryCodesDialog`: los códigos se enseñan una vez y no se cierra sin «Ya los guardé»; se copian o se bajan en .txt.
|
|
505
|
+
- `SessionsCard`: dónde está abierta la cuenta y «cerrar la sesión en los demás equipos». `ActivityLog`: la bitácora.
|
|
506
|
+
- En `/passkeys`, `createPasskey` y `signWithPasskey`: el navegador pide la huella, el rostro o el PIN.
|
|
507
|
+
|
|
508
|
+
Contra XSS: los textos del servidor se pintan como texto (nunca `dangerouslySetInnerHTML`), `safeInternalPath` solo deja
|
|
509
|
+
seguir direcciones de la app en `?next=`, la sesión va en una cookie HttpOnly (sin tokens en `localStorage`) y el CSRF con
|
|
510
|
+
la cookie doble de Sanctum. Los ejemplos lo enseñan en Componentes → Seguridad, y la verificación funciona con su
|
|
511
|
+
teléfono de verdad en Mi perfil → Seguridad.
|
|
512
|
+
|
|
513
|
+
## Entrar, Mi perfil y los permisos (el template)
|
|
514
|
+
|
|
515
|
+
Lo que piden todos los sistemas, listo para conectar a su API:
|
|
516
|
+
|
|
517
|
+
- `AuthLayout`: la pantalla de entrar, con el logo, una tarjeta al centro y el idioma y claro u oscuro arriba (con
|
|
518
|
+
vidrio, la tarjeta es de vidrio sobre el lienzo de color).
|
|
519
|
+
- En `/forms`, `SignInForm`, `ForgotPasswordForm` y `ChangePasswordForm`. Los errores del servidor salen en su lugar.
|
|
520
|
+
«¿Olvidó su contraseña?» no dice si el correo existe, a propósito. La contraseña nueva trae su lista de reglas, que se
|
|
521
|
+
va palomeando (`DEFAULT_PASSWORD_POLICY`: 12 caracteres, minúscula, mayúscula y número; cada proyecto pone la suya).
|
|
522
|
+
- `ProfileHeader`: portada, avatar con iniciales, nombre y perfil. `AppearanceSettings`: tamaño de letra, idioma y claro
|
|
523
|
+
u oscuro, los mismos del engrane del teléfono.
|
|
524
|
+
- `PermissionMatrix`: los permisos de un perfil por grupo, con «todos» y cuántos tiene. Cada módulo declara los suyos en
|
|
525
|
+
su `menu.js` y `composePermissionGroups` los junta: no hay lista central.
|
|
526
|
+
- `MetricCard` con `trend`: cuánto cambió contra el periodo anterior, en verde si es bueno y en rojo si es malo.
|
|
527
|
+
|
|
528
|
+
```jsx
|
|
529
|
+
<AuthLayout logo={<Logo />} title={t('auth:signIn.title')} description={t('auth:signIn.subtitle')}>
|
|
530
|
+
<SignInForm onSubmit={(values) => api.signIn(values)} forgotPasswordPath="/forgot-password" />
|
|
531
|
+
</AuthLayout>
|
|
532
|
+
|
|
533
|
+
// modules/orders/menu.js
|
|
534
|
+
export const permissions = [
|
|
535
|
+
{key: 'orders.view', labelKey: 'orders:permissions.view', descriptionKey: 'orders:permissions.viewDescription'},
|
|
536
|
+
{key: 'orders.cancel', labelKey: 'orders:permissions.cancel'},
|
|
537
|
+
];
|
|
538
|
+
|
|
539
|
+
// la pantalla de perfiles
|
|
540
|
+
const groups = composePermissionGroups(import.meta.glob('@/modules/*/menu.js', {eager: true}), t);
|
|
541
|
+
<PermissionMatrix groups={groups} value={profile.abilities} onChange={setAbilities} />
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
Los ejemplos lo traen armado: entrar (con «Entrar como…» para los tres perfiles de prueba), «¿olvidó su contraseña?»,
|
|
545
|
+
elegir una contraseña nueva, Mi perfil (sus datos, seguridad y preferencias), Perfiles y permisos (al guardar los de su
|
|
546
|
+
propio perfil, el menú cambia en ese momento) y un tablero con tarjetas, gráficas y los últimos pedidos.
|
|
547
|
+
|
|
548
|
+
## Next.js (App Router)
|
|
549
|
+
|
|
550
|
+
El paquete ya viene marcado para Next: los componentes llevan `'use client'` y lo puro (formatos, `Money`, permisos,
|
|
551
|
+
menú, diccionarios) no lleva marca, así que también corre en los componentes de servidor. Lo que se conecta:
|
|
552
|
+
|
|
553
|
+
```jsx
|
|
554
|
+
// app/layout.jsx (servidor)
|
|
555
|
+
<html lang="es" suppressHydrationWarning>
|
|
556
|
+
<body>
|
|
557
|
+
<InitColorSchemeScript attribute="class" /> {/* claro u oscuro antes de pintar, sin brinco */}
|
|
558
|
+
<AppRouterCacheProvider> {/* @mui/material-nextjs/v16-appRouter */}
|
|
559
|
+
<AppProviders>{children}</AppProviders> {/* 'use client': tema, ToolkitProvider y AppLayout */}
|
|
560
|
+
</AppRouterCacheProvider>
|
|
561
|
+
</body>
|
|
562
|
+
</html>
|
|
563
|
+
|
|
564
|
+
// AppProviders.jsx ('use client')
|
|
565
|
+
<ToolkitProvider navigation={nextNavigation} …> {/* de @stackcraftmx/calcita/next */}
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
- El servidor calcula con las piezas puras y le pasa TEXTO al cliente (`money.toJSON()`): lo que cruza del servidor al
|
|
569
|
+
navegador tiene que ser JSON.
|
|
570
|
+
- Zona y moneda del servidor con `configureToolkit({timeZone, currency})` una vez (son de toda la app; sin eso, en un
|
|
571
|
+
contenedor la zona es UTC). El idioma NO: cambia por persona y vive en el cliente.
|
|
572
|
+
- Los `menu.js` se descubren con `require.context` (Next no tiene `import.meta.glob`).
|
|
573
|
+
- El «Regresar» de `BackButton` no sabe a dónde regresa (Next no guarda el índice del historial que pone react-router):
|
|
574
|
+
regresa a la última lista anotada o a `fallbackTo`.
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
## Formularios
|
|
578
|
+
|
|
579
|
+
Cada campo tiene su vista suelta en la puerta principal (`TextInput`, `SelectInput`, `NumberInput`, `CatalogInput`,
|
|
580
|
+
`ColorInput`; sirven sin formulario; `SelectInput` y `CatalogInput` aceptan varias opciones con `multiple`) y su conexión: a formik en `/forms` y a react-hook-form en `/react-hook-form`, con
|
|
581
|
+
los mismos nombres. Cambiar de librería es cambiar el import.
|
|
582
|
+
|
|
583
|
+
```jsx
|
|
584
|
+
import {Form, Formik, FormNumberField, FormProblemAlert, FormTextField, SubmitButton, Yup, applyServerProblem} from '@stackcraftmx/calcita/forms';
|
|
585
|
+
|
|
586
|
+
<Formik initialValues={{name: '', credit_limit: ''}} validationSchema={schema}
|
|
587
|
+
onSubmit={async (values, helpers) => {
|
|
588
|
+
try { await api.save(values); } catch (error) { applyServerProblem(error, {...helpers, values}); }
|
|
589
|
+
}}>
|
|
590
|
+
<Form noValidate>
|
|
591
|
+
<FormProblemAlert />
|
|
592
|
+
<FormTextField name="name" label="Nombre" />
|
|
593
|
+
<FormNumberField name="credit_limit" label="Límite de crédito" prefix="$" /> {/* viaja '50000.00' */}
|
|
594
|
+
<SubmitButton>Guardar</SubmitButton>
|
|
595
|
+
</Form>
|
|
596
|
+
</Formik>
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
formik y yup los instala el proyecto (`pnpm add formik yup`); `Formik`, `Form` y `Yup` también se pueden importar de
|
|
600
|
+
`@stackcraftmx/calcita/forms`, que es la misma copia. `FormWizard` parte un formulario en pasos, con pasos opcionales (hay
|
|
601
|
+
uno para formik y otro para react-hook-form); los ejemplos traen los dos.
|
|
602
|
+
|
|
603
|
+
Para que el formulario se vea como los de Apple (Ajustes, la hoja «Nuevo evento» de Calendario), los campos van dentro de
|
|
604
|
+
una `FormSection`: cada uno se vuelve un renglón, con la etiqueta a la izquierda y el valor a la derecha, sin la caja de
|
|
605
|
+
MUI. Son los mismos campos, sin cambiarles nada; las listas llevan su ⌃⌄ y la fecha va en una cápsula. `FormRow` es el
|
|
606
|
+
renglón suelto para lo demás (un interruptor, un texto).
|
|
607
|
+
|
|
608
|
+
```jsx
|
|
609
|
+
import {FormRow, FormSection} from '@stackcraftmx/calcita';
|
|
610
|
+
|
|
611
|
+
<FormSection title="Contacto" footer="Con el correo le avisamos de cada pedido.">
|
|
612
|
+
<FormTextField name="name" label="Nombre" placeholder="Nombre y apellidos" />
|
|
613
|
+
<FormTextField name="email" label="Correo" type="email" />
|
|
614
|
+
<FormRow label="Avisos por correo"><Switch /></FormRow>
|
|
615
|
+
</FormSection>
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
Los campos van directo dentro de la `FormSection` (sin Grid ni Stack en medio): la línea entre renglones se dibuja entre
|
|
619
|
+
hermanos.
|
|
620
|
+
|
|
621
|
+
## Subir archivos
|
|
622
|
+
|
|
623
|
+
Dos zonas para soltar archivos con el mismo uso: la de la puerta principal, con puro MUI (un archivo), y la de
|
|
624
|
+
`/filepond` (varios archivos, animaciones, avance por archivo). Cambiar de una a otra es cambiar el import. Las dos solo
|
|
625
|
+
eligen; la pantalla sube con `uploadWithProgress` (el avance real de la subida) y sigue la subida con `uploadMachine`.
|
|
626
|
+
|
|
627
|
+
```jsx
|
|
628
|
+
import {FileDropzone, buildUploadActors, uploadMachine, uploadWithProgress} from '@stackcraftmx/calcita';
|
|
629
|
+
|
|
630
|
+
<FileDropzone value={file} onChange={setFile} accept="excel" maxSize="10 MB" busy={isUploading}
|
|
631
|
+
actions={<Button onClick={() => send({type: 'UPLOAD', input: {file}})}>Importar</Button>} />
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
`accept` acepta nombres (`'excel'`, `['pdf', 'image']`) o lo de siempre del input (`'.xlsx,.xls'`); `maxSize` va en bytes
|
|
635
|
+
o con unidades (`'10 MB'`, en base 1000 como el navegador).
|
|
636
|
+
|
|
637
|
+
## Dinero sin problemas de decimales
|
|
638
|
+
|
|
639
|
+
En JavaScript `0.1 + 0.2` da `0.30000000000000004`. `Money` guarda los montos en centavos enteros (como el Money de PHP
|
|
640
|
+
con bcmath y el de Go con int64), así que las sumas siempre cuadran al centavo:
|
|
641
|
+
|
|
642
|
+
```js
|
|
643
|
+
import {MONEY_ROUNDING, Money} from '@stackcraftmx/calcita/money';
|
|
644
|
+
|
|
645
|
+
const total = Money.fromString(order.total).plus(Money.fromNumber(order.shipping)); // del API, en texto o número
|
|
646
|
+
const withTax = total.times('1.16'); // redondea una vez, al centavo
|
|
647
|
+
const perPayment = total.dividedBy(3, {rounding: MONEY_ROUNDING.halfEven}); // redondeo bancario
|
|
648
|
+
total.format(); // "$1,234.50", en el idioma y la moneda de ToolkitProvider
|
|
649
|
+
total.amount(); // "1234.50", lo que se le manda al API
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
Los decimales salen de la moneda (`MXN` 2, `JPY` 0, `KWD` 3) y se pueden cambiar con `{currency, decimals}`. Truena en
|
|
653
|
+
vez de perder centavos: un texto que no es número, decimales de más, mezclar monedas o usar `+` y `>` en lugar de
|
|
654
|
+
`plus` e `isGreaterThan`.
|
|
655
|
+
|
|
656
|
+
## Desarrollo del paquete
|
|
657
|
+
|
|
658
|
+
Se trabaja con Node 22 y pnpm, las dos versiones fijadas en el paquete: `nvm use` toma la de `.nvmrc`, Volta la toma
|
|
659
|
+
sola de `package.json`, y Corepack (viene con Node 22) baja la versión de pnpm que dice `packageManager`.
|
|
660
|
+
|
|
661
|
+
```bash
|
|
662
|
+
nvm use
|
|
663
|
+
pnpm install
|
|
664
|
+
pnpm test # pruebas sin navegador (node --test)
|
|
665
|
+
pnpm run build # dist/ con un archivo por módulo y sus tipos en dist/types
|
|
666
|
+
pnpm run check # pruebas, build, cada componente pintado con el tema por omisión de MUI, el CLI, un proyecto en TypeScript y los ejemplos
|
|
667
|
+
pnpm run examples # construye el paquete y abre los ejemplos sin backend en http://localhost:5173
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
Los ejemplos ([examples/](examples/README.md)) usan el paquete ya construido, como un proyecto nuevo: tabla de servidor,
|
|
671
|
+
formulario, avisos, descargas y Excel, y métricas, con datos inventados en memoria. No viajan a npm.
|
|
672
|
+
|
|
673
|
+
## Probar sin instalar nada
|
|
674
|
+
|
|
675
|
+
Con Docker, los ejemplos se construyen y se sirven en una imagen; no hace falta Node ni pnpm:
|
|
676
|
+
|
|
677
|
+
```bash
|
|
678
|
+
docker compose up -d examples # construye y arranca: http://localhost:8095
|
|
679
|
+
docker compose down # lo apaga
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
Es la versión de producción (archivos construidos, servidos por nginx sin permisos de administrador), no el servidor de
|
|
683
|
+
desarrollo. `EXAMPLES_PORT=8100 docker compose up -d examples` cambia el puerto.
|
|
684
|
+
|
|
685
|
+
### Enseñarlo por internet (túnel de Cloudflare)
|
|
686
|
+
|
|
687
|
+
`scripts/tunnel.sh` publica los ejemplos con un túnel de Cloudflare. El token va en `tunnel/.cloudflared.token` (una
|
|
688
|
+
línea, fuera de git) y la dirección pública y su destino se configuran en el panel de Cloudflare; el destino es el puerto
|
|
689
|
+
de Docker (`http://localhost:8095`), no el servidor de desarrollo, que se rompe cada vez que cambian sus dependencias.
|
|
690
|
+
|
|
691
|
+
```bash
|
|
692
|
+
pnpm run tunnel:start # arranca y dice la dirección pública y a dónde apunta
|
|
693
|
+
pnpm run tunnel:status # ¿corre? y las dos direcciones responden
|
|
694
|
+
pnpm run tunnel:stop # lo apaga (solo el suyo, nunca el cloudflared de otro proyecto)
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
## Licencia
|
|
698
|
+
|
|
699
|
+
[FSL-1.1-MIT](LICENSE) (Functional Source License): se puede usar, copiar, modificar y poner en producción gratis, en
|
|
700
|
+
cualquier proyecto y empresa, también comercial. Lo único que no se permite es ofrecer Calcita (o algo que la sustituya)
|
|
701
|
+
como producto o servicio comercial que compita con ella. Dos años después de publicada, cada versión pasa sola a MIT.
|