@stackcraftmx/calcita 0.0.0-stage → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +110 -0
- package/README.md +611 -2
- package/cli/askQuestions.js +63 -0
- package/cli/calcita.js +150 -0
- package/cli/makeComponent.js +50 -0
- package/cli/makeForm.js +68 -0
- package/cli/makeModule.js +78 -0
- package/cli/makePage.js +62 -0
- package/cli/names.js +64 -0
- package/cli/newProject.js +103 -0
- package/cli/packageVersions.js +38 -0
- package/cli/projectAnswers.js +145 -0
- package/cli/projectConfig.js +38 -0
- package/cli/projectFiles.js +126 -0
- package/cli/screenLabels.js +41 -0
- package/cli/templateFiles.js +186 -0
- package/cli/templates/component/core/__ComponentName__.jsx.tpl +23 -0
- package/cli/templates/component/module/__ComponentName__.jsx.tpl +21 -0
- package/cli/templates/form/formik/__FormName__.jsx.tpl +50 -0
- package/cli/templates/form/hookForm/__FormName__.jsx.tpl +53 -0
- package/cli/templates/form/shared/__formName__Schema.js.tpl +20 -0
- package/cli/templates/form/shared/__formName__Texts.js.tpl +6 -0
- package/cli/templates/module/__Name__Page.jsx.tpl +75 -0
- package/cli/templates/module/__name__Api.js.tpl +39 -0
- package/cli/templates/module/__name__Texts.js.tpl +27 -0
- package/cli/templates/module/menu.js.tpl +21 -0
- package/cli/templates/module/routes.js.tpl +7 -0
- package/cli/templates/moduleServer/__name__Server.js.tpl +68 -0
- package/cli/templates/page/__PageName__Page.jsx.tpl +22 -0
- package/cli/templates/page/__pageName__PageTexts.js.tpl +23 -0
- package/cli/templates/project/README.md.tpl +55 -0
- package/cli/templates/project/dot-gitignore.tpl +11 -0
- package/cli/templates/project/index.html.tpl +20 -0
- package/cli/templates/project/jsconfig.json.tpl +16 -0
- package/cli/templates/project/pnpm-workspace.yaml.tpl +5 -0
- package/cli/templates/project/public/favicon.svg +1 -0
- package/cli/templates/project/public/icons/apple-touch-icon.png +0 -0
- package/cli/templates/project/public/icons/icon-192.png +0 -0
- package/cli/templates/project/public/icons/icon-512-maskable.png +0 -0
- package/cli/templates/project/public/icons/icon-512.png +0 -0
- package/cli/templates/project/public/manifest.webmanifest.tpl +17 -0
- package/cli/templates/project/src/app/AppProviders.jsx.tpl +102 -0
- package/cli/templates/project/src/app/AppShell.jsx.tpl +87 -0
- package/cli/templates/project/src/app/appRouter.jsx.tpl +49 -0
- package/cli/templates/project/src/app/appSettings.js.tpl +13 -0
- package/cli/templates/project/src/app/appTexts.js.tpl +15 -0
- package/cli/templates/project/src/app/combineTexts.js.tpl +31 -0
- package/cli/templates/project/src/app/i18n.js.tpl +19 -0
- package/cli/templates/project/src/app/shellTexts.js.tpl +16 -0
- package/cli/templates/project/src/core/AppLogo.jsx.tpl +12 -0
- package/cli/templates/project/src/core/accountConnector.js.tpl +36 -0
- package/cli/templates/project/src/core/apiClient.js.tpl +15 -0
- package/cli/templates/project/src/core/appPaths.js.tpl +11 -0
- package/cli/templates/project/src/core/index.js.tpl +8 -0
- package/cli/templates/project/src/fakeServer/networkDelay.js.tpl +40 -0
- package/cli/templates/project/src/fakeServer/serverText.js.tpl +20 -0
- package/cli/templates/project/src/main.jsx.tpl +24 -0
- package/cli/templates/project/src/modules/auth/ForgotPasswordPage.jsx.tpl +14 -0
- package/cli/templates/project/src/modules/auth/ResetPasswordPage.jsx.tpl +15 -0
- package/cli/templates/project/src/modules/auth/SignInPage.jsx.tpl +29 -0
- package/cli/templates/project/src/modules/auth/authTexts.js.tpl +6 -0
- package/cli/templates/project/src/modules/auth/routes.js.tpl +11 -0
- package/cli/templates/project/src/modules/home/HomePage.jsx.tpl +38 -0
- package/cli/templates/project/src/modules/home/homeTexts.js.tpl +29 -0
- package/cli/templates/project/src/modules/home/menu.js.tpl +17 -0
- package/cli/templates/project/src/modules/home/routes.js.tpl +4 -0
- package/cli/templates/project/src/modules/profile/ProfilePage.jsx.tpl +13 -0
- package/cli/templates/project/src/modules/profile/routes.js.tpl +6 -0
- package/cli/templates/project/vite.config.js.tpl +27 -0
- package/dist/DataTable/AuditTrailDialog.js +40 -0
- package/dist/DataTable/AuditTrailDialog.js.map +1 -0
- package/dist/DataTable/AuditTrailTable.js +87 -0
- package/dist/DataTable/AuditTrailTable.js.map +1 -0
- package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js +71 -0
- package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js.map +1 -0
- package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js +50 -0
- package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js.map +1 -0
- package/dist/DataTable/ColumnFilters/SortableFilterHeader.js +54 -0
- package/dist/DataTable/ColumnFilters/SortableFilterHeader.js.map +1 -0
- package/dist/DataTable/ColumnFilters/TextColumnFilter.js +24 -0
- package/dist/DataTable/ColumnFilters/TextColumnFilter.js.map +1 -0
- package/dist/DataTable/EmptyState.js +22 -0
- package/dist/DataTable/EmptyState.js.map +1 -0
- package/dist/DataTable/FilterChips.js +39 -0
- package/dist/DataTable/FilterChips.js.map +1 -0
- package/dist/DataTable/GoToPage.js +62 -0
- package/dist/DataTable/GoToPage.js.map +1 -0
- package/dist/DataTable/ServerTable.js +407 -0
- package/dist/DataTable/ServerTable.js.map +1 -0
- package/dist/DataTable/buildChipConfig.js +27 -0
- package/dist/DataTable/buildChipConfig.js.map +1 -0
- package/dist/DataTable/columns.js +122 -0
- package/dist/DataTable/columns.js.map +1 -0
- package/dist/DataTable/filterContext.js +15 -0
- package/dist/DataTable/filterContext.js.map +1 -0
- package/dist/DataTable/serverTableParams.js +19 -0
- package/dist/DataTable/serverTableParams.js.map +1 -0
- package/dist/DataTable/tableMachine.js +87 -0
- package/dist/DataTable/tableMachine.js.map +1 -0
- package/dist/DataTable/useDebouncedFilter.js +29 -0
- package/dist/DataTable/useDebouncedFilter.js.map +1 -0
- package/dist/DataTable/useTableState.js +132 -0
- package/dist/DataTable/useTableState.js.map +1 -0
- package/dist/access/Can.js +9 -0
- package/dist/access/Can.js.map +1 -0
- package/dist/access/PermissionMatrix.js +83 -0
- package/dist/access/PermissionMatrix.js.map +1 -0
- package/dist/access/RequireAccess.js +14 -0
- package/dist/access/RequireAccess.js.map +1 -0
- package/dist/access/accessRules.js +49 -0
- package/dist/access/accessRules.js.map +1 -0
- package/dist/access/permissionGroups.js +43 -0
- package/dist/access/permissionGroups.js.map +1 -0
- package/dist/access/useCan.js +12 -0
- package/dist/access/useCan.js.map +1 -0
- package/dist/account/AccountProvider.js +58 -0
- package/dist/account/AccountProvider.js.map +1 -0
- package/dist/account/AccountSecuritySection.js +81 -0
- package/dist/account/AccountSecuritySection.js.map +1 -0
- package/dist/account/DemoTotpCodeButton.js +26 -0
- package/dist/account/DemoTotpCodeButton.js.map +1 -0
- package/dist/account/ForgotPasswordScreen.js +26 -0
- package/dist/account/ForgotPasswordScreen.js.map +1 -0
- package/dist/account/ProfileScreen.js +108 -0
- package/dist/account/ProfileScreen.js.map +1 -0
- package/dist/account/ResetPasswordScreen.js +57 -0
- package/dist/account/ResetPasswordScreen.js.map +1 -0
- package/dist/account/SignInScreen.js +101 -0
- package/dist/account/SignInScreen.js.map +1 -0
- package/dist/account/accountConnector.js +31 -0
- package/dist/account/accountConnector.js.map +1 -0
- package/dist/account/demo/createDemoAccountConnector.js +368 -0
- package/dist/account/demo/createDemoAccountConnector.js.map +1 -0
- package/dist/account/demo/totp.js +61 -0
- package/dist/account/demo/totp.js.map +1 -0
- package/dist/account/restAccountConnector.js +117 -0
- package/dist/account/restAccountConnector.js.map +1 -0
- package/dist/account-demo.js +12 -0
- package/dist/account-demo.js.map +1 -0
- package/dist/account.js +25 -0
- package/dist/account.js.map +1 -0
- package/dist/adapters/i18next.js +7 -0
- package/dist/adapters/i18next.js.map +1 -0
- package/dist/adapters/nextNavigation.js +36 -0
- package/dist/adapters/nextNavigation.js.map +1 -0
- package/dist/adapters/reactRouter.js +7 -0
- package/dist/adapters/reactRouter.js.map +1 -0
- package/dist/adapters/reactRouterRoutes.js +48 -0
- package/dist/adapters/reactRouterRoutes.js.map +1 -0
- package/dist/api/ApiError.js +58 -0
- package/dist/api/ApiError.js.map +1 -0
- package/dist/api/createApiClient.js +226 -0
- package/dist/api/createApiClient.js.map +1 -0
- package/dist/api/staleChunks.js +47 -0
- package/dist/api/staleChunks.js.map +1 -0
- package/dist/appShell/AccountMenu.js +86 -0
- package/dist/appShell/AccountMenu.js.map +1 -0
- package/dist/appShell/AppLayout.js +493 -0
- package/dist/appShell/AppLayout.js.map +1 -0
- package/dist/appShell/AppearanceSettings.js +93 -0
- package/dist/appShell/AppearanceSettings.js.map +1 -0
- package/dist/appShell/AuthLayout.js +44 -0
- package/dist/appShell/AuthLayout.js.map +1 -0
- package/dist/appShell/BarActionButton.js +31 -0
- package/dist/appShell/BarActionButton.js.map +1 -0
- package/dist/appShell/BarActions.js +94 -0
- package/dist/appShell/BarActions.js.map +1 -0
- package/dist/appShell/BarCapsule.js +35 -0
- package/dist/appShell/BarCapsule.js.map +1 -0
- package/dist/appShell/HeaderTools.js +53 -0
- package/dist/appShell/HeaderTools.js.map +1 -0
- package/dist/appShell/MobileTabBar.js +346 -0
- package/dist/appShell/MobileTabBar.js.map +1 -0
- package/dist/appShell/SettingsMenu.js +41 -0
- package/dist/appShell/SettingsMenu.js.map +1 -0
- package/dist/appShell/SideMenu.js +217 -0
- package/dist/appShell/SideMenu.js.map +1 -0
- package/dist/appShell/SideMenuEntry.js +140 -0
- package/dist/appShell/SideMenuEntry.js.map +1 -0
- package/dist/appShell/SubmenuActionsMenu.js +71 -0
- package/dist/appShell/SubmenuActionsMenu.js.map +1 -0
- package/dist/appShell/TabBarEditor.js +55 -0
- package/dist/appShell/TabBarEditor.js.map +1 -0
- package/dist/appShell/TopMenu.js +80 -0
- package/dist/appShell/TopMenu.js.map +1 -0
- package/dist/appShell/appMenuContext.js +11 -0
- package/dist/appShell/appMenuContext.js.map +1 -0
- package/dist/appShell/barActionsSlot.js +26 -0
- package/dist/appShell/barActionsSlot.js.map +1 -0
- package/dist/appShell/barMenuPlacement.js +33 -0
- package/dist/appShell/barMenuPlacement.js.map +1 -0
- package/dist/appShell/menuItemText.js +33 -0
- package/dist/appShell/menuItemText.js.map +1 -0
- package/dist/appShell/pageTitle.js +45 -0
- package/dist/appShell/pageTitle.js.map +1 -0
- package/dist/appShell/shellSizes.js +38 -0
- package/dist/appShell/shellSizes.js.map +1 -0
- package/dist/appShell/tabBarRule.js +12 -0
- package/dist/appShell/tabBarRule.js.map +1 -0
- package/dist/appShell/tabBarScroll.js +23 -0
- package/dist/appShell/tabBarScroll.js.map +1 -0
- package/dist/appShell/useDrawerCollapsed.js +29 -0
- package/dist/appShell/useDrawerCollapsed.js.map +1 -0
- package/dist/appShell/useFittingActionCount.js +45 -0
- package/dist/appShell/useFittingActionCount.js.map +1 -0
- package/dist/appShell/usePinnedMobileTabs.js +32 -0
- package/dist/appShell/usePinnedMobileTabs.js.map +1 -0
- package/dist/appShell/useTabBarMinimized.js +33 -0
- package/dist/appShell/useTabBarMinimized.js.map +1 -0
- package/dist/auth/PasswordChecklist.js +44 -0
- package/dist/auth/PasswordChecklist.js.map +1 -0
- package/dist/auth/passwordRules.js +43 -0
- package/dist/auth/passwordRules.js.map +1 -0
- package/dist/calendar/EventCalendar.js +138 -0
- package/dist/calendar/EventCalendar.js.map +1 -0
- package/dist/calendar.js +6 -0
- package/dist/calendar.js.map +1 -0
- package/dist/charts.js +7 -0
- package/dist/charts.js.map +1 -0
- package/dist/date-pickers.js +8 -0
- package/dist/date-pickers.js.map +1 -0
- package/dist/datePickers/DateInput.js +75 -0
- package/dist/datePickers/DateInput.js.map +1 -0
- package/dist/datePickers/FormDateField.js +12 -0
- package/dist/datePickers/FormDateField.js.map +1 -0
- package/dist/dates.js +25 -0
- package/dist/dates.js.map +1 -0
- package/dist/dictionaries/dictionaries.js +48 -0
- package/dist/dictionaries/dictionaries.js.map +1 -0
- package/dist/downloads/DownloadManager.js +201 -0
- package/dist/downloads/DownloadManager.js.map +1 -0
- package/dist/downloads/downloadQueue.js +54 -0
- package/dist/downloads/downloadQueue.js.map +1 -0
- package/dist/downloads/downloadsMachine.js +77 -0
- package/dist/downloads/downloadsMachine.js.map +1 -0
- package/dist/excel/reportWorkbook.js +299 -0
- package/dist/excel/reportWorkbook.js.map +1 -0
- package/dist/excel.js +13 -0
- package/dist/excel.js.map +1 -0
- package/dist/feedback/ConfirmDialog.js +72 -0
- package/dist/feedback/ConfirmDialog.js.map +1 -0
- package/dist/feedback/ModalWaiting.js +23 -0
- package/dist/feedback/ModalWaiting.js.map +1 -0
- package/dist/feedback/NewBuildNotice.js +79 -0
- package/dist/feedback/NewBuildNotice.js.map +1 -0
- package/dist/feedback/StaleBuildBoundary.js +36 -0
- package/dist/feedback/StaleBuildBoundary.js.map +1 -0
- package/dist/feedback/Toaster.js +20 -0
- package/dist/feedback/Toaster.js.map +1 -0
- package/dist/feedback/confirmActionMachine.js +67 -0
- package/dist/feedback/confirmActionMachine.js.map +1 -0
- package/dist/feedback/toast.js +88 -0
- package/dist/feedback/toast.js.map +1 -0
- package/dist/feedback/useConfirmAction.js +40 -0
- package/dist/feedback/useConfirmAction.js.map +1 -0
- package/dist/filepond/FileDropzone.js +254 -0
- package/dist/filepond/FileDropzone.js.map +1 -0
- package/dist/filepond/pondServer.js +48 -0
- package/dist/filepond/pondServer.js.map +1 -0
- package/dist/filepond.js +10 -0
- package/dist/filepond.js.map +1 -0
- package/dist/files.js +43 -0
- package/dist/files.js.map +1 -0
- package/dist/formatting.js +177 -0
- package/dist/formatting.js.map +1 -0
- package/dist/forms/FormCatalogField.js +12 -0
- package/dist/forms/FormCatalogField.js.map +1 -0
- package/dist/forms/FormColorField.js +12 -0
- package/dist/forms/FormColorField.js.map +1 -0
- package/dist/forms/FormNumberField.js +12 -0
- package/dist/forms/FormNumberField.js.map +1 -0
- package/dist/forms/FormProblemAlert.js +15 -0
- package/dist/forms/FormProblemAlert.js.map +1 -0
- package/dist/forms/FormSelectField.js +12 -0
- package/dist/forms/FormSelectField.js.map +1 -0
- package/dist/forms/FormServerProblem.js +23 -0
- package/dist/forms/FormServerProblem.js.map +1 -0
- package/dist/forms/FormTextField.js +12 -0
- package/dist/forms/FormTextField.js.map +1 -0
- package/dist/forms/FormWizard.js +90 -0
- package/dist/forms/FormWizard.js.map +1 -0
- package/dist/forms/SubmitButton.js +14 -0
- package/dist/forms/SubmitButton.js.map +1 -0
- package/dist/forms/applyServerProblem.js +15 -0
- package/dist/forms/applyServerProblem.js.map +1 -0
- package/dist/forms/auth/ChangePasswordForm.js +46 -0
- package/dist/forms/auth/ChangePasswordForm.js.map +1 -0
- package/dist/forms/auth/ForgotPasswordForm.js +50 -0
- package/dist/forms/auth/ForgotPasswordForm.js.map +1 -0
- package/dist/forms/auth/SignInForm.js +48 -0
- package/dist/forms/auth/SignInForm.js.map +1 -0
- package/dist/forms/security/SecondStepForm.js +122 -0
- package/dist/forms/security/SecondStepForm.js.map +1 -0
- package/dist/forms/security/TwoStepVerificationCard.js +336 -0
- package/dist/forms/security/TwoStepVerificationCard.js.map +1 -0
- package/dist/forms/security/securityRules.js +28 -0
- package/dist/forms/security/securityRules.js.map +1 -0
- package/dist/forms/serverProblemFields.js +25 -0
- package/dist/forms/serverProblemFields.js.map +1 -0
- package/dist/forms/useFormikField.js +16 -0
- package/dist/forms/useFormikField.js.map +1 -0
- package/dist/forms/validation.js +55 -0
- package/dist/forms/validation.js.map +1 -0
- package/dist/forms/validationMessages.js +16 -0
- package/dist/forms/validationMessages.js.map +1 -0
- package/dist/forms.js +57 -0
- package/dist/forms.js.map +1 -0
- package/dist/hookForm/FormCatalogField.js +12 -0
- package/dist/hookForm/FormCatalogField.js.map +1 -0
- package/dist/hookForm/FormColorField.js +12 -0
- package/dist/hookForm/FormColorField.js.map +1 -0
- package/dist/hookForm/FormNumberField.js +12 -0
- package/dist/hookForm/FormNumberField.js.map +1 -0
- package/dist/hookForm/FormProblemAlert.js +17 -0
- package/dist/hookForm/FormProblemAlert.js.map +1 -0
- package/dist/hookForm/FormSelectField.js +12 -0
- package/dist/hookForm/FormSelectField.js.map +1 -0
- package/dist/hookForm/FormTextField.js +12 -0
- package/dist/hookForm/FormTextField.js.map +1 -0
- package/dist/hookForm/SubmitButton.js +15 -0
- package/dist/hookForm/SubmitButton.js.map +1 -0
- package/dist/hookForm/applyServerProblem.js +21 -0
- package/dist/hookForm/applyServerProblem.js.map +1 -0
- package/dist/hookForm/useHookFormField.js +19 -0
- package/dist/hookForm/useHookFormField.js.map +1 -0
- package/dist/i18next.js +5 -0
- package/dist/i18next.js.map +1 -0
- package/dist/identifiers.js +8 -0
- package/dist/identifiers.js.map +1 -0
- package/dist/inbox/InboxLayout.js +68 -0
- package/dist/inbox/InboxLayout.js.map +1 -0
- package/dist/inbox/MessageList.js +64 -0
- package/dist/inbox/MessageList.js.map +1 -0
- package/dist/inbox/MessageView.js +53 -0
- package/dist/inbox/MessageView.js.map +1 -0
- package/dist/inbox/inboxDates.js +8 -0
- package/dist/inbox/inboxDates.js.map +1 -0
- package/dist/index.js +383 -0
- package/dist/index.js.map +1 -0
- package/dist/inputs/CatalogInput.js +62 -0
- package/dist/inputs/CatalogInput.js.map +1 -0
- package/dist/inputs/ColorInput.js +108 -0
- package/dist/inputs/ColorInput.js.map +1 -0
- package/dist/inputs/FieldFrame.js +20 -0
- package/dist/inputs/FieldFrame.js.map +1 -0
- package/dist/inputs/FormSection.js +105 -0
- package/dist/inputs/FormSection.js.map +1 -0
- package/dist/inputs/NumberInput.js +69 -0
- package/dist/inputs/NumberInput.js.map +1 -0
- package/dist/inputs/SelectInput.js +66 -0
- package/dist/inputs/SelectInput.js.map +1 -0
- package/dist/inputs/TextInput.js +97 -0
- package/dist/inputs/TextInput.js.map +1 -0
- package/dist/inputs/colorContrast.js +46 -0
- package/dist/inputs/colorContrast.js.map +1 -0
- package/dist/inputs/formLayoutContext.js +9 -0
- package/dist/inputs/formLayoutContext.js.map +1 -0
- package/dist/inputs/numberText.js +48 -0
- package/dist/inputs/numberText.js.map +1 -0
- package/dist/kanban/KanbanBoard.js +113 -0
- package/dist/kanban/KanbanBoard.js.map +1 -0
- package/dist/kanban/kanbanMoves.js +29 -0
- package/dist/kanban/kanbanMoves.js.map +1 -0
- package/dist/kanban.js +9 -0
- package/dist/kanban.js.map +1 -0
- package/dist/laravel/csrfRetry.js +18 -0
- package/dist/laravel/csrfRetry.js.map +1 -0
- package/dist/laravel.js +6 -0
- package/dist/laravel.js.map +1 -0
- package/dist/lastListUrl.js +35 -0
- package/dist/lastListUrl.js.map +1 -0
- package/dist/locales/en.js +714 -0
- package/dist/locales/en.js.map +1 -0
- package/dist/locales/es.js +714 -0
- package/dist/locales/es.js.map +1 -0
- package/dist/maps/MapView.js +96 -0
- package/dist/maps/MapView.js.map +1 -0
- package/dist/maps/mapMarkers.js +19 -0
- package/dist/maps/mapMarkers.js.map +1 -0
- package/dist/maps.js +10 -0
- package/dist/maps.js.map +1 -0
- package/dist/money/money.js +380 -0
- package/dist/money/money.js.map +1 -0
- package/dist/money.js +6 -0
- package/dist/money.js.map +1 -0
- package/dist/navigation/appMenu.js +93 -0
- package/dist/navigation/appMenu.js.map +1 -0
- package/dist/navigation/useMenuBadges.js +45 -0
- package/dist/navigation/useMenuBadges.js.map +1 -0
- package/dist/navigation.js +30 -0
- package/dist/navigation.js.map +1 -0
- package/dist/navigationTrail.js +82 -0
- package/dist/navigationTrail.js.map +1 -0
- package/dist/next.js +5 -0
- package/dist/next.js.map +1 -0
- package/dist/observability/buildWatch.js +19 -0
- package/dist/observability/buildWatch.js.map +1 -0
- package/dist/observability/logger.js +43 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/publishedBuild.js +39 -0
- package/dist/observability/publishedBuild.js.map +1 -0
- package/dist/observability/usePublishedBuildWatch.js +76 -0
- package/dist/observability/usePublishedBuildWatch.js.map +1 -0
- package/dist/passkeys.js +7 -0
- package/dist/passkeys.js.map +1 -0
- package/dist/periodRanges.js +33 -0
- package/dist/periodRanges.js.map +1 -0
- package/dist/problems.js +51 -0
- package/dist/problems.js.map +1 -0
- package/dist/pwa/InstallAppSetting.js +33 -0
- package/dist/pwa/InstallAppSetting.js.map +1 -0
- package/dist/pwa/InstallInstructionsDialog.js +35 -0
- package/dist/pwa/InstallInstructionsDialog.js.map +1 -0
- package/dist/pwa/InstallPromptBanner.js +64 -0
- package/dist/pwa/InstallPromptBanner.js.map +1 -0
- package/dist/pwa/installInstructions.js +60 -0
- package/dist/pwa/installInstructions.js.map +1 -0
- package/dist/pwa/useInstallPrompt.js +70 -0
- package/dist/pwa/useInstallPrompt.js.map +1 -0
- package/dist/react-hook-form.js +30 -0
- package/dist/react-hook-form.js.map +1 -0
- package/dist/react-router.js +10 -0
- package/dist/react-router.js.map +1 -0
- package/dist/security/ActivityLog.js +79 -0
- package/dist/security/ActivityLog.js.map +1 -0
- package/dist/security/RecoveryCodesDialog.js +84 -0
- package/dist/security/RecoveryCodesDialog.js.map +1 -0
- package/dist/security/SessionsCard.js +81 -0
- package/dist/security/SessionsCard.js.map +1 -0
- package/dist/security/passkeys.js +39 -0
- package/dist/security/passkeys.js.map +1 -0
- package/dist/table.js +35 -0
- package/dist/table.js.map +1 -0
- package/dist/theme/androidDevice.js +16 -0
- package/dist/theme/androidDevice.js.map +1 -0
- package/dist/theme/appleTracking.js +34 -0
- package/dist/theme/appleTracking.js.map +1 -0
- package/dist/theme/components/MuiAppBar.js +27 -0
- package/dist/theme/components/MuiAppBar.js.map +1 -0
- package/dist/theme/components/MuiBackdrop.js +13 -0
- package/dist/theme/components/MuiBackdrop.js.map +1 -0
- package/dist/theme/components/MuiButton.js +25 -0
- package/dist/theme/components/MuiButton.js.map +1 -0
- package/dist/theme/components/MuiButtonBase.js +16 -0
- package/dist/theme/components/MuiButtonBase.js.map +1 -0
- package/dist/theme/components/MuiChip.js +30 -0
- package/dist/theme/components/MuiChip.js.map +1 -0
- package/dist/theme/components/MuiDataGrid.js +30 -0
- package/dist/theme/components/MuiDataGrid.js.map +1 -0
- package/dist/theme/components/MuiDrawer.js +18 -0
- package/dist/theme/components/MuiDrawer.js.map +1 -0
- package/dist/theme/components/MuiMenuItem.js +17 -0
- package/dist/theme/components/MuiMenuItem.js.map +1 -0
- package/dist/theme/components/MuiTypography.js +22 -0
- package/dist/theme/components/MuiTypography.js.map +1 -0
- package/dist/theme/components/glassComponents.js +885 -0
- package/dist/theme/components/glassComponents.js.map +1 -0
- package/dist/theme/components/minimalComponents.js +146 -0
- package/dist/theme/components/minimalComponents.js.map +1 -0
- package/dist/theme/components/paletteOf.js +7 -0
- package/dist/theme/components/paletteOf.js.map +1 -0
- package/dist/theme/createToolkitTheme.js +100 -0
- package/dist/theme/createToolkitTheme.js.map +1 -0
- package/dist/theme/glassSurface.js +328 -0
- package/dist/theme/glassSurface.js.map +1 -0
- package/dist/theme/glassToasterStyles.js +50 -0
- package/dist/theme/glassToasterStyles.js.map +1 -0
- package/dist/theme/mergeComponents.js +42 -0
- package/dist/theme/mergeComponents.js.map +1 -0
- package/dist/theme/stackcraftPalette.js +59 -0
- package/dist/theme/stackcraftPalette.js.map +1 -0
- package/dist/theme/toolkitComponents.js +26 -0
- package/dist/theme/toolkitComponents.js.map +1 -0
- package/dist/timeline.js +8 -0
- package/dist/timeline.js.map +1 -0
- package/dist/toolkit/ToolkitProvider.js +49 -0
- package/dist/toolkit/ToolkitProvider.js.map +1 -0
- package/dist/toolkit/browserNavigation.js +34 -0
- package/dist/toolkit/browserNavigation.js.map +1 -0
- package/dist/toolkit/toolkitContext.js +19 -0
- package/dist/toolkit/toolkitContext.js.map +1 -0
- package/dist/toolkit/toolkitSettings.js +87 -0
- package/dist/toolkit/toolkitSettings.js.map +1 -0
- package/dist/toolkit/useToolkitTranslation.js +18 -0
- package/dist/toolkit/useToolkitTranslation.js.map +1 -0
- package/dist/types/DataTable/AuditTrailDialog.d.ts +32 -0
- package/dist/types/DataTable/AuditTrailTable.d.ts +28 -0
- package/dist/types/DataTable/ColumnFilters/HeaderFilterPopover.d.ts +8 -0
- package/dist/types/DataTable/ColumnFilters/MultiSelectColumnFilter.d.ts +16 -0
- package/dist/types/DataTable/ColumnFilters/SortableFilterHeader.d.ts +26 -0
- package/dist/types/DataTable/ColumnFilters/TextColumnFilter.d.ts +8 -0
- package/dist/types/DataTable/ColumnFilters/index.d.ts +4 -0
- package/dist/types/DataTable/EmptyState.d.ts +8 -0
- package/dist/types/DataTable/FilterChips.d.ts +15 -0
- package/dist/types/DataTable/GoToPage.d.ts +8 -0
- package/dist/types/DataTable/ServerTable.d.ts +110 -0
- package/dist/types/DataTable/buildChipConfig.d.ts +22 -0
- package/dist/types/DataTable/columns.d.ts +93 -0
- package/dist/types/DataTable/filterContext.d.ts +13 -0
- package/dist/types/DataTable/index.d.ts +13 -0
- package/dist/types/DataTable/serverTableParams.d.ts +16 -0
- package/dist/types/DataTable/tableMachine.d.ts +41 -0
- package/dist/types/DataTable/useDebouncedFilter.d.ts +8 -0
- package/dist/types/DataTable/useTableState.d.ts +93 -0
- package/dist/types/access/Can.d.ts +11 -0
- package/dist/types/access/PermissionMatrix.d.ts +21 -0
- package/dist/types/access/RequireAccess.d.ts +11 -0
- package/dist/types/access/accessRules.d.ts +24 -0
- package/dist/types/access/permissionGroups.d.ts +56 -0
- package/dist/types/access/useCan.d.ts +11 -0
- package/dist/types/account/AccountProvider.d.ts +27 -0
- package/dist/types/account/AccountSecuritySection.d.ts +7 -0
- package/dist/types/account/DemoTotpCodeButton.d.ts +6 -0
- package/dist/types/account/ForgotPasswordScreen.d.ts +15 -0
- package/dist/types/account/ProfileScreen.d.ts +13 -0
- package/dist/types/account/ResetPasswordScreen.d.ts +19 -0
- package/dist/types/account/SignInScreen.d.ts +25 -0
- package/dist/types/account/accountConnector.d.ts +263 -0
- package/dist/types/account/demo/createDemoAccountConnector.d.ts +30 -0
- package/dist/types/account/demo/totp.d.ts +45 -0
- package/dist/types/account/restAccountConnector.d.ts +49 -0
- package/dist/types/account-demo.d.ts +2 -0
- package/dist/types/account.d.ts +16 -0
- package/dist/types/adapters/i18next.d.ts +11 -0
- package/dist/types/adapters/nextNavigation.d.ts +33 -0
- package/dist/types/adapters/reactRouter.d.ts +6 -0
- package/dist/types/adapters/reactRouterRoutes.d.ts +30 -0
- package/dist/types/api/ApiError.d.ts +42 -0
- package/dist/types/api/createApiClient.d.ts +146 -0
- package/dist/types/api/staleChunks.d.ts +15 -0
- package/dist/types/appShell/AccountMenu.d.ts +28 -0
- package/dist/types/appShell/AppLayout.d.ts +66 -0
- package/dist/types/appShell/AppearanceSettings.d.ts +34 -0
- package/dist/types/appShell/AuthLayout.d.ts +21 -0
- package/dist/types/appShell/BarActionButton.d.ts +15 -0
- package/dist/types/appShell/BarActions.d.ts +18 -0
- package/dist/types/appShell/BarCapsule.d.ts +12 -0
- package/dist/types/appShell/HeaderTools.d.ts +27 -0
- package/dist/types/appShell/MobileTabBar.d.ts +17 -0
- package/dist/types/appShell/SettingsMenu.d.ts +13 -0
- package/dist/types/appShell/SideMenu.d.ts +31 -0
- package/dist/types/appShell/SideMenuEntry.d.ts +17 -0
- package/dist/types/appShell/SubmenuActionsMenu.d.ts +24 -0
- package/dist/types/appShell/TabBarEditor.d.ts +13 -0
- package/dist/types/appShell/TopMenu.d.ts +7 -0
- package/dist/types/appShell/appMenuContext.d.ts +9 -0
- package/dist/types/appShell/barActionsSlot.d.ts +35 -0
- package/dist/types/appShell/barMenuPlacement.d.ts +9 -0
- package/dist/types/appShell/menuItemText.d.ts +55 -0
- package/dist/types/appShell/pageTitle.d.ts +26 -0
- package/dist/types/appShell/shellSizes.d.ts +45 -0
- package/dist/types/appShell/tabBarRule.d.ts +5 -0
- package/dist/types/appShell/tabBarScroll.d.ts +26 -0
- package/dist/types/appShell/useDrawerCollapsed.d.ts +8 -0
- package/dist/types/appShell/useFittingActionCount.d.ts +7 -0
- package/dist/types/appShell/usePinnedMobileTabs.d.ts +7 -0
- package/dist/types/appShell/useTabBarMinimized.d.ts +8 -0
- package/dist/types/auth/PasswordChecklist.d.ts +11 -0
- package/dist/types/auth/passwordRules.d.ts +34 -0
- package/dist/types/calendar/EventCalendar.d.ts +46 -0
- package/dist/types/calendar.d.ts +1 -0
- package/dist/types/charts.d.ts +2 -0
- package/dist/types/date-pickers.d.ts +2 -0
- package/dist/types/datePickers/DateInput.d.ts +39 -0
- package/dist/types/datePickers/FormDateField.d.ts +7 -0
- package/dist/types/dates.d.ts +18 -0
- package/dist/types/dictionaries/dictionaries.d.ts +54 -0
- package/dist/types/downloads/DownloadManager.d.ts +1 -0
- package/dist/types/downloads/downloadQueue.d.ts +45 -0
- package/dist/types/downloads/downloadsMachine.d.ts +10 -0
- package/dist/types/downloads/index.d.ts +3 -0
- package/dist/types/excel/reportWorkbook.d.ts +157 -0
- package/dist/types/excel.d.ts +1 -0
- package/dist/types/feedback/ConfirmDialog.d.ts +29 -0
- package/dist/types/feedback/ModalWaiting.d.ts +8 -0
- package/dist/types/feedback/NewBuildNotice.d.ts +18 -0
- package/dist/types/feedback/StaleBuildBoundary.d.ts +21 -0
- package/dist/types/feedback/Toaster.d.ts +1 -0
- package/dist/types/feedback/confirmActionMachine.d.ts +19 -0
- package/dist/types/feedback/index.d.ts +8 -0
- package/dist/types/feedback/toast.d.ts +100 -0
- package/dist/types/feedback/useConfirmAction.d.ts +33 -0
- package/dist/types/filepond/FileDropzone.d.ts +59 -0
- package/dist/types/filepond/pondServer.d.ts +17 -0
- package/dist/types/filepond.d.ts +3 -0
- package/dist/types/files.d.ts +29 -0
- package/dist/types/formatting.d.ts +106 -0
- package/dist/types/forms/FormCatalogField.d.ts +6 -0
- package/dist/types/forms/FormColorField.d.ts +6 -0
- package/dist/types/forms/FormNumberField.d.ts +6 -0
- package/dist/types/forms/FormProblemAlert.d.ts +6 -0
- package/dist/types/forms/FormSelectField.d.ts +6 -0
- package/dist/types/forms/FormServerProblem.d.ts +8 -0
- package/dist/types/forms/FormTextField.d.ts +6 -0
- package/dist/types/forms/FormWizard.d.ts +20 -0
- package/dist/types/forms/SubmitButton.d.ts +9 -0
- package/dist/types/forms/applyServerProblem.d.ts +9 -0
- package/dist/types/forms/auth/ChangePasswordForm.d.ts +15 -0
- package/dist/types/forms/auth/ForgotPasswordForm.d.ts +12 -0
- package/dist/types/forms/auth/SignInForm.d.ts +18 -0
- package/dist/types/forms/index.d.ts +19 -0
- package/dist/types/forms/security/SecondStepForm.d.ts +28 -0
- package/dist/types/forms/security/TwoStepVerificationCard.d.ts +81 -0
- package/dist/types/forms/security/securityRules.d.ts +24 -0
- package/dist/types/forms/serverProblemFields.d.ts +19 -0
- package/dist/types/forms/useFormikField.d.ts +11 -0
- package/dist/types/forms/validation.d.ts +251 -0
- package/dist/types/forms/validationMessages.d.ts +12 -0
- package/dist/types/forms.d.ts +2 -0
- package/dist/types/hookForm/FormCatalogField.d.ts +8 -0
- package/dist/types/hookForm/FormColorField.d.ts +8 -0
- package/dist/types/hookForm/FormNumberField.d.ts +8 -0
- package/dist/types/hookForm/FormProblemAlert.d.ts +7 -0
- package/dist/types/hookForm/FormSelectField.d.ts +8 -0
- package/dist/types/hookForm/FormTextField.d.ts +8 -0
- package/dist/types/hookForm/SubmitButton.d.ts +21 -0
- package/dist/types/hookForm/applyServerProblem.d.ts +10 -0
- package/dist/types/hookForm/useHookFormField.d.ts +13 -0
- package/dist/types/i18next.d.ts +1 -0
- package/dist/types/identifiers.d.ts +2 -0
- package/dist/types/inbox/InboxLayout.d.ts +26 -0
- package/dist/types/inbox/MessageList.d.ts +27 -0
- package/dist/types/inbox/MessageView.d.ts +23 -0
- package/dist/types/inbox/inboxDates.d.ts +6 -0
- package/dist/types/index.d.ts +84 -0
- package/dist/types/inputs/CatalogInput.d.ts +41 -0
- package/dist/types/inputs/ColorInput.d.ts +28 -0
- package/dist/types/inputs/FieldFrame.d.ts +14 -0
- package/dist/types/inputs/FormSection.d.ts +29 -0
- package/dist/types/inputs/NumberInput.d.ts +36 -0
- package/dist/types/inputs/SelectInput.d.ts +34 -0
- package/dist/types/inputs/TextInput.d.ts +60 -0
- package/dist/types/inputs/colorContrast.d.ts +18 -0
- package/dist/types/inputs/formLayoutContext.d.ts +3 -0
- package/dist/types/inputs/numberText.d.ts +25 -0
- package/dist/types/kanban/KanbanBoard.d.ts +33 -0
- package/dist/types/kanban/kanbanMoves.d.ts +38 -0
- package/dist/types/kanban.d.ts +2 -0
- package/dist/types/laravel/csrfRetry.d.ts +21 -0
- package/dist/types/laravel.d.ts +1 -0
- package/dist/types/lastListUrl.d.ts +20 -0
- package/dist/types/locales/en.d.ts +711 -0
- package/dist/types/locales/es.d.ts +711 -0
- package/dist/types/maps/MapView.d.ts +32 -0
- package/dist/types/maps/mapMarkers.d.ts +23 -0
- package/dist/types/maps.d.ts +2 -0
- package/dist/types/money/money.d.ts +203 -0
- package/dist/types/money.d.ts +1 -0
- package/dist/types/navigation/appMenu.d.ts +92 -0
- package/dist/types/navigation/useMenuBadges.d.ts +16 -0
- package/dist/types/navigation.d.ts +22 -0
- package/dist/types/navigationTrail.d.ts +49 -0
- package/dist/types/next.d.ts +1 -0
- package/dist/types/observability/buildWatch.d.ts +28 -0
- package/dist/types/observability/logger.d.ts +19 -0
- package/dist/types/observability/publishedBuild.d.ts +35 -0
- package/dist/types/observability/usePublishedBuildWatch.d.ts +16 -0
- package/dist/types/passkeys.d.ts +1 -0
- package/dist/types/periodRanges.d.ts +32 -0
- package/dist/types/problems.d.ts +31 -0
- package/dist/types/pwa/InstallAppSetting.d.ts +1 -0
- package/dist/types/pwa/InstallInstructionsDialog.d.ts +18 -0
- package/dist/types/pwa/InstallPromptBanner.d.ts +7 -0
- package/dist/types/pwa/installInstructions.d.ts +52 -0
- package/dist/types/pwa/useInstallPrompt.d.ts +12 -0
- package/dist/types/react-hook-form.d.ts +11 -0
- package/dist/types/react-router.d.ts +2 -0
- package/dist/types/security/ActivityLog.d.ts +31 -0
- package/dist/types/security/RecoveryCodesDialog.d.ts +11 -0
- package/dist/types/security/SessionsCard.d.ts +22 -0
- package/dist/types/security/passkeys.d.ts +18 -0
- package/dist/types/table.d.ts +1 -0
- package/dist/types/theme/androidDevice.d.ts +11 -0
- package/dist/types/theme/appleTracking.d.ts +17 -0
- package/dist/types/theme/components/MuiAppBar.d.ts +13 -0
- package/dist/types/theme/components/MuiBackdrop.d.ts +11 -0
- package/dist/types/theme/components/MuiButton.d.ts +27 -0
- package/dist/types/theme/components/MuiButtonBase.d.ts +14 -0
- package/dist/types/theme/components/MuiChip.d.ts +29 -0
- package/dist/types/theme/components/MuiDataGrid.d.ts +45 -0
- package/dist/types/theme/components/MuiDrawer.d.ts +13 -0
- package/dist/types/theme/components/MuiMenuItem.d.ts +17 -0
- package/dist/types/theme/components/MuiTypography.d.ts +20 -0
- package/dist/types/theme/components/glassComponents.d.ts +8 -0
- package/dist/types/theme/components/minimalComponents.d.ts +22 -0
- package/dist/types/theme/components/paletteOf.d.ts +5 -0
- package/dist/types/theme/createToolkitTheme.d.ts +48 -0
- package/dist/types/theme/glassSurface.d.ts +247 -0
- package/dist/types/theme/glassToasterStyles.d.ts +7 -0
- package/dist/types/theme/mergeComponents.d.ts +15 -0
- package/dist/types/theme/stackcraftPalette.d.ts +142 -0
- package/dist/types/theme/toolkitComponents.d.ts +4 -0
- package/dist/types/timeline.d.ts +2 -0
- package/dist/types/toolkit/ToolkitProvider.d.ts +31 -0
- package/dist/types/toolkit/browserNavigation.d.ts +32 -0
- package/dist/types/toolkit/toolkitContext.d.ts +28 -0
- package/dist/types/toolkit/toolkitSettings.d.ts +68 -0
- package/dist/types/toolkit/useToolkitTranslation.d.ts +10 -0
- package/dist/types/ui/actions/CopyButton.d.ts +13 -0
- package/dist/types/ui/actions/DownloadMenu.d.ts +50 -0
- package/dist/types/ui/actions/SecretField.d.ts +13 -0
- package/dist/types/ui/filters/DateRangeFilter.d.ts +16 -0
- package/dist/types/ui/filters/PeriodRangeSelector.d.ts +28 -0
- package/dist/types/ui/filters/QuickFilters.d.ts +21 -0
- package/dist/types/ui/filters/SegmentedControl.d.ts +44 -0
- package/dist/types/ui/index.d.ts +33 -0
- package/dist/types/ui/labels/DictionaryText.d.ts +7 -0
- package/dist/types/ui/labels/StatusChip.d.ts +21 -0
- package/dist/types/ui/labels/Tag.d.ts +19 -0
- package/dist/types/ui/layout/CollapsibleSection.d.ts +15 -0
- package/dist/types/ui/layout/ContentDialog.d.ts +13 -0
- package/dist/types/ui/layout/DefinitionList.d.ts +15 -0
- package/dist/types/ui/layout/DetailHeader.d.ts +15 -0
- package/dist/types/ui/layout/ErrorPage.d.ts +22 -0
- package/dist/types/ui/layout/FullPageLoader.d.ts +1 -0
- package/dist/types/ui/layout/GlassLensFilter.d.ts +1 -0
- package/dist/types/ui/layout/GlassPanel.d.ts +11 -0
- package/dist/types/ui/layout/PageHeader.d.ts +15 -0
- package/dist/types/ui/layout/PageHeading.d.ts +18 -0
- package/dist/types/ui/layout/ProfileHeader.d.ts +17 -0
- package/dist/types/ui/layout/ScrollableRow.d.ts +33 -0
- package/dist/types/ui/layout/SectionCard.d.ts +11 -0
- package/dist/types/ui/layout/appBarHeight.d.ts +13 -0
- package/dist/types/ui/metrics/BarList.d.ts +19 -0
- package/dist/types/ui/metrics/CalendarHeatmap.d.ts +28 -0
- package/dist/types/ui/metrics/ChartTooltip.d.ts +5 -0
- package/dist/types/ui/metrics/ColumnChart.d.ts +35 -0
- package/dist/types/ui/metrics/MetricCard.d.ts +31 -0
- package/dist/types/ui/metrics/TableToggle.d.ts +7 -0
- package/dist/types/ui/metrics/barListLabels.d.ts +17 -0
- package/dist/types/ui/metrics/heatmapScale.d.ts +45 -0
- package/dist/types/ui/navigation/BackButton.d.ts +11 -0
- package/dist/types/ui/navigation/ColorSchemeToggle.d.ts +7 -0
- package/dist/types/ui/navigation/DocumentTitle.d.ts +6 -0
- package/dist/types/ui/navigation/FontSizeToggle.d.ts +6 -0
- package/dist/types/ui/navigation/LanguageToggle.d.ts +8 -0
- package/dist/types/ui/navigation/PageBreadcrumbs.d.ts +9 -0
- package/dist/types/ui/navigation/colorMode.d.ts +18 -0
- package/dist/types/ui/navigation/fontSizeLevels.d.ts +25 -0
- package/dist/types/ui/navigation/useFontSize.d.ts +10 -0
- package/dist/types/ui/timeline/GroupedTimeline.d.ts +38 -0
- package/dist/types/ui/timeline/timelineDot.d.ts +19 -0
- package/dist/types/upload/FileDropzone.d.ts +34 -0
- package/dist/types/upload/fileRules.d.ts +51 -0
- package/dist/types/upload/uploadMachine.d.ts +23 -0
- package/dist/types/upload/uploadWithProgress.d.ts +16 -0
- package/dist/ui/actions/CopyButton.js +28 -0
- package/dist/ui/actions/CopyButton.js.map +1 -0
- package/dist/ui/actions/DownloadMenu.js +163 -0
- package/dist/ui/actions/DownloadMenu.js.map +1 -0
- package/dist/ui/actions/SecretField.js +57 -0
- package/dist/ui/actions/SecretField.js.map +1 -0
- package/dist/ui/filters/DateRangeFilter.js +86 -0
- package/dist/ui/filters/DateRangeFilter.js.map +1 -0
- package/dist/ui/filters/PeriodRangeSelector.js +56 -0
- package/dist/ui/filters/PeriodRangeSelector.js.map +1 -0
- package/dist/ui/filters/QuickFilters.js +91 -0
- package/dist/ui/filters/QuickFilters.js.map +1 -0
- package/dist/ui/filters/SegmentedControl.js +80 -0
- package/dist/ui/filters/SegmentedControl.js.map +1 -0
- package/dist/ui/labels/DictionaryText.js +11 -0
- package/dist/ui/labels/DictionaryText.js.map +1 -0
- package/dist/ui/labels/StatusChip.js +52 -0
- package/dist/ui/labels/StatusChip.js.map +1 -0
- package/dist/ui/labels/Tag.js +26 -0
- package/dist/ui/labels/Tag.js.map +1 -0
- package/dist/ui/layout/CollapsibleSection.js +48 -0
- package/dist/ui/layout/CollapsibleSection.js.map +1 -0
- package/dist/ui/layout/ContentDialog.js +97 -0
- package/dist/ui/layout/ContentDialog.js.map +1 -0
- package/dist/ui/layout/DefinitionList.js +30 -0
- package/dist/ui/layout/DefinitionList.js.map +1 -0
- package/dist/ui/layout/DetailHeader.js +27 -0
- package/dist/ui/layout/DetailHeader.js.map +1 -0
- package/dist/ui/layout/ErrorPage.js +40 -0
- package/dist/ui/layout/ErrorPage.js.map +1 -0
- package/dist/ui/layout/FullPageLoader.js +13 -0
- package/dist/ui/layout/FullPageLoader.js.map +1 -0
- package/dist/ui/layout/GlassLensFilter.js +53 -0
- package/dist/ui/layout/GlassLensFilter.js.map +1 -0
- package/dist/ui/layout/GlassPanel.js +18 -0
- package/dist/ui/layout/GlassPanel.js.map +1 -0
- package/dist/ui/layout/PageHeader.js +23 -0
- package/dist/ui/layout/PageHeader.js.map +1 -0
- package/dist/ui/layout/PageHeading.js +51 -0
- package/dist/ui/layout/PageHeading.js.map +1 -0
- package/dist/ui/layout/ProfileHeader.js +64 -0
- package/dist/ui/layout/ProfileHeader.js.map +1 -0
- package/dist/ui/layout/ScrollableRow.js +156 -0
- package/dist/ui/layout/ScrollableRow.js.map +1 -0
- package/dist/ui/layout/SectionCard.js +18 -0
- package/dist/ui/layout/SectionCard.js.map +1 -0
- package/dist/ui/layout/appBarHeight.js +42 -0
- package/dist/ui/layout/appBarHeight.js.map +1 -0
- package/dist/ui/metrics/BarList.js +89 -0
- package/dist/ui/metrics/BarList.js.map +1 -0
- package/dist/ui/metrics/CalendarHeatmap.js +131 -0
- package/dist/ui/metrics/CalendarHeatmap.js.map +1 -0
- package/dist/ui/metrics/ChartTooltip.js +16 -0
- package/dist/ui/metrics/ChartTooltip.js.map +1 -0
- package/dist/ui/metrics/ColumnChart.js +110 -0
- package/dist/ui/metrics/ColumnChart.js.map +1 -0
- package/dist/ui/metrics/MetricCard.js +64 -0
- package/dist/ui/metrics/MetricCard.js.map +1 -0
- package/dist/ui/metrics/TableToggle.js +13 -0
- package/dist/ui/metrics/TableToggle.js.map +1 -0
- package/dist/ui/metrics/barListLabels.js +9 -0
- package/dist/ui/metrics/barListLabels.js.map +1 -0
- package/dist/ui/metrics/heatmapScale.js +67 -0
- package/dist/ui/metrics/heatmapScale.js.map +1 -0
- package/dist/ui/navigation/BackButton.js +28 -0
- package/dist/ui/navigation/BackButton.js.map +1 -0
- package/dist/ui/navigation/ColorSchemeToggle.js +37 -0
- package/dist/ui/navigation/ColorSchemeToggle.js.map +1 -0
- package/dist/ui/navigation/DocumentTitle.js +11 -0
- package/dist/ui/navigation/DocumentTitle.js.map +1 -0
- package/dist/ui/navigation/FontSizeToggle.js +40 -0
- package/dist/ui/navigation/FontSizeToggle.js.map +1 -0
- package/dist/ui/navigation/LanguageToggle.js +27 -0
- package/dist/ui/navigation/LanguageToggle.js.map +1 -0
- package/dist/ui/navigation/PageBreadcrumbs.js +51 -0
- package/dist/ui/navigation/PageBreadcrumbs.js.map +1 -0
- package/dist/ui/navigation/colorMode.js +13 -0
- package/dist/ui/navigation/colorMode.js.map +1 -0
- package/dist/ui/navigation/fontSizeLevels.js +24 -0
- package/dist/ui/navigation/fontSizeLevels.js.map +1 -0
- package/dist/ui/navigation/useFontSize.js +44 -0
- package/dist/ui/navigation/useFontSize.js.map +1 -0
- package/dist/ui/timeline/GroupedTimeline.js +104 -0
- package/dist/ui/timeline/GroupedTimeline.js.map +1 -0
- package/dist/ui/timeline/timelineDot.js +20 -0
- package/dist/ui/timeline/timelineDot.js.map +1 -0
- package/dist/upload/FileDropzone.js +143 -0
- package/dist/upload/FileDropzone.js.map +1 -0
- package/dist/upload/fileRules.js +62 -0
- package/dist/upload/fileRules.js.map +1 -0
- package/dist/upload/uploadMachine.js +73 -0
- package/dist/upload/uploadMachine.js.map +1 -0
- package/dist/upload/uploadWithProgress.js +45 -0
- package/dist/upload/uploadWithProgress.js.map +1 -0
- package/package.json +303 -5
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Las versiones exactas que pide el proyecto nuevo: las mismas con que se probó Calcita. Se leen del package.json del
|
|
2
|
+
// paquete (sus devDependencies), así hay UNA sola lista de versiones y no una copia aquí que se quede vieja.
|
|
3
|
+
//
|
|
4
|
+
// Funciones de node, sin React: function (regla de la casa). Pruebas en packageVersions.test.js.
|
|
5
|
+
import {readFile} from 'node:fs/promises';
|
|
6
|
+
|
|
7
|
+
// Lo que el paquete no usa, así que no está en sus devDependencies: i18next (su adaptador recibe la instancia del proyecto;
|
|
8
|
+
// versión con más de dos semanas publicada al escogerla, pnpm espera un día antes de instalar una recién salida) y qrcode
|
|
9
|
+
// (el QR de la cuenta de demostración; la misma versión que usan los ejemplos)
|
|
10
|
+
const VERSIONS_NOT_IN_PACKAGE = Object.freeze({i18next: '26.4.2', qrcode: '1.5.4'});
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* El package.json de Calcita (el del CLI que corre). OJO: por ruta de archivo y no con import: el CLI se publica tal cual,
|
|
14
|
+
* sin pasar por Vite, y node no lee JSON con import sin una bandera.
|
|
15
|
+
*
|
|
16
|
+
* @returns {Promise<{name: string, version: string, devDependencies: Record<string, string>}>}
|
|
17
|
+
*/
|
|
18
|
+
export async function calcitaPackageJson() {
|
|
19
|
+
return JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* La versión exacta de cada librería.
|
|
24
|
+
*
|
|
25
|
+
* @param {string[]} packageNames
|
|
26
|
+
* @param {{devDependencies: Record<string, string>}} calcitaPackage
|
|
27
|
+
* @returns {Record<string, string>}
|
|
28
|
+
*/
|
|
29
|
+
export function versionsOf(packageNames, calcitaPackage) {
|
|
30
|
+
return Object.fromEntries(packageNames.map((packageName) => {
|
|
31
|
+
const version = calcitaPackage.devDependencies?.[packageName] ?? VERSIONS_NOT_IN_PACKAGE[packageName];
|
|
32
|
+
// guard clause: una librería sin versión es un error del CLI (alguien la quitó del paquete), no algo que se adivine
|
|
33
|
+
if (!version) {
|
|
34
|
+
throw new Error(`El CLI no sabe con qué versión de ${packageName} se probó Calcita`);
|
|
35
|
+
}
|
|
36
|
+
return [packageName, version];
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// Las preguntas de «calcita new»: qué se pregunta, sus opciones (la primera es la recomendada) y cómo cada respuesta
|
|
2
|
+
// prende o apaga partes de las plantillas. Las mismas respuestas se pueden dar con banderas (--forms=react-hook-form) o
|
|
3
|
+
// aceptar todas las recomendadas con --yes.
|
|
4
|
+
//
|
|
5
|
+
// Funciones puras: function (regla de la casa). Pruebas en projectAnswers.test.js.
|
|
6
|
+
import {CliError} from './templateFiles.js';
|
|
7
|
+
|
|
8
|
+
/** Los colores de fábrica de cada opción (el principal): el tema de la app y el color de la barra del sistema al instalarla. */
|
|
9
|
+
export const PRIMARY_COLOR_OF = Object.freeze({
|
|
10
|
+
// el naranja Forge de Stackcraft (STACKCRAFT.forge del paquete)
|
|
11
|
+
stackcraft: '#FF6B1A',
|
|
12
|
+
// el azul de MUI (su primary.main por omisión)
|
|
13
|
+
mui: '#1976D2',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const HEX_COLOR = /^#[0-9A-Fa-f]{6}$/;
|
|
17
|
+
// el nombre de la app va en el código (un texto entre comillas), en el HTML y en el manifiesto: sin comillas, sin < ni &
|
|
18
|
+
const APP_TITLE_PATTERN = /^[\p{L}\p{N}][\p{L}\p{N} .,·-]*$/u;
|
|
19
|
+
|
|
20
|
+
/** Las preguntas, en orden. `options`: [valor, texto]; la primera es la recomendada. */
|
|
21
|
+
export const QUESTIONS = Object.freeze([
|
|
22
|
+
{key: 'appTitle', text: 'Nombre de la app (en la barra y en la pestaña)'},
|
|
23
|
+
{key: 'menuPosition', text: '¿Dónde va el menú?', options: [['side', 'A un lado (se encoge a íconos)'], ['top', 'Arriba, en la barra']]},
|
|
24
|
+
{
|
|
25
|
+
key: 'style', text: 'Estilo',
|
|
26
|
+
options: [['glass', 'Vidrio líquido en lo que flota (menús, barra, avisos); en Android, minimalista'], ['plain', 'Sin vidrio'], ['minimal', 'Minimalista: plano, sin bordes ni sombras']],
|
|
27
|
+
},
|
|
28
|
+
{key: 'colorModes', text: 'Modos de color', options: [['lightAndDark', 'Claro y oscuro (con su botón)'], ['lightOnly', 'Solo claro']]},
|
|
29
|
+
{key: 'colors', text: 'Colores', options: [['stackcraft', 'Los de Stackcraft (naranja)'], ['mui', 'Los de MUI (azul)'], ['custom', 'Uno propio']]},
|
|
30
|
+
{key: 'primaryColor', text: 'Color principal (#RRGGBB)', when: (answers) => answers.colors === 'custom'},
|
|
31
|
+
{key: 'forms', text: 'Formularios', options: [['formik', 'formik (viene con Calcita)'], ['react-hook-form', 'react-hook-form']]},
|
|
32
|
+
{key: 'texts', text: 'Textos de la app', options: [['calcita', 'Los de Calcita (archivos JS por módulo)'], ['i18next', 'Con i18next']]},
|
|
33
|
+
{key: 'auth', text: 'Pantallas de entrar, «¿Olvidó su contraseña?» y Mi perfil, con un servidor de mentira', options: [['yes', 'Sí'], ['no', 'No']]},
|
|
34
|
+
{key: 'pwa', text: 'Que se pueda instalar como app (PWA, sin modo sin conexión)', options: [['yes', 'Sí'], ['no', 'No']]},
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Las respuestas recomendadas.
|
|
39
|
+
*
|
|
40
|
+
* @param {string} folderName el nombre de la carpeta: de ahí sale el nombre de la app por omisión
|
|
41
|
+
* @returns {Record<string, string>}
|
|
42
|
+
*/
|
|
43
|
+
export function defaultAnswersOf(folderName) {
|
|
44
|
+
const answers = {appTitle: titleOfFolder(folderName)};
|
|
45
|
+
for (const question of QUESTIONS) {
|
|
46
|
+
if (question.options) {
|
|
47
|
+
answers[question.key] = question.options[0][0];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return answers;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** «mi-tienda» → «Mi tienda». */
|
|
54
|
+
function titleOfFolder(folderName) {
|
|
55
|
+
const words = folderName.split(/[-_\s]+/).filter(Boolean);
|
|
56
|
+
const title = words.join(' ');
|
|
57
|
+
return title ? title.charAt(0).toUpperCase() + title.slice(1) : 'Mi app';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* ¿La respuesta sirve? Regresa el motivo si no, en palabras de la persona.
|
|
62
|
+
*
|
|
63
|
+
* @param {string} key
|
|
64
|
+
* @param {string} value
|
|
65
|
+
* @returns {string|null}
|
|
66
|
+
*/
|
|
67
|
+
export function problemWithAnswer(key, value) {
|
|
68
|
+
const question = QUESTIONS.find((candidate) => candidate.key === key);
|
|
69
|
+
if (!question) {
|
|
70
|
+
return `No hay una opción «${key}».`;
|
|
71
|
+
}
|
|
72
|
+
if (question.options && !question.options.some(([optionValue]) => optionValue === value)) {
|
|
73
|
+
return `«${value}» no es una opción de ${key}: use ${question.options.map(([optionValue]) => optionValue).join(', ')}.`;
|
|
74
|
+
}
|
|
75
|
+
if (key === 'primaryColor' && !HEX_COLOR.test(value)) {
|
|
76
|
+
return 'El color va como #RRGGBB, por ejemplo #2563EB.';
|
|
77
|
+
}
|
|
78
|
+
if (key === 'appTitle' && !APP_TITLE_PATTERN.test(value)) {
|
|
79
|
+
return 'El nombre lleva letras, números, espacios, puntos, comas o guiones (sin comillas).';
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Las respuestas recomendadas con lo que vino en banderas encima; truena con el motivo si una no sirve.
|
|
86
|
+
*
|
|
87
|
+
* @param {string} folderName
|
|
88
|
+
* @param {Record<string, string|undefined>} flagValues
|
|
89
|
+
* @returns {Record<string, string>}
|
|
90
|
+
*/
|
|
91
|
+
export function answersFromFlags(folderName, flagValues) {
|
|
92
|
+
const answers = defaultAnswersOf(folderName);
|
|
93
|
+
for (const question of QUESTIONS) {
|
|
94
|
+
const value = flagValues[question.key];
|
|
95
|
+
if (value !== undefined) {
|
|
96
|
+
answers[question.key] = value;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return checkedAnswers(answers);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Revisa todas: cada valor y que el color propio venga si se eligió.
|
|
104
|
+
*
|
|
105
|
+
* @param {Record<string, string>} answers
|
|
106
|
+
* @returns {Record<string, string>}
|
|
107
|
+
*/
|
|
108
|
+
export function checkedAnswers(answers) {
|
|
109
|
+
for (const [key, value] of Object.entries(answers)) {
|
|
110
|
+
const problem = problemWithAnswer(key, value);
|
|
111
|
+
if (problem) {
|
|
112
|
+
throw new CliError(problem);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (answers.colors === 'custom' && !answers.primaryColor) {
|
|
116
|
+
throw new CliError('Con colores propios hace falta el color principal: --primaryColor=#2563EB.');
|
|
117
|
+
}
|
|
118
|
+
return answers;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Las opciones que leen las plantillas («//#if pwa»), sacadas de las respuestas.
|
|
123
|
+
*
|
|
124
|
+
* @param {Record<string, string>} answers
|
|
125
|
+
* @returns {Record<string, boolean>}
|
|
126
|
+
*/
|
|
127
|
+
export function templateFlagsOf(answers) {
|
|
128
|
+
return {
|
|
129
|
+
auth: answers.auth === 'yes',
|
|
130
|
+
pwa: answers.pwa === 'yes',
|
|
131
|
+
i18next: answers.texts === 'i18next',
|
|
132
|
+
hookForm: answers.forms === 'react-hook-form',
|
|
133
|
+
darkMode: answers.colorModes === 'lightAndDark',
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* El color principal elegido.
|
|
139
|
+
*
|
|
140
|
+
* @param {Record<string, string>} answers
|
|
141
|
+
* @returns {string}
|
|
142
|
+
*/
|
|
143
|
+
export function primaryColorOf(answers) {
|
|
144
|
+
return answers.colors === 'custom' ? answers.primaryColor.toUpperCase() : PRIMARY_COLOR_OF[answers.colors];
|
|
145
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// calcita.json: lo que se eligió al crear el proyecto con «calcita new». Los comandos make:* lo leen para armar igual que el
|
|
2
|
+
// resto del proyecto (los formularios con formik o con react-hook-form). Vive en la raíz del proyecto y se sube al repo.
|
|
3
|
+
//
|
|
4
|
+
// Funciones de node, sin React: function (regla de la casa).
|
|
5
|
+
import {readFile} from 'node:fs/promises';
|
|
6
|
+
import {join} from 'node:path';
|
|
7
|
+
|
|
8
|
+
import {CliError} from './templateFiles.js';
|
|
9
|
+
|
|
10
|
+
export const PROJECT_CONFIG_FILE = 'calcita.json';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Lo que se guarda: la librería de formularios (la que leen los make:*) y todas las respuestas, para saber cómo se armó.
|
|
14
|
+
*
|
|
15
|
+
* @param {Record<string, string>} answers
|
|
16
|
+
* @param {string} calcitaVersion
|
|
17
|
+
* @returns {string} el contenido del archivo
|
|
18
|
+
*/
|
|
19
|
+
export function projectConfigOf(answers, calcitaVersion) {
|
|
20
|
+
return `${JSON.stringify({forms: answers.forms, createdWithCalcita: calcitaVersion, answers}, null, 4)}\n`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Lee calcita.json de la carpeta donde se corre el comando.
|
|
25
|
+
*
|
|
26
|
+
* @param {string} projectRoot
|
|
27
|
+
* @returns {Promise<{forms: string}>}
|
|
28
|
+
*/
|
|
29
|
+
export async function readProjectConfig(projectRoot) {
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(await readFile(join(projectRoot, PROJECT_CONFIG_FILE), 'utf8'));
|
|
32
|
+
} catch (error) {
|
|
33
|
+
if (error.code === 'ENOENT') {
|
|
34
|
+
throw new CliError(`No encontré ${PROJECT_CONFIG_FILE} aquí. Corra el comando en la carpeta del proyecto (la que armó «calcita new»).`);
|
|
35
|
+
}
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// Los tres archivos del proyecto nuevo que cambian demasiado según las respuestas para una plantilla con «//#if»: el
|
|
2
|
+
// package.json (qué librerías pide), calcita.json (projectConfig.js) y el tema (colores, modos y estilo).
|
|
3
|
+
//
|
|
4
|
+
// Funciones puras: function (regla de la casa). Pruebas en projectFiles.test.js.
|
|
5
|
+
import {versionsOf} from './packageVersions.js';
|
|
6
|
+
import {primaryColorOf, templateFlagsOf} from './projectAnswers.js';
|
|
7
|
+
|
|
8
|
+
// lo que pide toda app con Calcita: React, MUI, el router, los avisos y las máquinas de estados que usa su puerta principal
|
|
9
|
+
const BASE_DEPENDENCIES = Object.freeze([
|
|
10
|
+
'@emotion/react', '@emotion/styled', '@mui/icons-material', '@mui/material', '@xstate/react', 'react', 'react-dom', 'react-router',
|
|
11
|
+
'sonner', 'xstate',
|
|
12
|
+
]);
|
|
13
|
+
const HOOK_FORM_DEPENDENCIES = Object.freeze(['@hookform/resolvers', 'react-hook-form']);
|
|
14
|
+
// la cuenta: las llaves de acceso (las pide @stackcraftmx/calcita/account) y el QR de la demostración
|
|
15
|
+
const ACCOUNT_DEPENDENCIES = Object.freeze(['@simplewebauthn/browser', 'qrcode']);
|
|
16
|
+
const DEV_DEPENDENCIES = Object.freeze(['@vitejs/plugin-react', 'vite']);
|
|
17
|
+
|
|
18
|
+
/** Un objeto con sus llaves en orden alfabético (como los escribe npm). */
|
|
19
|
+
const sortedByKey = (record) => Object.fromEntries(Object.entries(record).sort(([first], [second]) => first.localeCompare(second)));
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {object} options
|
|
23
|
+
* @param {string} options.packageName
|
|
24
|
+
* @param {Record<string, string>} options.answers
|
|
25
|
+
* @param {{version: string, devDependencies: Record<string, string>}} options.calcitaPackage
|
|
26
|
+
* @returns {string}
|
|
27
|
+
*/
|
|
28
|
+
export function packageJsonOf({packageName, answers, calcitaPackage}) {
|
|
29
|
+
const flags = templateFlagsOf(answers);
|
|
30
|
+
const dependencyNames = [
|
|
31
|
+
...BASE_DEPENDENCIES,
|
|
32
|
+
...(flags.hookForm ? HOOK_FORM_DEPENDENCIES : []),
|
|
33
|
+
...(flags.auth ? ACCOUNT_DEPENDENCIES : []),
|
|
34
|
+
...(flags.i18next ? ['i18next'] : []),
|
|
35
|
+
];
|
|
36
|
+
const packageJson = {
|
|
37
|
+
name: packageName,
|
|
38
|
+
version: '0.1.0',
|
|
39
|
+
private: true,
|
|
40
|
+
type: 'module',
|
|
41
|
+
scripts: {dev: 'vite', build: 'vite build', preview: 'vite preview'},
|
|
42
|
+
dependencies: sortedByKey({'@stackcraftmx/calcita': `^${calcitaPackage.version}`, ...versionsOf(dependencyNames, calcitaPackage)}),
|
|
43
|
+
devDependencies: sortedByKey(versionsOf([...DEV_DEPENDENCIES], calcitaPackage)),
|
|
44
|
+
engines: {node: '>=22'},
|
|
45
|
+
};
|
|
46
|
+
return `${JSON.stringify(packageJson, null, 4)}\n`;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* src/app/appTheme.js con lo elegido.
|
|
51
|
+
*
|
|
52
|
+
* @param {Record<string, string>} answers
|
|
53
|
+
* @returns {string}
|
|
54
|
+
*/
|
|
55
|
+
export function appThemeFileOf(answers) {
|
|
56
|
+
const flags = templateFlagsOf(answers);
|
|
57
|
+
const usesStackcraftPalettes = answers.colors !== 'mui';
|
|
58
|
+
// con vidrio también el minimalista: en Android arranca así
|
|
59
|
+
const imports = [
|
|
60
|
+
...(answers.style === 'minimal' || answers.style === 'glass' ? ['THEME_LOOK'] : []),
|
|
61
|
+
'createToolkitTheme',
|
|
62
|
+
...(answers.style === 'glass' ? ['isAndroidDevice'] : []),
|
|
63
|
+
...(usesStackcraftPalettes && flags.darkMode ? ['stackcraftDarkPalette'] : []),
|
|
64
|
+
...(usesStackcraftPalettes ? ['stackcraftLightPalette'] : []),
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
const lines = [
|
|
68
|
+
'// El tema de la app: el del framework (createToolkitTheme), con los ajustes de cada componente de Calcita.',
|
|
69
|
+
'//',
|
|
70
|
+
'// Los colores van por modo de color. De cada color basta el «main»: MUI saca su versión clara, la oscura y el',
|
|
71
|
+
'// color de la letra encima. El configurador de tema de los ejemplos de Calcita arma este archivo con vista previa.',
|
|
72
|
+
`import {${imports.join(', ')}} from '@stackcraftmx/calcita';`,
|
|
73
|
+
'',
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
if (answers.colors === 'custom') {
|
|
77
|
+
lines.push(
|
|
78
|
+
'// el color principal de la app; los demás (éxito, aviso, error) se quedan los de Stackcraft',
|
|
79
|
+
`const PRIMARY_COLOR = '${primaryColorOf(answers)}';`,
|
|
80
|
+
'',
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
lines.push(...colorSchemesLinesOf(answers.colors, flags.darkMode), '');
|
|
84
|
+
|
|
85
|
+
if (answers.style === 'glass') {
|
|
86
|
+
lines.push(
|
|
87
|
+
'// vidrio líquido en lo que flota (barra, menús, avisos) y en los controles; el contenido, sólido (guía de Apple).',
|
|
88
|
+
'// En Android, el minimalista: el vidrio es el estilo de Apple (allá se ve ajeno) y el desenfoque pesa en los teléfonos',
|
|
89
|
+
'// baratos',
|
|
90
|
+
'export const appTheme = isAndroidDevice()',
|
|
91
|
+
' ? createToolkitTheme({colorSchemes, look: THEME_LOOK.minimal})',
|
|
92
|
+
' : createToolkitTheme({colorSchemes, glass: true});',
|
|
93
|
+
'',
|
|
94
|
+
);
|
|
95
|
+
return lines.join('\n');
|
|
96
|
+
}
|
|
97
|
+
lines.push('export const appTheme = createToolkitTheme({', ' colorSchemes,');
|
|
98
|
+
if (answers.style === 'minimal') {
|
|
99
|
+
lines.push(' // plano y tonal: sin bordes ni sombras, las superficies se separan por su tono', ' look: THEME_LOOK.minimal,');
|
|
100
|
+
}
|
|
101
|
+
lines.push('});', '');
|
|
102
|
+
return lines.join('\n');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Los renglones de `colorSchemes` según los colores y los modos. */
|
|
106
|
+
function colorSchemesLinesOf(colors, darkMode) {
|
|
107
|
+
if (colors === 'mui') {
|
|
108
|
+
return [
|
|
109
|
+
'// los colores de MUI tal cual (true: su paleta por omisión)',
|
|
110
|
+
darkMode ? 'const colorSchemes = {light: true, dark: true};' : '// solo claro: sin el modo oscuro\nconst colorSchemes = {light: true};',
|
|
111
|
+
];
|
|
112
|
+
}
|
|
113
|
+
if (colors === 'custom') {
|
|
114
|
+
return darkMode
|
|
115
|
+
? [
|
|
116
|
+
'const colorSchemes = {',
|
|
117
|
+
' light: {palette: {...stackcraftLightPalette, primary: {main: PRIMARY_COLOR}}},',
|
|
118
|
+
' dark: {palette: {...stackcraftDarkPalette, primary: {main: PRIMARY_COLOR}}},',
|
|
119
|
+
'};',
|
|
120
|
+
]
|
|
121
|
+
: ['// solo claro: sin el modo oscuro', 'const colorSchemes = {light: {palette: {...stackcraftLightPalette, primary: {main: PRIMARY_COLOR}}}};'];
|
|
122
|
+
}
|
|
123
|
+
return darkMode
|
|
124
|
+
? ['// los colores de Stackcraft', 'const colorSchemes = {light: {palette: stackcraftLightPalette}, dark: {palette: stackcraftDarkPalette}};']
|
|
125
|
+
: ['// los colores de Stackcraft, solo claro (sin el modo oscuro)', 'const colorSchemes = {light: {palette: stackcraftLightPalette}};'];
|
|
126
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Los nombres en pantalla (español e inglés) de un módulo o de una pantalla nueva: con --label-es y --label-en, o
|
|
2
|
+
// preguntados en la terminal; sin respuesta, el nombre en palabras («Purchase orders»), para cambiarlo después en su
|
|
3
|
+
// archivo de textos.
|
|
4
|
+
//
|
|
5
|
+
// Funciones de node, sin React: function (regla de la casa).
|
|
6
|
+
import {createInterface} from 'node:readline/promises';
|
|
7
|
+
import {stdin, stdout} from 'node:process';
|
|
8
|
+
|
|
9
|
+
import {CliError} from './templateFiles.js';
|
|
10
|
+
|
|
11
|
+
// va dentro de un texto entre comillas en el código: sin comillas ni diagonales
|
|
12
|
+
const SCREEN_LABEL_PATTERN = /^[\p{L}\p{N}][\p{L}\p{N} .,·()-]*$/u;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {object} options
|
|
16
|
+
* @param {string} options.defaultLabel el nombre en palabras
|
|
17
|
+
* @param {string} [options.labelEs] el de la bandera --label-es
|
|
18
|
+
* @param {string} [options.labelEn] el de la bandera --label-en
|
|
19
|
+
* @param {boolean} options.canAsk si se puede preguntar (terminal y sin --yes)
|
|
20
|
+
* @param {string} options.what «el módulo», «la pantalla»: para la pregunta
|
|
21
|
+
* @returns {Promise<{es: string, en: string}>}
|
|
22
|
+
*/
|
|
23
|
+
export async function screenLabelsOf({defaultLabel, labelEs, labelEn, canAsk, what}) {
|
|
24
|
+
const labels = {es: labelEs, en: labelEn};
|
|
25
|
+
if (canAsk && (!labels.es || !labels.en)) {
|
|
26
|
+
const terminal = createInterface({input: stdin, output: stdout});
|
|
27
|
+
try {
|
|
28
|
+
labels.es ??= (await terminal.question(`¿Cómo se llama ${what} en pantalla, en español? [${defaultLabel}]: `)).trim() || undefined;
|
|
29
|
+
labels.en ??= (await terminal.question(`¿Y en inglés? [${defaultLabel}]: `)).trim() || undefined;
|
|
30
|
+
} finally {
|
|
31
|
+
terminal.close();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const result = {es: labels.es ?? defaultLabel, en: labels.en ?? defaultLabel};
|
|
35
|
+
for (const label of Object.values(result)) {
|
|
36
|
+
if (!SCREEN_LABEL_PATTERN.test(label)) {
|
|
37
|
+
throw new CliError(`«${label}» no sirve como nombre en pantalla: letras, números, espacios, puntos, comas o guiones (sin comillas).`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// Las plantillas del CLI: archivos tal cual en cli/templates, con dos cosas que se cambian al copiarlos.
|
|
2
|
+
//
|
|
3
|
+
// 1. Los valores: __Name__, __APP_TITLE__… se cambian por el valor que toca (ver la lista de cada comando). Si una
|
|
4
|
+
// plantilla trae uno que el comando no conoce, truena: un «__Name__» olvidado en el proyecto nuevo no compilaría.
|
|
5
|
+
// 2. Los renglones opcionales: lo que va entre «//#if pwa» y «//#endif» solo se queda si la opción está prendida
|
|
6
|
+
// («//#if !pwa»: si está apagada). Los renglones de las marcas se quitan; se pueden anidar.
|
|
7
|
+
//
|
|
8
|
+
// Así una plantilla se lee como el archivo que va a salir, sin código que la arme. Los archivos que no terminan en .tpl
|
|
9
|
+
// (los íconos) se copian sin tocar.
|
|
10
|
+
//
|
|
11
|
+
// Funciones de node, sin React: function (regla de la casa). Pruebas en templateFiles.test.js.
|
|
12
|
+
import {mkdir, readdir, readFile, writeFile} from 'node:fs/promises';
|
|
13
|
+
import {dirname, join, relative} from 'node:path';
|
|
14
|
+
|
|
15
|
+
const TEMPLATE_EXTENSION = '.tpl';
|
|
16
|
+
const IF_MARKER = /^\s*\/\/#if (!?)(\w+)\s*$/;
|
|
17
|
+
const END_MARKER = /^\s*\/\/#endif\s*$/;
|
|
18
|
+
const LEFTOVER_VALUE = /__[A-Za-z]+(?:_[A-Za-z]+)*__/;
|
|
19
|
+
// npm no publica los archivos que se llaman .gitignore: en la plantilla van como dot-gitignore.tpl
|
|
20
|
+
const DOT_FILE_PREFIX = 'dot-';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Error que se le explica a la persona (sin el detalle técnico de dónde tronó): un nombre que ya existe, un archivo que no
|
|
24
|
+
* está. Lo demás es un error del CLI y sale completo.
|
|
25
|
+
*/
|
|
26
|
+
export class CliError extends Error {}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {string} text el contenido de la plantilla
|
|
30
|
+
* @param {{values?: Record<string, string>, flags?: Record<string, boolean>}} [options]
|
|
31
|
+
* @returns {string}
|
|
32
|
+
*/
|
|
33
|
+
export function renderTemplate(text, {values = {}, flags = {}} = {}) {
|
|
34
|
+
const keptLines = [];
|
|
35
|
+
// lo que dice cada «//#if» abierto: si su parte se queda
|
|
36
|
+
const openConditions = [];
|
|
37
|
+
for (const line of text.split('\n')) {
|
|
38
|
+
const ifMatch = IF_MARKER.exec(line);
|
|
39
|
+
if (ifMatch) {
|
|
40
|
+
const [, negation, flagName] = ifMatch;
|
|
41
|
+
if (!(flagName in flags)) {
|
|
42
|
+
throw new Error(`La plantilla pregunta por «${flagName}», que el comando no conoce`);
|
|
43
|
+
}
|
|
44
|
+
openConditions.push(negation ? !flags[flagName] : Boolean(flags[flagName]));
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (END_MARKER.test(line)) {
|
|
48
|
+
if (openConditions.length === 0) {
|
|
49
|
+
throw new Error('La plantilla trae un «//#endif» de más');
|
|
50
|
+
}
|
|
51
|
+
openConditions.pop();
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (openConditions.every(Boolean)) {
|
|
55
|
+
keptLines.push(line);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (openConditions.length > 0) {
|
|
59
|
+
throw new Error('A la plantilla le falta un «//#endif»');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let rendered = keptLines.join('\n');
|
|
63
|
+
for (const [name, value] of Object.entries(values)) {
|
|
64
|
+
rendered = rendered.replaceAll(`__${name}__`, value);
|
|
65
|
+
}
|
|
66
|
+
const leftover = LEFTOVER_VALUE.exec(rendered);
|
|
67
|
+
if (leftover) {
|
|
68
|
+
throw new Error(`La plantilla trae «${leftover[0]}» y el comando no le dio valor`);
|
|
69
|
+
}
|
|
70
|
+
return rendered;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* El nombre con que sale un archivo: sin .tpl, con sus valores (__Name__Page.jsx → ContactsPage.jsx) y dot-gitignore
|
|
75
|
+
* como .gitignore.
|
|
76
|
+
*
|
|
77
|
+
* @param {string} relativePath
|
|
78
|
+
* @param {Record<string, string>} values
|
|
79
|
+
* @returns {string}
|
|
80
|
+
*/
|
|
81
|
+
export function outputPathOf(relativePath, values) {
|
|
82
|
+
let outputPath = relativePath.endsWith(TEMPLATE_EXTENSION) ? relativePath.slice(0, -TEMPLATE_EXTENSION.length) : relativePath;
|
|
83
|
+
for (const [name, value] of Object.entries(values)) {
|
|
84
|
+
outputPath = outputPath.replaceAll(`__${name}__`, value);
|
|
85
|
+
}
|
|
86
|
+
return outputPath.split('/').map((part) => (part.startsWith(DOT_FILE_PREFIX) ? `.${part.slice(DOT_FILE_PREFIX.length)}` : part)).join('/');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Los archivos de una carpeta de plantillas, con su ruta relativa (con «/» también en Windows).
|
|
91
|
+
*
|
|
92
|
+
* @param {string} folder
|
|
93
|
+
* @returns {Promise<string[]>}
|
|
94
|
+
*/
|
|
95
|
+
export async function templateFilesOf(folder) {
|
|
96
|
+
const entries = await readdir(folder, {recursive: true, withFileTypes: true});
|
|
97
|
+
return entries
|
|
98
|
+
.filter((entry) => entry.isFile())
|
|
99
|
+
.map((entry) => relative(folder, join(entry.parentPath, entry.name)).split('\\').join('/'))
|
|
100
|
+
.sort();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Escribe un archivo nuevo; si ya existe, truena sin tocarlo (el CLI nunca pisa lo que ya escribió alguien).
|
|
105
|
+
*
|
|
106
|
+
* @param {string} path
|
|
107
|
+
* @param {string|Buffer} content
|
|
108
|
+
*/
|
|
109
|
+
export async function writeNewFile(path, content) {
|
|
110
|
+
await mkdir(dirname(path), {recursive: true});
|
|
111
|
+
try {
|
|
112
|
+
await writeFile(path, content, {flag: 'wx'});
|
|
113
|
+
} catch (error) {
|
|
114
|
+
if (error.code === 'EEXIST') {
|
|
115
|
+
throw new CliError(`Ya existe ${path}; no se tocó nada de ese archivo.`);
|
|
116
|
+
}
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Copia una carpeta de plantillas a su destino: las .tpl con sus valores y sus renglones opcionales, lo demás tal cual.
|
|
123
|
+
*
|
|
124
|
+
* @param {object} options
|
|
125
|
+
* @param {string} options.templateFolder
|
|
126
|
+
* @param {string} options.targetFolder
|
|
127
|
+
* @param {Record<string, string>} options.values
|
|
128
|
+
* @param {Record<string, boolean>} [options.flags]
|
|
129
|
+
* @param {(relativePath: string) => boolean} [options.includes] cuáles se copian; por omisión todas
|
|
130
|
+
* @returns {Promise<string[]>} las rutas escritas, relativas al destino
|
|
131
|
+
*/
|
|
132
|
+
export async function copyTemplateFolder({templateFolder, targetFolder, values, flags = {}, includes = () => true}) {
|
|
133
|
+
const written = [];
|
|
134
|
+
for (const relativePath of await templateFilesOf(templateFolder)) {
|
|
135
|
+
if (!includes(relativePath)) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const outputPath = outputPathOf(relativePath, values);
|
|
139
|
+
const source = await readFile(join(templateFolder, relativePath));
|
|
140
|
+
const content = relativePath.endsWith(TEMPLATE_EXTENSION) ? renderTemplate(source.toString('utf8'), {values, flags}) : source;
|
|
141
|
+
await writeNewFile(join(targetFolder, outputPath), content);
|
|
142
|
+
written.push(outputPath);
|
|
143
|
+
}
|
|
144
|
+
return written;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Agrega un renglón al final de un arreglo exportado («export const routes = [ … ];»), antes de su «];». Regresa null si no
|
|
149
|
+
* encuentra el arreglo con esa forma (alguien lo cambió): entonces el comando le dice a la persona qué renglón poner.
|
|
150
|
+
*
|
|
151
|
+
* @param {string} text el archivo
|
|
152
|
+
* @param {string} declaration p. ej. 'export const routes = ['
|
|
153
|
+
* @param {string} line el renglón completo, con su sangría
|
|
154
|
+
* @returns {string|null}
|
|
155
|
+
*/
|
|
156
|
+
export function insertIntoArray(text, declaration, line) {
|
|
157
|
+
const start = text.indexOf(declaration);
|
|
158
|
+
if (start < 0) {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
// el «];» que cierra el arreglo: el primero al inicio de un renglón después de la declaración
|
|
162
|
+
const end = text.indexOf('\n];', start);
|
|
163
|
+
if (end < 0) {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
return `${text.slice(0, end)}\n${line}${text.slice(end)}`;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Agrega un renglón después del último que cumple la regla (p. ej. después de la última «export const …_PATH»). Regresa null
|
|
171
|
+
* si ninguno la cumple.
|
|
172
|
+
*
|
|
173
|
+
* @param {string} text
|
|
174
|
+
* @param {RegExp} pattern con la bandera m (renglón por renglón)
|
|
175
|
+
* @param {string} line
|
|
176
|
+
* @returns {string|null}
|
|
177
|
+
*/
|
|
178
|
+
export function insertAfterLastMatch(text, pattern, line) {
|
|
179
|
+
const matches = [...text.matchAll(new RegExp(pattern.source, `${pattern.flags.replace('g', '')}g`))];
|
|
180
|
+
if (matches.length === 0) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
const lastMatch = matches.at(-1);
|
|
184
|
+
const lineEnd = lastMatch.index + lastMatch[0].length;
|
|
185
|
+
return `${text.slice(0, lineEnd)}\n${line}${text.slice(lineEnd)}`;
|
|
186
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// __ComponentName__: lo armó el CLI de Calcita (make:component) con un título y su contenido; cámbielo a lo que pida. Vive
|
|
2
|
+
// en core porque lo usan dos o más módulos: se importa de '@/core'.
|
|
3
|
+
//
|
|
4
|
+
// Genérico y sin estado: function (regla de la casa). Recibe los textos ya traducidos.
|
|
5
|
+
import Paper from '@mui/material/Paper';
|
|
6
|
+
import Stack from '@mui/material/Stack';
|
|
7
|
+
import Typography from '@mui/material/Typography';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {object} props
|
|
11
|
+
* @param {string} props.title ya traducido
|
|
12
|
+
* @param {import('react').ReactNode} [props.children]
|
|
13
|
+
*/
|
|
14
|
+
export function __ComponentName__({title, children}) {
|
|
15
|
+
return (
|
|
16
|
+
<Paper variant="outlined" sx={{p: 2}}>
|
|
17
|
+
<Stack spacing={1}>
|
|
18
|
+
<Typography variant="subtitle2" component="h3">{title}</Typography>
|
|
19
|
+
{children}
|
|
20
|
+
</Stack>
|
|
21
|
+
</Paper>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// __ComponentName__ de __module__: lo armó el CLI de Calcita (make:component) con un título y su contenido; cámbielo a lo
|
|
2
|
+
// que pida. Es solo de este módulo; si otro módulo lo necesita, sube a src/core.
|
|
3
|
+
//
|
|
4
|
+
// Lo renderiza la app: arrow (regla de la casa).
|
|
5
|
+
import Paper from '@mui/material/Paper';
|
|
6
|
+
import Stack from '@mui/material/Stack';
|
|
7
|
+
import Typography from '@mui/material/Typography';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {object} props
|
|
11
|
+
* @param {string} props.title ya traducido
|
|
12
|
+
* @param {import('react').ReactNode} [props.children]
|
|
13
|
+
*/
|
|
14
|
+
export const __ComponentName__ = ({title, children}) => (
|
|
15
|
+
<Paper variant="outlined" sx={{p: 2}}>
|
|
16
|
+
<Stack spacing={1}>
|
|
17
|
+
<Typography variant="subtitle2" component="h3">{title}</Typography>
|
|
18
|
+
{children}
|
|
19
|
+
</Stack>
|
|
20
|
+
</Paper>
|
|
21
|
+
);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// __FormName__ (formik + yup): las reglas en __formName__Schema.js y los textos en __formName__Texts.js.
|
|
2
|
+
//
|
|
3
|
+
// La pantalla dice qué hacer con los datos (onSubmit). Si el servidor dice que no (RFC 9457), el aviso sale arriba del
|
|
4
|
+
// formulario y lo de cada campo, en su campo (applyServerProblem). Al guardar, el formulario se vacía y avisa (onSaved).
|
|
5
|
+
//
|
|
6
|
+
// Lo renderiza la app: arrow (regla de la casa).
|
|
7
|
+
import {useMemo} from 'react';
|
|
8
|
+
import Stack from '@mui/material/Stack';
|
|
9
|
+
import {useToolkitTranslation} from '@stackcraftmx/calcita';
|
|
10
|
+
import {Form, FormProblemAlert, FormTextField, Formik, SubmitButton, applyServerProblem} from '@stackcraftmx/calcita/forms';
|
|
11
|
+
|
|
12
|
+
import {__FORM_NAME___INITIAL_VALUES, build__FormName__Schema} from '@/modules/__module__/__formName__Schema.js';
|
|
13
|
+
|
|
14
|
+
// los renglones de las notas al abrir
|
|
15
|
+
const NOTES_MIN_ROWS = 3;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {object} props
|
|
19
|
+
* @param {(values: {name: string, notes: string}) => Promise<{message: string}>} props.onSubmit guarda; truena con el
|
|
20
|
+
* ApiError si el servidor dice que no
|
|
21
|
+
* @param {(message: string) => void} [props.onSaved] ya se guardó: el aviso del servidor
|
|
22
|
+
*/
|
|
23
|
+
export const __FormName__ = ({onSubmit, onSaved}) => {
|
|
24
|
+
const {t} = useToolkitTranslation('__module__');
|
|
25
|
+
// el esquema se arma al pintar: yup toma sus mensajes al armarlo
|
|
26
|
+
const schema = useMemo(() => build__FormName__Schema(), []);
|
|
27
|
+
|
|
28
|
+
const submit = async (values, formikHelpers) => {
|
|
29
|
+
try {
|
|
30
|
+
const response = await onSubmit(values);
|
|
31
|
+
formikHelpers.resetForm();
|
|
32
|
+
onSaved?.(response.message);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
applyServerProblem(error, {...formikHelpers, values});
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<Formik initialValues={__FORM_NAME___INITIAL_VALUES} validationSchema={schema} onSubmit={submit}>
|
|
40
|
+
<Form noValidate>
|
|
41
|
+
<Stack spacing={2}>
|
|
42
|
+
<FormProblemAlert />
|
|
43
|
+
<FormTextField name="name" label={t('__formName__.name')} />
|
|
44
|
+
<FormTextField name="notes" label={t('__formName__.notes')} helperText={t('__formName__.notesHelp')} multiline minRows={NOTES_MIN_ROWS} />
|
|
45
|
+
<SubmitButton sx={{alignSelf: 'flex-start'}}>{t('__formName__.submit')}</SubmitButton>
|
|
46
|
+
</Stack>
|
|
47
|
+
</Form>
|
|
48
|
+
</Formik>
|
|
49
|
+
);
|
|
50
|
+
};
|