@stackcraftmx/calcita 0.32.2 → 0.51.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/README.md +426 -4
- package/cli/calcita.js +15 -0
- package/cli/checkTexts.js +209 -0
- package/cli/packageVersions.js +17 -3
- package/cli/projectFiles.js +7 -2
- package/cli/templates/module/__Name__Page.test.jsx.tpl +24 -0
- package/cli/templates/project/README.md.tpl +35 -2
- package/cli/templates/project/eslint.config.js.tpl +27 -0
- package/cli/templates/project/src/app/appRouter.jsx.tpl +5 -2
- package/cli/templates/project/src/app/appTexts.js.tpl +2 -1
- package/cli/templates/project/src/core/accountConnector.js.tpl +4 -2
- package/cli/templates/project/src/core/publicPaths.js.tpl +10 -2
- package/cli/templates/project/src/modules/auth/SignInPage.test.jsx.tpl +20 -0
- package/cli/templates/project/src/modules/home/HomePage.test.jsx.tpl +16 -0
- package/cli/templates/project/src/testing/browserGaps.js.tpl +70 -0
- package/cli/templates/project/src/testing/openScreen.jsx.tpl +58 -0
- package/cli/templates/project/src/testing/setup.js.tpl +25 -0
- package/cli/templates/project/vite.config.js.tpl +20 -1
- package/dist/DataTable/AuditTrailDialog.js +3 -2
- package/dist/DataTable/AuditTrailDialog.js.map +1 -1
- package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js +3 -2
- package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js.map +1 -1
- package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js +3 -2
- package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js.map +1 -1
- package/dist/DataTable/ColumnFilters/SortableFilterHeader.js +3 -2
- package/dist/DataTable/ColumnFilters/SortableFilterHeader.js.map +1 -1
- package/dist/DataTable/EmptyState.js +3 -2
- package/dist/DataTable/EmptyState.js.map +1 -1
- package/dist/DataTable/FilterChips.js +3 -2
- package/dist/DataTable/FilterChips.js.map +1 -1
- package/dist/DataTable/GoToPage.js +71 -14
- package/dist/DataTable/GoToPage.js.map +1 -1
- package/dist/DataTable/ServerTable.js +97 -28
- package/dist/DataTable/ServerTable.js.map +1 -1
- package/dist/DataTable/ServerTableFilterDrawer.js +57 -0
- package/dist/DataTable/ServerTableFilterDrawer.js.map +1 -0
- package/dist/DataTable/StackedCell.js +60 -0
- package/dist/DataTable/StackedCell.js.map +1 -0
- package/dist/DataTable/TableCardsView.js +88 -0
- package/dist/DataTable/TableCardsView.js.map +1 -0
- package/dist/DataTable/columnWidths.js +30 -0
- package/dist/DataTable/columnWidths.js.map +1 -0
- package/dist/DataTable/columns.js +47 -1
- package/dist/DataTable/columns.js.map +1 -1
- package/dist/DataTable/filterContext.js.map +1 -1
- package/dist/DataTable/fixedColumns.js +24 -0
- package/dist/DataTable/fixedColumns.js.map +1 -0
- package/dist/DataTable/goToPageOptions.js +17 -0
- package/dist/DataTable/goToPageOptions.js.map +1 -0
- package/dist/DataTable/useTableView.js +29 -0
- package/dist/DataTable/useTableView.js.map +1 -0
- package/dist/access/PermissionMatrix.js +3 -2
- package/dist/access/PermissionMatrix.js.map +1 -1
- package/dist/account/AccountProvider.js +1 -1
- package/dist/account/AccountSecuritySection.js +3 -2
- package/dist/account/AccountSecuritySection.js.map +1 -1
- package/dist/account/DemoTotpCodeButton.js +3 -2
- package/dist/account/DemoTotpCodeButton.js.map +1 -1
- package/dist/account/ProfileScreen.js +3 -2
- package/dist/account/ProfileScreen.js.map +1 -1
- package/dist/account/SignInScreen.js +3 -2
- package/dist/account/SignInScreen.js.map +1 -1
- package/dist/appShell/AccountMenu.js +3 -2
- package/dist/appShell/AccountMenu.js.map +1 -1
- package/dist/appShell/AppLayout.js +3 -2
- package/dist/appShell/AppLayout.js.map +1 -1
- package/dist/appShell/AppearanceSettings.js +3 -2
- package/dist/appShell/AppearanceSettings.js.map +1 -1
- package/dist/appShell/AuthLayout.js +3 -2
- package/dist/appShell/AuthLayout.js.map +1 -1
- package/dist/appShell/BarActionButton.js +11 -4
- package/dist/appShell/BarActionButton.js.map +1 -1
- package/dist/appShell/BarActions.js +3 -2
- package/dist/appShell/BarActions.js.map +1 -1
- package/dist/appShell/BarCapsule.js +3 -2
- package/dist/appShell/BarCapsule.js.map +1 -1
- package/dist/appShell/BarSearch.js +3 -2
- package/dist/appShell/BarSearch.js.map +1 -1
- package/dist/appShell/HeaderTools.js +3 -2
- package/dist/appShell/HeaderTools.js.map +1 -1
- package/dist/appShell/MobileTabBar.js +3 -2
- package/dist/appShell/MobileTabBar.js.map +1 -1
- package/dist/appShell/SettingsMenu.js +3 -2
- package/dist/appShell/SettingsMenu.js.map +1 -1
- package/dist/appShell/SideMenu.js +3 -2
- package/dist/appShell/SideMenu.js.map +1 -1
- package/dist/appShell/SideMenuEntry.js +3 -2
- package/dist/appShell/SideMenuEntry.js.map +1 -1
- package/dist/appShell/SubmenuActionsMenu.js +3 -2
- package/dist/appShell/SubmenuActionsMenu.js.map +1 -1
- package/dist/appShell/TabBarEditor.js +3 -2
- package/dist/appShell/TabBarEditor.js.map +1 -1
- package/dist/appShell/TopMenu.js +3 -2
- package/dist/appShell/TopMenu.js.map +1 -1
- package/dist/appShell/Wordmark.js +3 -2
- package/dist/appShell/Wordmark.js.map +1 -1
- package/dist/auth/PasswordChecklist.js +3 -2
- package/dist/auth/PasswordChecklist.js.map +1 -1
- package/dist/calendar/EventCalendar.js +3 -2
- package/dist/calendar/EventCalendar.js.map +1 -1
- package/dist/calendar/EventDetails.js +3 -2
- package/dist/calendar/EventDetails.js.map +1 -1
- package/dist/date-pickers.js +28 -2
- package/dist/date-pickers.js.map +1 -1
- package/dist/datePickers/DateInput.js +41 -54
- package/dist/datePickers/DateInput.js.map +1 -1
- package/dist/datePickers/DateTimeInput.js +81 -0
- package/dist/datePickers/DateTimeInput.js.map +1 -0
- package/dist/datePickers/FormDateTimeField.js +12 -0
- package/dist/datePickers/FormDateTimeField.js.map +1 -0
- package/dist/datePickers/FormMonthField.js +12 -0
- package/dist/datePickers/FormMonthField.js.map +1 -0
- package/dist/datePickers/FormTimeField.js +12 -0
- package/dist/datePickers/FormTimeField.js.map +1 -0
- package/dist/datePickers/MonthInput.js +64 -0
- package/dist/datePickers/MonthInput.js.map +1 -0
- package/dist/datePickers/PickerFrame.js +27 -0
- package/dist/datePickers/PickerFrame.js.map +1 -0
- package/dist/datePickers/TimeInput.js +61 -0
- package/dist/datePickers/TimeInput.js.map +1 -0
- package/dist/datePickers/dateTimeRules.js +24 -0
- package/dist/datePickers/dateTimeRules.js.map +1 -0
- package/dist/datePickers/pickerValues.js +106 -0
- package/dist/datePickers/pickerValues.js.map +1 -0
- package/dist/datePickers/useCurrentMinute.js +28 -0
- package/dist/datePickers/useCurrentMinute.js.map +1 -0
- package/dist/datePickers/usePickerField.js +23 -0
- package/dist/datePickers/usePickerField.js.map +1 -0
- package/dist/dictionaries/dictionaries.js +3 -1
- package/dist/dictionaries/dictionaries.js.map +1 -1
- package/dist/downloads/DownloadManager.js +3 -2
- package/dist/downloads/DownloadManager.js.map +1 -1
- package/dist/feedback/ConfirmDialog.js +3 -2
- package/dist/feedback/ConfirmDialog.js.map +1 -1
- package/dist/feedback/ModalWaiting.js +3 -2
- package/dist/feedback/ModalWaiting.js.map +1 -1
- package/dist/feedback/NewBuildNotice.js +3 -2
- package/dist/feedback/NewBuildNotice.js.map +1 -1
- package/dist/filepond/FileDropzone.js +3 -2
- package/dist/filepond/FileDropzone.js.map +1 -1
- package/dist/forms/FormAttachmentsField.js +12 -0
- package/dist/forms/FormAttachmentsField.js.map +1 -0
- package/dist/forms/FormCheckboxGroupField.js +12 -0
- package/dist/forms/FormCheckboxGroupField.js.map +1 -0
- package/dist/forms/FormFileField.js +12 -0
- package/dist/forms/FormFileField.js.map +1 -0
- package/dist/forms/FormFileUploadField.js +12 -0
- package/dist/forms/FormFileUploadField.js.map +1 -0
- package/dist/forms/FormImageField.js +12 -0
- package/dist/forms/FormImageField.js.map +1 -0
- package/dist/forms/FormMaskedField.js +12 -0
- package/dist/forms/FormMaskedField.js.map +1 -0
- package/dist/forms/FormProblemAlert.js +3 -2
- package/dist/forms/FormProblemAlert.js.map +1 -1
- package/dist/forms/FormRepeatingFields.js +54 -0
- package/dist/forms/FormRepeatingFields.js.map +1 -0
- package/dist/forms/FormTransferListField.js +12 -0
- package/dist/forms/FormTransferListField.js.map +1 -0
- package/dist/forms/SubmitButton.js +7 -2
- package/dist/forms/SubmitButton.js.map +1 -1
- package/dist/forms/applyServerProblem.js +10 -3
- package/dist/forms/applyServerProblem.js.map +1 -1
- package/dist/forms/auth/SignInForm.js +3 -2
- package/dist/forms/auth/SignInForm.js.map +1 -1
- package/dist/forms/fieldRules.js +30 -0
- package/dist/forms/fieldRules.js.map +1 -0
- package/dist/forms/listRules.js +111 -0
- package/dist/forms/listRules.js.map +1 -0
- package/dist/forms/security/SecondStepForm.js +3 -2
- package/dist/forms/security/SecondStepForm.js.map +1 -1
- package/dist/forms/security/TwoStepVerificationCard.js +3 -2
- package/dist/forms/security/TwoStepVerificationCard.js.map +1 -1
- package/dist/forms/serverProblemFields.js +17 -0
- package/dist/forms/serverProblemFields.js.map +1 -1
- package/dist/forms/useValidationText.js +18 -0
- package/dist/forms/useValidationText.js.map +1 -0
- package/dist/forms/validation.js +35 -31
- package/dist/forms/validation.js.map +1 -1
- package/dist/forms/validationMessages.js +64 -7
- package/dist/forms/validationMessages.js.map +1 -1
- package/dist/forms.js +54 -29
- package/dist/forms.js.map +1 -1
- package/dist/hookForm/FormAttachmentsField.js +12 -0
- package/dist/hookForm/FormAttachmentsField.js.map +1 -0
- package/dist/hookForm/FormCheckboxGroupField.js +12 -0
- package/dist/hookForm/FormCheckboxGroupField.js.map +1 -0
- package/dist/hookForm/FormFileField.js +12 -0
- package/dist/hookForm/FormFileField.js.map +1 -0
- package/dist/hookForm/FormFileUploadField.js +12 -0
- package/dist/hookForm/FormFileUploadField.js.map +1 -0
- package/dist/hookForm/FormImageField.js +12 -0
- package/dist/hookForm/FormImageField.js.map +1 -0
- package/dist/hookForm/FormMaskedField.js +12 -0
- package/dist/hookForm/FormMaskedField.js.map +1 -0
- package/dist/hookForm/FormProblemAlert.js +3 -2
- package/dist/hookForm/FormProblemAlert.js.map +1 -1
- package/dist/hookForm/FormRepeatingFields.js +44 -0
- package/dist/hookForm/FormRepeatingFields.js.map +1 -0
- package/dist/hookForm/FormTransferListField.js +12 -0
- package/dist/hookForm/FormTransferListField.js.map +1 -0
- package/dist/hookForm/SubmitButton.js +7 -2
- package/dist/hookForm/SubmitButton.js.map +1 -1
- package/dist/hookForm/applyServerProblem.js +8 -3
- package/dist/hookForm/applyServerProblem.js.map +1 -1
- package/dist/inbox/InboxLayout.js +3 -2
- package/dist/inbox/InboxLayout.js.map +1 -1
- package/dist/inbox/MessageList.js +3 -2
- package/dist/inbox/MessageList.js.map +1 -1
- package/dist/inbox/MessageView.js +3 -2
- package/dist/inbox/MessageView.js.map +1 -1
- package/dist/index.js +235 -124
- package/dist/index.js.map +1 -1
- package/dist/inputs/CatalogInput.js +103 -29
- package/dist/inputs/CatalogInput.js.map +1 -1
- package/dist/inputs/CheckboxGroupInput.js +103 -0
- package/dist/inputs/CheckboxGroupInput.js.map +1 -0
- package/dist/inputs/ColorInput.js +7 -4
- package/dist/inputs/ColorInput.js.map +1 -1
- package/dist/inputs/FieldFrame.js +10 -4
- package/dist/inputs/FieldFrame.js.map +1 -1
- package/dist/inputs/FormSection.js +1 -1
- package/dist/inputs/MaskedInput.js +87 -0
- package/dist/inputs/MaskedInput.js.map +1 -0
- package/dist/inputs/NumberInput.js +41 -25
- package/dist/inputs/NumberInput.js.map +1 -1
- package/dist/inputs/RepeatingFields.js +180 -0
- package/dist/inputs/RepeatingFields.js.map +1 -0
- package/dist/inputs/SelectInput.js +50 -9
- package/dist/inputs/SelectInput.js.map +1 -1
- package/dist/inputs/TextInput.js +5 -3
- package/dist/inputs/TextInput.js.map +1 -1
- package/dist/inputs/TransferListInput.js +218 -0
- package/dist/inputs/TransferListInput.js.map +1 -0
- package/dist/inputs/WizardLayout.js +3 -2
- package/dist/inputs/WizardLayout.js.map +1 -1
- package/dist/inputs/inputMasks.js +84 -0
- package/dist/inputs/inputMasks.js.map +1 -0
- package/dist/inputs/selectAllState.js +20 -0
- package/dist/inputs/selectAllState.js.map +1 -0
- package/dist/inputs/useRowKeys.js +26 -0
- package/dist/inputs/useRowKeys.js.map +1 -0
- package/dist/kanban/KanbanBoard.js +3 -2
- package/dist/kanban/KanbanBoard.js.map +1 -1
- package/dist/legal/CookieNotice.js +80 -0
- package/dist/legal/CookieNotice.js.map +1 -0
- package/dist/legal/TermsAcceptanceDialog.js +130 -0
- package/dist/legal/TermsAcceptanceDialog.js.map +1 -0
- package/dist/legal/consentStorage.js +18 -0
- package/dist/legal/consentStorage.js.map +1 -0
- package/dist/legal/useCookieConsent.js +17 -0
- package/dist/legal/useCookieConsent.js.map +1 -0
- package/dist/locales/en.js +257 -1
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +257 -1
- package/dist/locales/es.js.map +1 -1
- package/dist/maps/MapView.js +3 -2
- package/dist/maps/MapView.js.map +1 -1
- package/dist/mexico/CfdiSummary.js +82 -0
- package/dist/mexico/CfdiSummary.js.map +1 -0
- package/dist/mexico/EfirmaFields.js +168 -0
- package/dist/mexico/EfirmaFields.js.map +1 -0
- package/dist/mexico/certificateReader.js +79 -0
- package/dist/mexico/certificateReader.js.map +1 -0
- package/dist/mexico/cfdiReader.js +81 -0
- package/dist/mexico/cfdiReader.js.map +1 -0
- package/dist/mexico/derReader.js +81 -0
- package/dist/mexico/derReader.js.map +1 -0
- package/dist/mexico/efirmaKey.js +51 -0
- package/dist/mexico/efirmaKey.js.map +1 -0
- package/dist/mexico/mexicoIdentifiers.js +91 -0
- package/dist/mexico/mexicoIdentifiers.js.map +1 -0
- package/dist/mexico/mexicoRules.js +21 -0
- package/dist/mexico/mexicoRules.js.map +1 -0
- package/dist/mexico.js +34 -0
- package/dist/mexico.js.map +1 -0
- package/dist/pwa/InstallAppSetting.js +3 -2
- package/dist/pwa/InstallAppSetting.js.map +1 -1
- package/dist/pwa/InstallInstructionsDialog.js +3 -2
- package/dist/pwa/InstallInstructionsDialog.js.map +1 -1
- package/dist/pwa/InstallPromptBanner.js +3 -2
- package/dist/pwa/InstallPromptBanner.js.map +1 -1
- package/dist/react-hook-form.js +43 -17
- package/dist/react-hook-form.js.map +1 -1
- package/dist/rich-text.js +19 -0
- package/dist/rich-text.js.map +1 -0
- package/dist/richText/FormRichTextField.js +12 -0
- package/dist/richText/FormRichTextField.js.map +1 -0
- package/dist/richText/RichTextEditor.js +111 -0
- package/dist/richText/RichTextEditor.js.map +1 -0
- package/dist/richText/RichTextLinkPopover.js +57 -0
- package/dist/richText/RichTextLinkPopover.js.map +1 -0
- package/dist/richText/RichTextToolbar.js +189 -0
- package/dist/richText/RichTextToolbar.js.map +1 -0
- package/dist/richText/RichTextView.js +27 -0
- package/dist/richText/RichTextView.js.map +1 -0
- package/dist/richText/richTextContentSx.js +42 -0
- package/dist/richText/richTextContentSx.js.map +1 -0
- package/dist/richText/richTextExtensions.js +44 -0
- package/dist/richText/richTextExtensions.js.map +1 -0
- package/dist/richText/richTextRules.js +46 -0
- package/dist/richText/richTextRules.js.map +1 -0
- package/dist/security/ActivityLog.js +3 -2
- package/dist/security/ActivityLog.js.map +1 -1
- package/dist/security/RecoveryCodesDialog.js +3 -2
- package/dist/security/RecoveryCodesDialog.js.map +1 -1
- package/dist/security/SessionsCard.js +3 -2
- package/dist/security/SessionsCard.js.map +1 -1
- package/dist/table.js +23 -2
- package/dist/table.js.map +1 -1
- package/dist/theme/components/glassComponents.js +27 -0
- package/dist/theme/components/glassComponents.js.map +1 -1
- package/dist/theme/components/minimalComponents.js +12 -0
- package/dist/theme/components/minimalComponents.js.map +1 -1
- package/dist/theme/themePieces.js +70 -4
- package/dist/theme/themePieces.js.map +1 -1
- package/dist/toolkit/ToolkitProvider.js +8 -1
- package/dist/toolkit/ToolkitProvider.js.map +1 -1
- package/dist/toolkit/browserNavigation.js +19 -4
- package/dist/toolkit/browserNavigation.js.map +1 -1
- package/dist/toolkit/combineTexts.js +32 -0
- package/dist/toolkit/combineTexts.js.map +1 -0
- package/dist/toolkit/hashNavigation.js +17 -3
- package/dist/toolkit/hashNavigation.js.map +1 -1
- package/dist/toolkit/navigationPaths.js +15 -0
- package/dist/toolkit/navigationPaths.js.map +1 -1
- package/dist/toolkit/pathIndex.js +66 -0
- package/dist/toolkit/pathIndex.js.map +1 -0
- package/dist/toolkit/toolkitSettings.js +19 -1
- package/dist/toolkit/toolkitSettings.js.map +1 -1
- package/dist/types/DataTable/AuditTrailDialog.d.ts +6 -17
- package/dist/types/DataTable/ColumnFilters/HeaderFilterPopover.d.ts +6 -5
- package/dist/types/DataTable/ColumnFilters/MultiSelectColumnFilter.d.ts +6 -9
- package/dist/types/DataTable/ColumnFilters/SortableFilterHeader.d.ts +6 -14
- package/dist/types/DataTable/EmptyState.d.ts +6 -9
- package/dist/types/DataTable/FilterChips.d.ts +6 -11
- package/dist/types/DataTable/GoToPage.d.ts +6 -9
- package/dist/types/DataTable/ServerTable.d.ts +16 -80
- package/dist/types/DataTable/ServerTableFilterDrawer.d.ts +14 -0
- package/dist/types/DataTable/StackedCell.d.ts +12 -0
- package/dist/types/DataTable/TableCardsView.d.ts +27 -0
- package/dist/types/DataTable/columnWidths.d.ts +21 -0
- package/dist/types/DataTable/columns.d.ts +111 -0
- package/dist/types/DataTable/filterContext.d.ts +2 -1
- package/dist/types/DataTable/fixedColumns.d.ts +29 -0
- package/dist/types/DataTable/goToPageOptions.d.ts +15 -0
- package/dist/types/DataTable/index.d.ts +7 -1
- package/dist/types/DataTable/useTableView.d.ts +22 -0
- package/dist/types/access/PermissionMatrix.d.ts +6 -10
- package/dist/types/account/AccountSecuritySection.d.ts +6 -7
- package/dist/types/account/DemoTotpCodeButton.d.ts +6 -5
- package/dist/types/account/ProfileScreen.d.ts +6 -18
- package/dist/types/account/SignInScreen.d.ts +6 -13
- package/dist/types/appShell/AccountMenu.d.ts +6 -11
- package/dist/types/appShell/AppLayout.d.ts +3 -40
- package/dist/types/appShell/AppearanceSettings.d.ts +6 -12
- package/dist/types/appShell/AuthLayout.d.ts +3 -11
- package/dist/types/appShell/BarActionButton.d.ts +6 -10
- package/dist/types/appShell/BarActions.d.ts +6 -15
- package/dist/types/appShell/BarCapsule.d.ts +6 -9
- package/dist/types/appShell/BarSearch.d.ts +6 -15
- package/dist/types/appShell/HeaderTools.d.ts +6 -16
- package/dist/types/appShell/MobileTabBar.d.ts +6 -13
- package/dist/types/appShell/SettingsMenu.d.ts +6 -10
- package/dist/types/appShell/SideMenu.d.ts +6 -20
- package/dist/types/appShell/SideMenuEntry.d.ts +6 -11
- package/dist/types/appShell/SubmenuActionsMenu.d.ts +6 -12
- package/dist/types/appShell/TabBarEditor.d.ts +6 -9
- package/dist/types/appShell/TopMenu.d.ts +6 -5
- package/dist/types/appShell/Wordmark.d.ts +6 -7
- package/dist/types/auth/PasswordChecklist.d.ts +6 -9
- package/dist/types/calendar/EventCalendar.d.ts +6 -23
- package/dist/types/calendar/EventDetails.d.ts +6 -10
- package/dist/types/date-pickers.d.ts +10 -1
- package/dist/types/datePickers/DateInput.d.ts +10 -23
- package/dist/types/datePickers/DateTimeInput.d.ts +30 -0
- package/dist/types/datePickers/FormDateTimeField.d.ts +7 -0
- package/dist/types/datePickers/FormMonthField.d.ts +7 -0
- package/dist/types/datePickers/FormTimeField.d.ts +7 -0
- package/dist/types/datePickers/MonthInput.d.ts +25 -0
- package/dist/types/datePickers/PickerFrame.d.ts +22 -0
- package/dist/types/datePickers/TimeInput.d.ts +24 -0
- package/dist/types/datePickers/dateTimeRules.d.ts +31 -0
- package/dist/types/datePickers/pickerValues.d.ts +114 -0
- package/dist/types/datePickers/useCurrentMinute.d.ts +5 -0
- package/dist/types/datePickers/usePickerField.d.ts +28 -0
- package/dist/types/dictionaries/dictionaries.d.ts +6 -3
- package/dist/types/downloads/DownloadManager.d.ts +6 -6
- package/dist/types/feedback/ConfirmDialog.d.ts +6 -18
- package/dist/types/feedback/ModalWaiting.d.ts +6 -9
- package/dist/types/feedback/NewBuildNotice.d.ts +6 -10
- package/dist/types/filepond/FileDropzone.d.ts +6 -29
- package/dist/types/forms/FormAttachmentsField.d.ts +7 -0
- package/dist/types/forms/FormCheckboxGroupField.d.ts +7 -0
- package/dist/types/forms/FormFileField.d.ts +7 -0
- package/dist/types/forms/FormFileUploadField.d.ts +7 -0
- package/dist/types/forms/FormImageField.d.ts +7 -0
- package/dist/types/forms/FormMaskedField.d.ts +7 -0
- package/dist/types/forms/FormProblemAlert.d.ts +6 -5
- package/dist/types/forms/FormRepeatingFields.d.ts +25 -0
- package/dist/types/forms/FormTransferListField.d.ts +7 -0
- package/dist/types/forms/SubmitButton.d.ts +6 -6
- package/dist/types/forms/auth/SignInForm.d.ts +6 -11
- package/dist/types/forms/fieldRules.d.ts +44 -0
- package/dist/types/forms/index.d.ts +11 -1
- package/dist/types/forms/listRules.d.ts +48 -0
- package/dist/types/forms/security/SecondStepForm.d.ts +6 -14
- package/dist/types/forms/security/TwoStepVerificationCard.d.ts +6 -21
- package/dist/types/forms/serverProblemFields.d.ts +13 -0
- package/dist/types/forms/useValidationText.d.ts +12 -0
- package/dist/types/forms/validation.d.ts +117 -174
- package/dist/types/forms/validationMessages.d.ts +54 -6
- package/dist/types/forms.d.ts +1 -1
- package/dist/types/hookForm/FormAttachmentsField.d.ts +8 -0
- package/dist/types/hookForm/FormCheckboxGroupField.d.ts +8 -0
- package/dist/types/hookForm/FormFileField.d.ts +8 -0
- package/dist/types/hookForm/FormFileUploadField.d.ts +8 -0
- package/dist/types/hookForm/FormImageField.d.ts +8 -0
- package/dist/types/hookForm/FormMaskedField.d.ts +9 -0
- package/dist/types/hookForm/FormProblemAlert.d.ts +6 -5
- package/dist/types/hookForm/FormRepeatingFields.d.ts +27 -0
- package/dist/types/hookForm/FormTransferListField.d.ts +8 -0
- package/dist/types/hookForm/SubmitButton.d.ts +6 -13
- package/dist/types/inbox/InboxLayout.d.ts +6 -17
- package/dist/types/inbox/MessageList.d.ts +6 -18
- package/dist/types/inbox/MessageView.d.ts +6 -14
- package/dist/types/index.d.ts +33 -4
- package/dist/types/inputs/CatalogInput.d.ts +10 -21
- package/dist/types/inputs/CheckboxGroupInput.d.ts +28 -0
- package/dist/types/inputs/ColorInput.d.ts +7 -16
- package/dist/types/inputs/FieldFrame.d.ts +6 -10
- package/dist/types/inputs/MaskedInput.d.ts +38 -0
- package/dist/types/inputs/NumberInput.d.ts +7 -20
- package/dist/types/inputs/RepeatingFields.d.ts +31 -0
- package/dist/types/inputs/SelectInput.d.ts +10 -18
- package/dist/types/inputs/TextInput.d.ts +3 -0
- package/dist/types/inputs/TransferListInput.d.ts +30 -0
- package/dist/types/inputs/WizardLayout.d.ts +6 -19
- package/dist/types/inputs/inputMasks.d.ts +52 -0
- package/dist/types/inputs/selectAllState.d.ts +11 -0
- package/dist/types/inputs/useRowKeys.d.ts +11 -0
- package/dist/types/kanban/KanbanBoard.d.ts +6 -25
- package/dist/types/legal/CookieNotice.d.ts +20 -0
- package/dist/types/legal/TermsAcceptanceDialog.d.ts +20 -0
- package/dist/types/legal/consentStorage.d.ts +16 -0
- package/dist/types/legal/useCookieConsent.d.ts +13 -0
- package/dist/types/locales/en.d.ts +256 -0
- package/dist/types/locales/es.d.ts +256 -0
- package/dist/types/maps/MapView.d.ts +6 -17
- package/dist/types/mexico/CfdiSummary.d.ts +12 -0
- package/dist/types/mexico/EfirmaFields.d.ts +28 -0
- package/dist/types/mexico/certificateReader.d.ts +37 -0
- package/dist/types/mexico/cfdiReader.d.ts +95 -0
- package/dist/types/mexico/derReader.d.ts +54 -0
- package/dist/types/mexico/efirmaKey.d.ts +26 -0
- package/dist/types/mexico/mexicoIdentifiers.d.ts +68 -0
- package/dist/types/mexico/mexicoRules.d.ts +45 -0
- package/dist/types/mexico.d.ts +11 -0
- package/dist/types/pwa/InstallAppSetting.d.ts +6 -6
- package/dist/types/pwa/InstallInstructionsDialog.d.ts +6 -9
- package/dist/types/pwa/InstallPromptBanner.d.ts +6 -11
- package/dist/types/react-hook-form.d.ts +11 -1
- package/dist/types/rich-text.d.ts +5 -0
- package/dist/types/richText/FormRichTextField.d.ts +7 -0
- package/dist/types/richText/RichTextEditor.d.ts +27 -0
- package/dist/types/richText/RichTextLinkPopover.d.ts +17 -0
- package/dist/types/richText/RichTextToolbar.d.ts +15 -0
- package/dist/types/richText/RichTextView.d.ts +10 -0
- package/dist/types/richText/richTextContentSx.d.ts +7 -0
- package/dist/types/richText/richTextExtensions.d.ts +15 -0
- package/dist/types/richText/richTextRules.d.ts +41 -0
- package/dist/types/security/ActivityLog.d.ts +6 -9
- package/dist/types/security/RecoveryCodesDialog.d.ts +6 -11
- package/dist/types/security/SessionsCard.d.ts +6 -11
- package/dist/types/table.d.ts +3 -1
- package/dist/types/theme/themePieces.d.ts +55 -3
- package/dist/types/toolkit/ToolkitProvider.d.ts +13 -1
- package/dist/types/toolkit/browserNavigation.d.ts +7 -3
- package/dist/types/toolkit/combineTexts.d.ts +6 -0
- package/dist/types/toolkit/hashNavigation.d.ts +4 -2
- package/dist/types/toolkit/navigationPaths.d.ts +35 -0
- package/dist/types/toolkit/pathIndex.d.ts +27 -0
- package/dist/types/toolkit/toolkitSettings.d.ts +7 -4
- package/dist/types/ui/actions/ActionsMenu.d.ts +24 -11
- package/dist/types/ui/actions/CopyButton.d.ts +8 -11
- package/dist/types/ui/actions/DownloadMenu.d.ts +6 -29
- package/dist/types/ui/actions/SecretField.d.ts +6 -11
- package/dist/types/ui/actions/SelectionActions.d.ts +6 -13
- package/dist/types/ui/actions/tableRowText.d.ts +6 -0
- package/dist/types/ui/cards/RecordCard.d.ts +40 -0
- package/dist/types/ui/cards/RecordCardSkeleton.d.ts +12 -0
- package/dist/types/ui/countdown/Countdown.d.ts +22 -0
- package/dist/types/ui/countdown/countdownParts.d.ts +39 -0
- package/dist/types/ui/countdown/useCountdown.d.ts +14 -0
- package/dist/types/ui/documents/PdfViewerDialog.d.ts +14 -0
- package/dist/types/ui/filters/DateRangeFilter.d.ts +6 -10
- package/dist/types/ui/filters/FilterDrawer.d.ts +23 -0
- package/dist/types/ui/filters/PeriodRangeSelector.d.ts +6 -13
- package/dist/types/ui/filters/QuickFilters.d.ts +6 -12
- package/dist/types/ui/filters/filterDrawerFields.d.ts +139 -0
- package/dist/types/ui/help/HelpButton.d.ts +11 -0
- package/dist/types/ui/help/HelpCarouselDialog.d.ts +27 -0
- package/dist/types/ui/help/useHelpCarousel.d.ts +21 -0
- package/dist/types/ui/index.d.ts +10 -0
- package/dist/types/ui/labels/IconBadge.d.ts +34 -0
- package/dist/types/ui/labels/MarkedText.d.ts +10 -0
- package/dist/types/ui/labels/Tag.d.ts +6 -12
- package/dist/types/ui/labels/markedTextPieces.d.ts +22 -0
- package/dist/types/ui/layout/CollapsibleSection.d.ts +6 -12
- package/dist/types/ui/layout/ContentDialog.d.ts +6 -10
- package/dist/types/ui/layout/DefinitionList.d.ts +6 -9
- package/dist/types/ui/layout/DetailHeader.d.ts +6 -10
- package/dist/types/ui/layout/ErrorPage.d.ts +6 -17
- package/dist/types/ui/layout/FullPageLoader.d.ts +6 -6
- package/dist/types/ui/layout/GlassPanel.d.ts +6 -8
- package/dist/types/ui/layout/PageHeader.d.ts +6 -10
- package/dist/types/ui/layout/PageHeading.d.ts +6 -11
- package/dist/types/ui/layout/ProfileHeader.d.ts +6 -11
- package/dist/types/ui/layout/ScrollableRow.d.ts +6 -13
- package/dist/types/ui/layout/SectionCard.d.ts +6 -8
- package/dist/types/ui/metrics/BarList.d.ts +6 -12
- package/dist/types/ui/metrics/CalendarHeatmap.d.ts +6 -19
- package/dist/types/ui/metrics/ChartTooltip.d.ts +6 -6
- package/dist/types/ui/metrics/ColumnChart.d.ts +6 -25
- package/dist/types/ui/metrics/LineChart.d.ts +6 -20
- package/dist/types/ui/metrics/MetricCard.d.ts +6 -17
- package/dist/types/ui/metrics/TableToggle.d.ts +6 -6
- package/dist/types/ui/metrics/chartParts.d.ts +15 -30
- package/dist/types/ui/navigation/BackButton.d.ts +6 -9
- package/dist/types/ui/navigation/ColorSchemeToggle.d.ts +6 -9
- package/dist/types/ui/navigation/FontSizeToggle.d.ts +6 -8
- package/dist/types/ui/navigation/LanguageToggle.d.ts +6 -8
- package/dist/types/ui/navigation/PageBreadcrumbs.d.ts +6 -7
- package/dist/types/ui/navigation/RouteTabs.d.ts +39 -0
- package/dist/types/ui/navigation/routeTabMatching.d.ts +27 -0
- package/dist/types/ui/timeline/GroupedTimeline.d.ts +6 -23
- package/dist/types/upload/AttachmentsInput.d.ts +72 -0
- package/dist/types/upload/FileChip.d.ts +18 -0
- package/dist/types/upload/FileDropzone.d.ts +7 -19
- package/dist/types/upload/FileInput.d.ts +31 -0
- package/dist/types/upload/FileUploadInput.d.ts +56 -0
- package/dist/types/upload/ImageInput.d.ts +35 -0
- package/dist/types/upload/TemplateDownloadButton.d.ts +27 -0
- package/dist/types/upload/fileAppearance.d.ts +8 -0
- package/dist/types/upload/fileRules.d.ts +38 -0
- package/dist/types/upload/transferProgress.d.ts +18 -0
- package/dist/types/upload/uploadMachine.d.ts +6 -2
- package/dist/types/upload/uploadWithProgress.d.ts +6 -2
- package/dist/types/upload/useFilePicker.d.ts +39 -0
- package/dist/ui/actions/ActionsMenu.js +109 -17
- package/dist/ui/actions/ActionsMenu.js.map +1 -1
- package/dist/ui/actions/CopyButton.js +37 -12
- package/dist/ui/actions/CopyButton.js.map +1 -1
- package/dist/ui/actions/DownloadMenu.js +3 -2
- package/dist/ui/actions/DownloadMenu.js.map +1 -1
- package/dist/ui/actions/SecretField.js +8 -3
- package/dist/ui/actions/SecretField.js.map +1 -1
- package/dist/ui/actions/SelectionActions.js +3 -2
- package/dist/ui/actions/SelectionActions.js.map +1 -1
- package/dist/ui/actions/tableRowText.js +7 -0
- package/dist/ui/actions/tableRowText.js.map +1 -0
- package/dist/ui/cards/RecordCard.js +146 -0
- package/dist/ui/cards/RecordCard.js.map +1 -0
- package/dist/ui/cards/RecordCardSkeleton.js +38 -0
- package/dist/ui/cards/RecordCardSkeleton.js.map +1 -0
- package/dist/ui/countdown/Countdown.js +39 -0
- package/dist/ui/countdown/Countdown.js.map +1 -0
- package/dist/ui/countdown/countdownParts.js +34 -0
- package/dist/ui/countdown/countdownParts.js.map +1 -0
- package/dist/ui/countdown/useCountdown.js +35 -0
- package/dist/ui/countdown/useCountdown.js.map +1 -0
- package/dist/ui/documents/PdfViewerDialog.js +82 -0
- package/dist/ui/documents/PdfViewerDialog.js.map +1 -0
- package/dist/ui/filters/DateRangeFilter.js +3 -2
- package/dist/ui/filters/DateRangeFilter.js.map +1 -1
- package/dist/ui/filters/FilterDrawer.js +212 -0
- package/dist/ui/filters/FilterDrawer.js.map +1 -0
- package/dist/ui/filters/PeriodRangeSelector.js +3 -2
- package/dist/ui/filters/PeriodRangeSelector.js.map +1 -1
- package/dist/ui/filters/QuickFilters.js +3 -2
- package/dist/ui/filters/QuickFilters.js.map +1 -1
- package/dist/ui/filters/filterDrawerFields.js +119 -0
- package/dist/ui/filters/filterDrawerFields.js.map +1 -0
- package/dist/ui/help/HelpButton.js +22 -0
- package/dist/ui/help/HelpButton.js.map +1 -0
- package/dist/ui/help/HelpCarouselDialog.js +155 -0
- package/dist/ui/help/HelpCarouselDialog.js.map +1 -0
- package/dist/ui/help/useHelpCarousel.js +25 -0
- package/dist/ui/help/useHelpCarousel.js.map +1 -0
- package/dist/ui/labels/IconBadge.js +82 -0
- package/dist/ui/labels/IconBadge.js.map +1 -0
- package/dist/ui/labels/MarkedText.js +31 -0
- package/dist/ui/labels/MarkedText.js.map +1 -0
- package/dist/ui/labels/Tag.js +3 -2
- package/dist/ui/labels/Tag.js.map +1 -1
- package/dist/ui/labels/markedTextPieces.js +64 -0
- package/dist/ui/labels/markedTextPieces.js.map +1 -0
- package/dist/ui/layout/CollapsibleSection.js +3 -2
- package/dist/ui/layout/CollapsibleSection.js.map +1 -1
- package/dist/ui/layout/ContentDialog.js +3 -2
- package/dist/ui/layout/ContentDialog.js.map +1 -1
- package/dist/ui/layout/DefinitionList.js +3 -2
- package/dist/ui/layout/DefinitionList.js.map +1 -1
- package/dist/ui/layout/DetailHeader.js +3 -2
- package/dist/ui/layout/DetailHeader.js.map +1 -1
- package/dist/ui/layout/ErrorPage.js +3 -2
- package/dist/ui/layout/ErrorPage.js.map +1 -1
- package/dist/ui/layout/FullPageLoader.js +3 -2
- package/dist/ui/layout/FullPageLoader.js.map +1 -1
- package/dist/ui/layout/GlassPanel.js +3 -2
- package/dist/ui/layout/GlassPanel.js.map +1 -1
- package/dist/ui/layout/PageHeader.js +3 -2
- package/dist/ui/layout/PageHeader.js.map +1 -1
- package/dist/ui/layout/PageHeading.js +3 -2
- package/dist/ui/layout/PageHeading.js.map +1 -1
- package/dist/ui/layout/ProfileHeader.js +3 -2
- package/dist/ui/layout/ProfileHeader.js.map +1 -1
- package/dist/ui/layout/ScrollableRow.js +3 -2
- package/dist/ui/layout/ScrollableRow.js.map +1 -1
- package/dist/ui/layout/SectionCard.js +3 -2
- package/dist/ui/layout/SectionCard.js.map +1 -1
- package/dist/ui/metrics/BarList.js +3 -2
- package/dist/ui/metrics/BarList.js.map +1 -1
- package/dist/ui/metrics/CalendarHeatmap.js +3 -2
- package/dist/ui/metrics/CalendarHeatmap.js.map +1 -1
- package/dist/ui/metrics/ChartTooltip.js +3 -2
- package/dist/ui/metrics/ChartTooltip.js.map +1 -1
- package/dist/ui/metrics/ColumnChart.js +3 -2
- package/dist/ui/metrics/ColumnChart.js.map +1 -1
- package/dist/ui/metrics/LineChart.js +3 -2
- package/dist/ui/metrics/LineChart.js.map +1 -1
- package/dist/ui/metrics/MetricCard.js +3 -2
- package/dist/ui/metrics/MetricCard.js.map +1 -1
- package/dist/ui/metrics/TableToggle.js +3 -2
- package/dist/ui/metrics/TableToggle.js.map +1 -1
- package/dist/ui/metrics/chartParts.js +7 -4
- package/dist/ui/metrics/chartParts.js.map +1 -1
- package/dist/ui/navigation/BackButton.js +7 -2
- package/dist/ui/navigation/BackButton.js.map +1 -1
- package/dist/ui/navigation/ColorSchemeToggle.js +3 -2
- package/dist/ui/navigation/ColorSchemeToggle.js.map +1 -1
- package/dist/ui/navigation/FontSizeToggle.js +3 -2
- package/dist/ui/navigation/FontSizeToggle.js.map +1 -1
- package/dist/ui/navigation/LanguageToggle.js +3 -2
- package/dist/ui/navigation/LanguageToggle.js.map +1 -1
- package/dist/ui/navigation/PageBreadcrumbs.js +3 -2
- package/dist/ui/navigation/PageBreadcrumbs.js.map +1 -1
- package/dist/ui/navigation/RouteTabs.js +79 -0
- package/dist/ui/navigation/RouteTabs.js.map +1 -0
- package/dist/ui/navigation/routeTabMatching.js +23 -0
- package/dist/ui/navigation/routeTabMatching.js.map +1 -0
- package/dist/ui/timeline/GroupedTimeline.js +3 -2
- package/dist/ui/timeline/GroupedTimeline.js.map +1 -1
- package/dist/upload/AttachmentsInput.js +130 -0
- package/dist/upload/AttachmentsInput.js.map +1 -0
- package/dist/upload/FileChip.js +28 -0
- package/dist/upload/FileChip.js.map +1 -0
- package/dist/upload/FileDropzone.js +23 -87
- package/dist/upload/FileDropzone.js.map +1 -1
- package/dist/upload/FileInput.js +115 -0
- package/dist/upload/FileInput.js.map +1 -0
- package/dist/upload/FileUploadInput.js +288 -0
- package/dist/upload/FileUploadInput.js.map +1 -0
- package/dist/upload/ImageInput.js +128 -0
- package/dist/upload/ImageInput.js.map +1 -0
- package/dist/upload/TemplateDownloadButton.js +68 -0
- package/dist/upload/TemplateDownloadButton.js.map +1 -0
- package/dist/upload/fileAppearance.js +21 -0
- package/dist/upload/fileAppearance.js.map +1 -0
- package/dist/upload/fileRules.js +27 -1
- package/dist/upload/fileRules.js.map +1 -1
- package/dist/upload/transferProgress.js +23 -0
- package/dist/upload/transferProgress.js.map +1 -0
- package/dist/upload/uploadMachine.js +8 -8
- package/dist/upload/uploadMachine.js.map +1 -1
- package/dist/upload/uploadWithProgress.js +1 -1
- package/dist/upload/uploadWithProgress.js.map +1 -1
- package/dist/upload/useFilePicker.js +101 -0
- package/dist/upload/useFilePicker.js.map +1 -0
- package/package.json +44 -1
- package/cli/templates/project/src/app/combineTexts.js.tpl +0 -31
package/README.md
CHANGED
|
@@ -49,6 +49,15 @@ pnpm exec calcita make:component OrderTotals --module purchase-orders
|
|
|
49
49
|
El CLI nunca pisa un archivo que ya existe. Sus plantillas son los archivos tal cual (`cli/templates`), con
|
|
50
50
|
`//#if pwa` … `//#endif` en lo que depende de una respuesta.
|
|
51
51
|
|
|
52
|
+
El proyecto trae pruebas de pantalla (`pnpm test`, Vitest con jsdom y Testing Library): cada una abre la app completa en una
|
|
53
|
+
dirección con el servidor de mentira (`openScreen` en `src/testing`) y pica como una persona. Vienen las del inicio, la de
|
|
54
|
+
entrar y las del módulo de ejemplo, y `make:module` arma la de cada módulo nuevo.
|
|
55
|
+
|
|
56
|
+
Y dos revisiones para antes de subir: `pnpm lint` (ESLint: una variable que no existe, «t is not defined», se caza al
|
|
57
|
+
escribir) y `pnpm check:texts` (`calcita check:texts`: que cada `t('llave')` escrita tal cual exista en todos los idiomas y
|
|
58
|
+
que los idiomas tengan las mismas llaves). Sirve también en un proyecto que no salió del CLI: lee `src/**/*Texts.js` y
|
|
59
|
+
`src/**/texts.js`.
|
|
60
|
+
|
|
52
61
|
## Arrancar en un proyecto que ya existe
|
|
53
62
|
|
|
54
63
|
```bash
|
|
@@ -93,12 +102,42 @@ Sin nada más, todo sale en español, con la zona horaria del navegador, montos
|
|
|
93
102
|
| `canAccess` | quién ve qué (menú, rutas, botones): la regla del proyecto, normalmente `createAccessChecker(...)` | solo lo que no tiene regla |
|
|
94
103
|
| `buildId` | la compilación del front que corre en la pestaña, para el aviso de versión nueva | ninguna (sin aviso) |
|
|
95
104
|
| `fileTypes` | tipos de archivo propios para las descargas (su ícono y su color), además de Excel, CSV y PDF | los de la casa |
|
|
105
|
+
| `onMissingText` | a quién avisarle de un texto que no existe (la pantalla enseña la llave): mandarlo a Sentry, tronar una prueba | un aviso en la consola, una vez por idioma y llave |
|
|
106
|
+
| `readValidationMessage` | cómo leer los mensajes de validación de un sistema que ya existe (ver «Mensajes de error propios») | `{key}`, `{msg}`, `{message}` y texto |
|
|
96
107
|
|
|
97
108
|
Un `ToolkitProvider` dentro de otro (una parte de la app en otro idioma, una vista previa) toma del de afuera lo que no le
|
|
98
109
|
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,
|
|
99
110
|
`useFormatters()` da los formatos (`formatDate`, `formatCurrency`…) con el idioma, la zona y la moneda del proveedor más
|
|
100
111
|
cercano; los sueltos usan los del proveedor de la raíz.
|
|
101
112
|
|
|
113
|
+
**Fuera de un componente** (una función que arma columnas, un diccionario, un aviso): `translateToolkit(namespace, llave,
|
|
114
|
+
valores)` y los formatos sueltos (`formatDate`, `formatCurrency`, `formatNumber`…) usan el idioma, la zona y la moneda del
|
|
115
|
+
proveedor de la raíz, ya actualizados en la misma pintada en que cambian. Así una función auxiliar no tiene que recibir `t`
|
|
116
|
+
ni los formatos por parámetro:
|
|
117
|
+
|
|
118
|
+
```js
|
|
119
|
+
import {formatDate, translateToolkit} from '@stackcraftmx/calcita';
|
|
120
|
+
|
|
121
|
+
export const columnsOf = () => [
|
|
122
|
+
textColumn({field: 'registered_at', label: translateToolkit('clients', 'columns.registered'), valueFormatter: (value) => formatDate(value)}),
|
|
123
|
+
];
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Dos cuidados: con dos proveedores (dos islas en otro idioma) los sueltos usan el de la raíz; y si la pantalla guarda el
|
|
127
|
+
resultado (`useMemo(() => columnsOf(), [])`), ponga el idioma en las dependencias o se queda en el de antes.
|
|
128
|
+
|
|
129
|
+
Un texto que no existe se pinta con su llave (`clients:columns.registered`) y Calcita lo avisa en la consola una vez; con
|
|
130
|
+
`onMissingText` se le avisa al proyecto. Un texto opcional se pide con `defaultValue` (`t('tips.extra', {defaultValue: ''})`)
|
|
131
|
+
y no avisa.
|
|
132
|
+
|
|
133
|
+
Para un texto con una palabra resaltada, una sola llave con marcas y `MarkedText` (como `<Trans>` de react-i18next, sin
|
|
134
|
+
i18next). No pinta HTML: solo las marcas que se nombran; lo demás sale como texto.
|
|
135
|
+
|
|
136
|
+
```jsx
|
|
137
|
+
// es: {home: {headline: 'Optimiza tu negocio con <highlight>financiamiento</highlight> inteligente'}}
|
|
138
|
+
<MarkedText text={t('home.headline')} marks={{highlight: <Box component="strong" sx={{color: 'primary.main'}} />}} />
|
|
139
|
+
```
|
|
140
|
+
|
|
102
141
|
Con react-router y i18next:
|
|
103
142
|
|
|
104
143
|
```jsx
|
|
@@ -170,10 +209,10 @@ Cada puerta pide solo sus librerías; un proyecto instala lo que usa.
|
|
|
170
209
|
| Importar de | Trae | Pide además |
|
|
171
210
|
|---|---|---|
|
|
172
211
|
| `@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) | — |
|
|
173
|
-
| `@stackcraftmx/calcita/table` | `ServerTable`: paginada, filtrada y ordenada en el servidor, con su estado en la URL | `@mui/x-data-grid`, `nuqs` |
|
|
212
|
+
| `@stackcraftmx/calcita/table` | `ServerTable`: paginada, filtrada y ordenada en el servidor, con su estado en la URL; `ServerTableFilterDrawer`, su búsqueda en cajón | `@mui/x-data-grid`, `nuqs`, `react-window` |
|
|
174
213
|
| `@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` |
|
|
175
214
|
| `@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) |
|
|
176
|
-
| `@stackcraftmx/calcita/date-pickers` |
|
|
215
|
+
| `@stackcraftmx/calcita/date-pickers` | fecha, fecha con hora, hora y mes con los selectores de MUI X (`DateInput`, `DateTimeInput`, `TimeInput`, `MonthInput` y su versión de formik); cada uno viaja en texto | `@mui/x-date-pickers` 8, `dayjs` |
|
|
177
216
|
| `@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` |
|
|
178
217
|
| `@stackcraftmx/calcita/timeline` | línea de tiempo por grupos | `@mui/lab` |
|
|
179
218
|
| `@stackcraftmx/calcita/excel` | reporte en Excel (Resumen y Datos) y CSV | `exceljs`, que se le pasa al llamarlo |
|
|
@@ -183,6 +222,8 @@ Cada puerta pide solo sus librerías; un proyecto instala lo que usa.
|
|
|
183
222
|
| `@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` |
|
|
184
223
|
| `@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` |
|
|
185
224
|
| `@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 | — |
|
|
225
|
+
| `@stackcraftmx/calcita/rich-text` | el editor de texto con formato (`RichTextEditor`, `FormRichTextField`) y la vista que enseña lo guardado sin dejar pasar código (`RichTextView`); viaja HTML | `@tiptap/react`, `@tiptap/pm`, `@tiptap/starter-kit`, `@tiptap/extensions`, `@tiptap/extension-text-align` (3) |
|
|
226
|
+
| `@stackcraftmx/calcita/mexico` | RFC, CURP y CLABE con su dígito verificador y sus reglas de yup; la e.firma (`EfirmaFields`: el .cer leído y la llave abierta en el navegador) y la factura (`readCfdi`, `CfdiSummary`) | `jsrsasign` |
|
|
186
227
|
| `@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 |
|
|
187
228
|
| `@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` |
|
|
188
229
|
| `@stackcraftmx/calcita/account-demo` | `createDemoAccountConnector`: la cuenta en el navegador, sin backend (y los códigos TOTP) | — |
|
|
@@ -245,6 +286,13 @@ el teléfono, con cápsulas, flotan arriba a la derecha y se quedan al bajar: la
|
|
|
245
286
|
en un menú «⋯». Las `actions` de `PageHeading` ya suben solas, y `ServerTable` sube su búsqueda con
|
|
246
287
|
`searchInBar`. «Hecho en Calcita» → «Marco y menú» lo enseña vivo.
|
|
247
288
|
|
|
289
|
+
Cuando los filtros de una lista ya no caben arriba de la tabla, la búsqueda en cajón: `FilterDrawer` sale de un lado
|
|
290
|
+
(`anchor`) con los campos declarados una vez (`FILTER_FIELD_KIND`: texto, una o varias opciones, catálogo, casillas, rango de
|
|
291
|
+
números, de fechas, monto con operador o uno propio); lo que se cambia adentro no mueve la lista hasta «Buscar». Con
|
|
292
|
+
`ServerTableFilterDrawer` en `toolbarExtra` va conectado a la tabla: botón «Filtros (N)», filtros en la dirección y un chip
|
|
293
|
+
por filtro (`filterDrawerDefaultsOf`, `filterDrawerKindsOf`, `filterDrawerChipsOf`). Un monto viaja como `gte:500`
|
|
294
|
+
(`comparisonOf` lo separa en el backend o en la pantalla).
|
|
295
|
+
|
|
248
296
|
```jsx
|
|
249
297
|
<BarActions label="Buscar en pedidos" order={1}>
|
|
250
298
|
<IconButton aria-label="Buscar" onClick={openSearch}><SearchRoundedIcon /></IconButton>
|
|
@@ -297,6 +345,23 @@ tema del proyecto y al final el `sx` que pase la pantalla. Los números se leen
|
|
|
297
345
|
Sirve con `createToolkitTheme` y con cualquier tema de MUI (el que ya tenía un sistema, tal cual): así un sistema puede
|
|
298
346
|
dejar Calcita con su propia cara, parte por parte.
|
|
299
347
|
|
|
348
|
+
Además, como en MUI, cada parte con nombre se puede **cambiar por otro componente** (`slots`) o **recibir props de más**
|
|
349
|
+
(`slotProps`), con el nombre de la parte de la tabla de abajo; desde la pantalla o para toda la app desde el tema:
|
|
350
|
+
|
|
351
|
+
```jsx
|
|
352
|
+
<RecordCard slots={{avatar: StoreAvatar}} slotProps={{titles: {component: 'header'}}} … />
|
|
353
|
+
createTheme({components: {CalcitaRecordCard: {defaultProps: {slotProps: {root: {elevation: 3}}}}}});
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
`className`, `style` y `sx` de `slotProps` se suman a los de Calcita; una pieza dentro de otra igual no toma los `slots` de la
|
|
357
|
+
de afuera. `TextInput` es la excepción: su `slotProps` es el del `TextField` de MUI (`input`, `htmlInput`…). Una pieza propia
|
|
358
|
+
del proyecto se arma con lo mismo: `piecePart`, `usePieceProps` y `withPieceSlots`.
|
|
359
|
+
|
|
360
|
+
El `sx` de la pantalla se **combina regla por regla** con el de la pieza, no la reemplaza: en la tabla,
|
|
361
|
+
`gridSx={{'& .MuiDataGrid-cell': {alignItems: 'flex-start'}}}` cambia solo la alineación y la celda conserva lo demás.
|
|
362
|
+
Para hacer lo mismo en un componente propio: `sx={[{p: 2}, ...sxListOf(sx)]}` (una lista de sx, como pide MUI; nunca
|
|
363
|
+
`{p: 2, ...sx}`, que pierde la llave entera cuando las dos traen la misma).
|
|
364
|
+
|
|
300
365
|
<details>
|
|
301
366
|
<summary>Las piezas, con su nombre en el tema y sus partes</summary>
|
|
302
367
|
|
|
@@ -308,33 +373,49 @@ dejar Calcita con su propia cara, parte por parte.
|
|
|
308
373
|
| `CalcitaActivityLog` | `itemIcon` |
|
|
309
374
|
| `CalcitaAppearanceSettings` | `selectSection`, `section`, `sectionLabel`, `option`, `divider` |
|
|
310
375
|
| `CalcitaAppLayout` | `skipLink`, `brand`, `brandLogo`, `brandText`, `brandName`, `brandCaption`, `titleArea`, `phoneTitle`, `desktopTitle`, `railBrand`, `railLogo`, `collapseButton`, `root`, `scrollEdge`, `bar`, `toolbar`, `menuButton`, `spacer`, `tools`, `progress`, `body`, `drawer`, `main`, `phoneSlot`, `content`, `phoneDrawer` |
|
|
376
|
+
| `CalcitaAttachmentsInput` | `root`, `actions`, `button`, `list`, `fileChip`, `limits` |
|
|
311
377
|
| `CalcitaAuditTrailDialog` | `description` |
|
|
312
378
|
| `CalcitaAuthLayout` | `root`, `tools`, `body`, `brand`, `logo`, `brandName`, `card`, `description`, `content`, `footer` |
|
|
379
|
+
| `CalcitaBackButton` | `root` |
|
|
380
|
+
| `CalcitaBarActionButton` | `button`, `iconButton`, `menuItem` |
|
|
313
381
|
| `CalcitaBarActions` | `group` |
|
|
314
382
|
| `CalcitaBarCapsule` | `root` |
|
|
315
383
|
| `CalcitaBarList` | `row`, `chart` |
|
|
316
384
|
| `CalcitaBarSearch` | `field` |
|
|
317
385
|
| `CalcitaCalendarHeatmap` | `header`, `toggle`, `tableArea`, `dateCell`, `valueCell`, `descriptionCell`, `gridArea`, `grid`, `monthLabel`, `week`, `dayLabel`, `cell`, `legend`, `legendLess`, `legendCell`, `legendMore` |
|
|
386
|
+
| `CalcitaCatalogInput` | `field` |
|
|
387
|
+
| `CalcitaCfdiSummary` | `root`, `header`, `amounts`, `concepts` |
|
|
318
388
|
| `CalcitaChart` | `tableArea`, `legend`, `legendItem`, `legendLine`, `legendSwatch`, `reference`, `referenceLine` |
|
|
319
389
|
| `CalcitaChartTooltip` | `root` |
|
|
390
|
+
| `CalcitaCheckboxGroupInput` | `root`, `selectAll`, `option` |
|
|
320
391
|
| `CalcitaCollapsibleSection` | `root`, `accordion`, `summary`, `titleArea`, `collapsedTitle`, `expandedTitle`, `details` |
|
|
321
392
|
| `CalcitaColorInput` | `swatch`, `nativeInput` |
|
|
322
393
|
| `CalcitaColorSchemeToggle` | `button` |
|
|
323
394
|
| `CalcitaColumnChart` | `chart` |
|
|
324
395
|
| `CalcitaConfirmDialog` | `problem`, `actions` |
|
|
325
396
|
| `CalcitaContentDialog` | `header`, `title`, `closeButton`, `body` |
|
|
397
|
+
| `CalcitaCookieNotice` | `root`, `text`, `actions` |
|
|
398
|
+
| `CalcitaCopyButton` | `button` |
|
|
399
|
+
| `CalcitaCountdown` | `root` |
|
|
400
|
+
| `CalcitaDateInput` | `picker` |
|
|
326
401
|
| `CalcitaDateRangeFilter` | `chip`, `panel`, `actions` |
|
|
402
|
+
| `CalcitaDateTimeInput` | `picker` |
|
|
327
403
|
| `CalcitaDefinitionList` | `root`, `entry`, `label`, `value` |
|
|
328
404
|
| `CalcitaDemoTotpCode` | `root`, `code` |
|
|
329
405
|
| `CalcitaDetailHeader` | `root`, `titleArea`, `title`, `badges`, `actions` |
|
|
330
406
|
| `CalcitaDownloadManager` | `doneIcon`, `failedIcon`, `canceledIcon`, `cancelButton`, `progress`, `cancelIcon`, `item`, `itemText`, `itemStatus`, `itemActions`, `panel`, `header`, `title`, `list` |
|
|
331
407
|
| `CalcitaDownloadMenu` | `button` |
|
|
408
|
+
| `CalcitaEfirmaFields` | `root`, `certificate`, `verify` |
|
|
332
409
|
| `CalcitaEmptyState` | `root`, `icon` |
|
|
333
410
|
| `CalcitaErrorPage` | `root`, `actions` |
|
|
334
411
|
| `CalcitaEventCalendar` | `toolbar`, `navigation`, `title`, `calendar` |
|
|
335
412
|
| `CalcitaEventDetails` | `row`, `rowContent`, `titleRow`, `toneDot`, `linkRow`, `link`, `guestsTitle`, `guest`, `guestAvatar`, `guestName`, `notes`, `actions` |
|
|
413
|
+
| `CalcitaFieldFrame` | `root`, `label` |
|
|
336
414
|
| `CalcitaFileDropzone` | `root`, `fileArea`, `fileChip`, `hint`, `actions`, `limits`, `extra` |
|
|
415
|
+
| `CalcitaFileInput` | `root`, `button`, `fileChip`, `empty` |
|
|
416
|
+
| `CalcitaFileUploadInput` | `root`, `fileName`, `status`, `button`, `helper` |
|
|
337
417
|
| `CalcitaFilterChips` | `root`, `header`, `clearButton` |
|
|
418
|
+
| `CalcitaFilterDrawer` | `header`, `body`, `footer` |
|
|
338
419
|
| `CalcitaFontSizeToggle` | `button` |
|
|
339
420
|
| `CalcitaFormProblemAlert` | `root` |
|
|
340
421
|
| `CalcitaFormRow` | `root`, `label`, `control` |
|
|
@@ -345,6 +426,10 @@ dejar Calcita con su propia cara, parte por parte.
|
|
|
345
426
|
| `CalcitaGroupedTimeline` | `group`, `groupHeader`, `groupButton`, `groupTitle`, `expandIcon`, `timeline`, `opposite`, `connector`, `content`, `entryTitle` |
|
|
346
427
|
| `CalcitaHeaderFilter` | `button`, `badge`, `panel` |
|
|
347
428
|
| `CalcitaHeaderTools` | `divider`, `root` |
|
|
429
|
+
| `CalcitaHelpButton` | `root` |
|
|
430
|
+
| `CalcitaHelpCarouselDialog` | `media`, `content`, `dots`, `actions` |
|
|
431
|
+
| `CalcitaIconBadge` | `root`, `icon`, `label` |
|
|
432
|
+
| `CalcitaImageInput` | `root`, `preview`, `image`, `placeholder`, `actions` |
|
|
348
433
|
| `CalcitaInboxLayout` | `labelDot`, `folder`, `folderIcon`, `folderCount`, `root`, `folders`, `foldersHeader`, `labelsTitle`, `listPane`, `phoneTabs`, `phoneTabBadge`, `listHeader`, `list`, `detail`, `backButton` |
|
|
349
434
|
| `CalcitaInstallAppSetting` | `root` |
|
|
350
435
|
| `CalcitaInstallInstructions` | `steps` |
|
|
@@ -358,26 +443,37 @@ dejar Calcita con su propia cara, parte por parte.
|
|
|
358
443
|
| `CalcitaMetricCard` | `root`, `action`, `header`, `icon`, `label`, `value`, `caption`, `extra`, `trend` |
|
|
359
444
|
| `CalcitaMobileTabBar` | `tab`, `tabIconPlaceholder`, `tabLabel`, `root`, `bar`, `minimized`, `account`, `sheetHeader` |
|
|
360
445
|
| `CalcitaModalWaiting` | `root`, `title`, `body`, `text` |
|
|
446
|
+
| `CalcitaMonthInput` | `picker` |
|
|
361
447
|
| `CalcitaMultiSelectFilter` | `list`, `option` |
|
|
362
448
|
| `CalcitaNewBuildNotice` | `floating`, `icon`, `message`, `reloadButton`, `banner` |
|
|
449
|
+
| `CalcitaNumberInput` | `field` |
|
|
363
450
|
| `CalcitaPageBreadcrumbs` | `root`, `link`, `current` |
|
|
364
451
|
| `CalcitaPageHeader` | `root`, `subtitle`, `action` |
|
|
365
452
|
| `CalcitaPageHeading` | `root`, `breadcrumbs`, `titleRow`, `title`, `actions`, `description` |
|
|
366
453
|
| `CalcitaPasswordChecklist` | `title`, `list`, `item`, `hidden` |
|
|
454
|
+
| `CalcitaPdfViewerDialog` | `actions`, `frame` |
|
|
367
455
|
| `CalcitaPeriodRangeSelector` | `field`, `select`, `root` |
|
|
368
456
|
| `CalcitaPermissionMatrix` | `permission`, `checkbox`, `group`, `groupHeader`, `groupTitle`, `grid` |
|
|
369
457
|
| `CalcitaPondDropzone` | `root`, `summary`, `limits`, `actions`, `extra` |
|
|
370
458
|
| `CalcitaProfileHeader` | `root`, `cover`, `body`, `avatar`, `text`, `name`, `chips`, `actions` |
|
|
371
459
|
| `CalcitaProfileScreen` | `sectionTitle`, `form`, `preferences` |
|
|
372
460
|
| `CalcitaQuickFilters` | `root`, `caption`, `chip`, `chipLabel`, `chipCount` |
|
|
461
|
+
| `CalcitaRecordCard` | `root`, `header`, `avatar`, `titles`, `status`, `body`, `group`, `fact`, `highlight`, `footer`, `details` |
|
|
462
|
+
| `CalcitaRecordCardSkeleton` | `root` |
|
|
373
463
|
| `CalcitaRecoveryCodesDialog` | `codes`, `actions` |
|
|
464
|
+
| `CalcitaRepeatingFields` | `root`, `row`, `rowHeader`, `rowContent`, `addButton`, `helper` |
|
|
465
|
+
| `CalcitaRichTextEditor` | `root`, `toolbar`, `content`, `footer` |
|
|
466
|
+
| `CalcitaRichTextView` | `root` |
|
|
467
|
+
| `CalcitaRouteTabs` | `root`, `tab`, `badge` |
|
|
374
468
|
| `CalcitaScrollableRow` | `root` |
|
|
375
469
|
| `CalcitaSecondStepForm` | `actions` |
|
|
470
|
+
| `CalcitaSecretField` | `field` |
|
|
376
471
|
| `CalcitaSectionCard` | `root`, `header`, `title` |
|
|
377
472
|
| `CalcitaSegmentedControl` | `root` |
|
|
378
473
|
| `CalcitaSelectInput` | `option`, `optionText` |
|
|
379
474
|
| `CalcitaSelectionActions` | `bar`, `count`, `clear`, `phoneCount`, `phoneActions` |
|
|
380
|
-
| `CalcitaServerTable` | `toolbar`, `summary`, `customHeader`, `count`, `countRow`, `selectionNotice`, `error`, `card`, `grid`, `pagination` |
|
|
475
|
+
| `CalcitaServerTable` | `cards`, `cardsPagination`, `viewToggle`, `toolbar`, `summary`, `customHeader`, `count`, `countRow`, `selectionNotice`, `error`, `card`, `grid`, `pagination` |
|
|
476
|
+
| `CalcitaServerTableFilterDrawer` | `button` |
|
|
381
477
|
| `CalcitaSessionsCard` | `item`, `itemIcon`, `itemHeader`, `actions` |
|
|
382
478
|
| `CalcitaSettingsMenu` | `divider` |
|
|
383
479
|
| `CalcitaSideMenu` | `scrollArrow`, `root`, `brand`, `brandLogo`, `brandText`, `brandName`, `brandCaption`, `railTop`, `listArea`, `list`, `section`, `sectionTitle`, `sectionTitleText`, `footer`, `railBottom` |
|
|
@@ -385,16 +481,22 @@ dejar Calcita con su propia cara, parte por parte.
|
|
|
385
481
|
| `CalcitaSignInForm` | `footer` |
|
|
386
482
|
| `CalcitaSignInScreen` | `alert` |
|
|
387
483
|
| `CalcitaSortableFilterHeader` | `title`, `root`, `sortButton`, `sortIndicator`, `clearButton` |
|
|
484
|
+
| `CalcitaStackedCell` | `root`, `line`, `label`, `valueRow`, `primary`, `secondary`, `note` |
|
|
388
485
|
| `CalcitaStatusChip` | `root`, `dot`, `label`, `chip` |
|
|
389
486
|
| `CalcitaSubmenuActionsMenu` | `badge` |
|
|
487
|
+
| `CalcitaSubmitButton` | `root` |
|
|
390
488
|
| `CalcitaTabBarEditor` | `root`, `header`, `title`, `list`, `itemIcon`, `footer` |
|
|
391
489
|
| `CalcitaTableToggle` | `root`, `button` |
|
|
392
490
|
| `CalcitaTag` | `root` |
|
|
491
|
+
| `CalcitaTemplateDownloadButton` | `root` |
|
|
492
|
+
| `CalcitaTermsAcceptanceDialog` | `content`, `frame`, `footer` |
|
|
393
493
|
| `CalcitaTextInput` | `field` |
|
|
494
|
+
| `CalcitaTimeInput` | `picker` |
|
|
394
495
|
| `CalcitaTopMenu` | `link`, `root` |
|
|
496
|
+
| `CalcitaTransferListInput` | `root`, `list`, `actions` |
|
|
395
497
|
| `CalcitaTwoStepVerification` | `qr`, `secret`, `secretCode`, `header`, `headerTitle`, `headerText`, `menuIcon` |
|
|
396
498
|
| `CalcitaWizardLayout` | `stepper`, `phoneSteps`, `actions` |
|
|
397
|
-
| `CalcitaWordmark` | `root` |
|
|
499
|
+
| `CalcitaWordmark` | `root`, `mode` |
|
|
398
500
|
|
|
399
501
|
</details>
|
|
400
502
|
|
|
@@ -488,6 +590,30 @@ const menuItems = composeMenu(import.meta.glob('@/modules/*/menu.js', {eager: tr
|
|
|
488
590
|
|
|
489
591
|
En cada pantalla, `PageHeading` pone el título, la descripción y los botones, y arma las migas solo desde el menú
|
|
490
592
|
(Inicio › Sección › Pantalla). `PageHeader` es el encabezado centrado de una portada y `DetailHeader` el de un registro.
|
|
593
|
+
Para explicar una pantalla la primera vez que se entra, la ayuda en carrusel: `HelpCarouselDialog` (pasos con imagen o
|
|
594
|
+
ilustración, título y texto; Siguiente, los puntos, las flechas o deslizando) y `useHelpCarousel({helpKey, version})`, que
|
|
595
|
+
la abre sola la primera vez y por versión, hasta que se termina o se marca «No volver a mostrar» (`seen` para lo que ya sabe
|
|
596
|
+
el servidor del proyecto); `HelpButton` es el «?» que la vuelve a abrir.
|
|
597
|
+
|
|
598
|
+
Para listas donde una tabla se queda corta, `RecordCard`: arriba quién es (avatar con iniciales, folio, nombre) con su
|
|
599
|
+
estatus, insignias, botón para abrirlo y menú «⋯»; en el cuerpo sus datos en grupos (`groups`, o `content` libre) y el dato
|
|
600
|
+
principal grande; abajo lo que va a todo lo ancho y «Ver detalle», que despliega más. El orden es el que se da y nada se
|
|
601
|
+
reacomoda solo: para un orden obligatorio, `trailing` pone el estatus al final y `columns` fija el ancho de cada columna.
|
|
602
|
+
`RecordCardSkeleton` es su esqueleto. El menú «⋯» (`ActionsMenu`) acepta secciones, separadores, ligas, renglones propios y
|
|
603
|
+
submenús (`children`), que se abren dentro del mismo menú con «Regresar». Un renglón con `to` es una pantalla de la app: va
|
|
604
|
+
con la navegación del proyecto, así el clic normal no recarga la app y Cmd/Ctrl+clic o el botón de en medio la abren en otra
|
|
605
|
+
pestaña (`href` es para lo de afuera). `onClick` recibe el evento del clic.
|
|
606
|
+
|
|
607
|
+
Para las secciones de un registro, `RouteTabs`: pestañas donde cada una es una dirección (se comparte la liga a una
|
|
608
|
+
pestaña); por ruta (cada pestaña su página, y «atrás» regresa a la anterior) o en la consulta (`mode="query"`, `?tab=pagos`,
|
|
609
|
+
con `useActiveRouteTab` para pintar el panel), con ícono, conteo y permiso por pestaña. Las de la consulta son vistas de la
|
|
610
|
+
misma ficha: por omisión reemplazan la entrada del historial, así «atrás» y el `BackButton` salen de la ficha en vez de pasear
|
|
611
|
+
por sus pestañas (`replace={false}` lo apaga; en las de ruta, `replace` lo prende). Las tres navegaciones de Calcita (la del
|
|
612
|
+
navegador, la de `#` y la de Next) y react-router saben reemplazar. Junto al título de un registro van su
|
|
613
|
+
estatus (`StatusChip`) y sus insignias (`IconBadge`): un ícono y un texto corto con el
|
|
614
|
+
color de lo que significan («Envío asegurado», «Pago con tarjeta»), con borde, tenue o sin caja. Mejor desde un diccionario:
|
|
615
|
+
la entrada trae su ícono (`dictionaryEntryOf(value, keyPrefix, color, {icon})`) y la insignia saca de ahí texto,
|
|
616
|
+
explicación, color e ícono (`<IconBadge dictionary={PAYMENT_METHOD} value={order.payment_method} />`).
|
|
491
617
|
|
|
492
618
|
La misma regla protege las rutas (`withAccess(access, routes)` de `/react-router`: quien no puede ve «sin permiso», o la
|
|
493
619
|
página propia que se pase en `{fallback}`) y
|
|
@@ -501,6 +627,42 @@ El marco avisa cuando la persona encoge el menú (`onMenuCollapse`), abre el men
|
|
|
501
627
|
sus pestañas (`onMobileTabsChange`), para guardar esas preferencias en el servidor del proyecto si se quiere; sus textos se
|
|
502
628
|
cambian con `texts`.
|
|
503
629
|
|
|
630
|
+
## La tabla de servidor (`/table`)
|
|
631
|
+
|
|
632
|
+
`ServerTable` pagina, filtra y ordena en el servidor (`fetchPage` recibe `{filters, sortOrders, page, pageSize}` y regresa
|
|
633
|
+
`{rows, total, facets}`); con `prefix` su estado va en la dirección. Lo que piden casi todas las listas de administración
|
|
634
|
+
viene listo:
|
|
635
|
+
|
|
636
|
+
```jsx
|
|
637
|
+
import {ACTIONS_COLUMN_FIELD, ServerTable, actionsColumn, stackedColumn, statusColumn} from '@stackcraftmx/calcita/table';
|
|
638
|
+
|
|
639
|
+
const columns = [
|
|
640
|
+
actionsColumn({label: 'Acciones', actionsOf: (row) => [{key: 'open', label: 'Abrir', to: `/clientes/${row.id}`}]}),
|
|
641
|
+
stackedColumn({field: 'business_name', label: 'Empresa', entries: (row) => [row.business_name, row.rfc, row.regime]}),
|
|
642
|
+
stackedColumn({field: 'created_at', label: 'Fechas', entries: (row) => [ // con etiqueta
|
|
643
|
+
{label: 'Alta', value: formatDate(row.created_at)}, {label: 'Último cambio', value: formatDate(row.updated_at)},
|
|
644
|
+
]}),
|
|
645
|
+
statusColumn({field: 'status', label: 'Estado', dictionary: REGISTRATION_STATUS, t}), // el ancho, medido
|
|
646
|
+
];
|
|
647
|
+
|
|
648
|
+
<ServerTable prefix="clientes" fetchPage={fetchClients} columns={columns} ariaLabel="Clientes"
|
|
649
|
+
fixedColumn={[ACTIONS_COLUMN_FIELD, 'business_name']} // fijas al deslizar
|
|
650
|
+
renderCard={(row) => <RecordCard title={row.business_name} … />} /> // también en tarjetas
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
- `stackedColumn`: los datos que se leen de corrido en una celda, uno debajo del otro, los que hagan falta (el primero en
|
|
654
|
+
negritas, los demás en gris). Cada dato va solo, si el encabezado ya dice qué son, o con su etiqueta arriba
|
|
655
|
+
(`{label, value, note}`) si el encabezado nombra al grupo. Un dato vacío no se pinta, salvo el principal o uno con
|
|
656
|
+
etiqueta, que enseñan «—» (`texts={{cells: {empty: '- - -'}}}` lo cambia). Los renglones toman su alto solos;
|
|
657
|
+
`getRowHeight` también acepta `'auto'`. `StackedCell` es la misma celda para un `renderCell` propio.
|
|
658
|
+
- `statusColumn`: el estatus desde su diccionario, con filtro de facetas y, con `t`, el ancho de su etiqueta más larga.
|
|
659
|
+
- `actionsColumn`: el «⋯» de cada renglón en su columna, de ancho fijo.
|
|
660
|
+
- `fixedColumn` acepta una lista: cada una se pega donde termina la anterior (las que no son la última llevan `width`).
|
|
661
|
+
- `renderCard`: la misma lista en tarjetas, con la misma búsqueda, filtros, orden y páginas; un botón cambia de vista y con
|
|
662
|
+
`prefix` la vista va en la dirección (`?clientes_view=cards`). `view`, `defaultView`, `onViewChange` y `showViewToggle`
|
|
663
|
+
para decidirlo desde la pantalla.
|
|
664
|
+
- `gridSx` se combina con los estilos de la tabla regla por regla; `gridProps` pasa lo demás al DataGrid.
|
|
665
|
+
|
|
504
666
|
## Eventos y textos de cada componente
|
|
505
667
|
|
|
506
668
|
Cada componente de la casa avisa hacia afuera todo lo que pasa adentro (`onSelect`, `onChange`, `onViewChange`,
|
|
@@ -591,6 +753,29 @@ location /ventas/ {
|
|
|
591
753
|
}
|
|
592
754
|
```
|
|
593
755
|
|
|
756
|
+
Si el prefijo lo decide el servidor al servir la página (Laravel con `config('app.url')`, un proxy con su ruta), se construye
|
|
757
|
+
UNA vez con archivos relativos (`ASSET_URL=./`) y la página trae `<base href="/ventas/">`: `documentBasePath()` lo lee al
|
|
758
|
+
abrirla (`null` si no hay `<base>`) y el proyecto de `calcita new` ya lo usa para el router y `publicUrlOf`.
|
|
759
|
+
|
|
760
|
+
## Direcciones con nombre y textos que se juntan solos
|
|
761
|
+
|
|
762
|
+
Cuando una pantalla lleva a la de otro módulo (el detalle de un cliente regresa a la lista de donde salió), cada módulo
|
|
763
|
+
publica sus direcciones en su archivo y un índice las junta; se piden por nombre, sin importar el otro módulo:
|
|
764
|
+
|
|
765
|
+
```js
|
|
766
|
+
// src/app/appPaths.js — el glob tiene que ser un texto literal: Vite lo resuelve al compilar
|
|
767
|
+
export const {pathOf} = createPathIndex(import.meta.glob('@/modules/**/paths.js', {eager: true}));
|
|
768
|
+
|
|
769
|
+
pathOf('admin:profile:detail', {groupId: 2, userId: 7675, tab: 'documentos'}) // '/admin/user/detail/2/7675?tab=documentos'
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
Lo que la ruta pide (`:userId`) se sustituye y lo que sobra va como consulta; un nombre que no existe o una parte que falta
|
|
773
|
+
truena y dice qué sí hay. Las direcciones del API de cada módulo, igual: `createPathIndex(glob, {exportName: 'uris'})`.
|
|
774
|
+
`fillPath(ruta, partes)` llena una suelta.
|
|
775
|
+
|
|
776
|
+
Los textos de cada módulo se juntan con `combineTexts`: por idioma y namespace, los objetos de adentro se suman
|
|
777
|
+
(`validation.fields` de dos módulos) y un texto repetido entre módulos truena en vez de pisarse.
|
|
778
|
+
|
|
594
779
|
## La petición de la casa
|
|
595
780
|
|
|
596
781
|
Todo lo que habla con el servidor pasa por un cliente, armado una vez por proyecto con `fetch` del navegador (sin axios):
|
|
@@ -819,6 +1004,137 @@ import {FormRow, FormSection} from '@stackcraftmx/calcita';
|
|
|
819
1004
|
Los campos van directo dentro de la `FormSection` (sin Grid ni Stack en medio): la línea entre renglones se dibuja entre
|
|
820
1005
|
hermanos.
|
|
821
1006
|
|
|
1007
|
+
### Mensajes de error propios (sin tocar el esquema)
|
|
1008
|
+
|
|
1009
|
+
Los mensajes de `buildYupLocale()` son llaves que se traducen al pintarse, y cada uno lleva **su regla y su campo**. Cuando
|
|
1010
|
+
el negocio pide un mensaje muy específico no hace falta tocar el esquema ni los mensajes de Calcita. El primero que exista
|
|
1011
|
+
gana:
|
|
1012
|
+
|
|
1013
|
+
1. el de la pantalla, en el campo: `<FormTextField name="rfc" messages={{matches: 'El RFC lleva 12 o 13 caracteres'}} />`;
|
|
1014
|
+
2. el de los textos del proyecto para ese campo y esa regla, en todas las pantallas:
|
|
1015
|
+
`{es: {validation: {fields: {rfc: {matches: 'El RFC lleva 12 o 13 caracteres'}}}}}` (dentro de una lista,
|
|
1016
|
+
`contacts[2].email` busca `contacts.email`);
|
|
1017
|
+
3. el general de Calcita (o el del esquema: `.required({key: 'clientes:rfcObligatorio'})`).
|
|
1018
|
+
|
|
1019
|
+
Los textos pueden decir el nombre del campo: `{{label}}` (el de `.label('RFC')` del esquema o, si no, la etiqueta del campo).
|
|
1020
|
+
|
|
1021
|
+
**Un sistema que ya existe** con su propio `setLocale` de yup: Calcita entiende sola `{key, values}`, `{msg, values}` (la de
|
|
1022
|
+
muchos sistemas con i18next), `{message: 'texto'}`, el error entero de react-hook-form y un texto ya escrito. Para otra
|
|
1023
|
+
forma, una función en el proveedor; los esquemas viejos entran sin reescribirse:
|
|
1024
|
+
|
|
1025
|
+
```jsx
|
|
1026
|
+
<ToolkitProvider readValidationMessage={(error) => (error?.codigo ? {key: `legado:${error.codigo}`, values: error.datos} : undefined)}>
|
|
1027
|
+
```
|
|
1028
|
+
|
|
1029
|
+
Una forma que no entiende no se pinta como «[object Object]»: sale el mensaje general y se avisa en la consola. Un campo
|
|
1030
|
+
propio del proyecto usa lo mismo con `useValidationText({label, messages})`.
|
|
1031
|
+
|
|
1032
|
+
Reglas listas, con su mensaje en el idioma activo: `sameAsFieldRule('password', {otherLabel: 'la contraseña'})` (confirmar
|
|
1033
|
+
una contraseña, una CLABE o un correo), `percentRule({max: 30})` y, en `/mexico`, `postalCodeRule()` junto a `rfcRule()`,
|
|
1034
|
+
`curpRule()` y `clabeRule()`.
|
|
1035
|
+
|
|
1036
|
+
### Campos con máscara
|
|
1037
|
+
|
|
1038
|
+
`MaskedInput` (y `FormMaskedField` en `/forms` y `/react-hook-form`) es el campo de texto de la casa con una máscara: mientras
|
|
1039
|
+
se escribe se ven los separadores («555 123 4567») y al formulario llega el valor limpio («5551234567»). Pegar un número con
|
|
1040
|
+
otros separadores también sirve. Las de siempre vienen con nombre en `INPUT_MASK` (`phone`, `postalCode`, `clabe`, `card`,
|
|
1041
|
+
`rfc`, `curp`, `uuid`); una propia es un patrón donde `9` es un dígito, `A` una letra, `X` letra o dígito y `H` hexadecimal
|
|
1042
|
+
(`mask="AAA-9999"`). El RFC y la CURP solo se filtran y se pasan a mayúsculas mientras se escriben.
|
|
1043
|
+
|
|
1044
|
+
```jsx
|
|
1045
|
+
<FormMaskedField name="phone" mask={INPUT_MASK.phone} label="Teléfono" placeholder="555 123 4567" />
|
|
1046
|
+
<FormMaskedField name="clabe" mask="clabe" label="CLABE" />
|
|
1047
|
+
```
|
|
1048
|
+
|
|
1049
|
+
### Fechas y horas
|
|
1050
|
+
|
|
1051
|
+
Cuatro campos en `/date-pickers`, con los selectores de MUI X. Cada uno viaja en texto con una sola forma y se ve en el
|
|
1052
|
+
idioma de la persona; la pantalla no convierte nada:
|
|
1053
|
+
|
|
1054
|
+
| Campo (suelto · formik) | Para qué | Viaja |
|
|
1055
|
+
|---|---|---|
|
|
1056
|
+
| `DateInput` · `FormDateField` | una fecha de calendario (un nacimiento, una entrega) | `'2026-11-01'` |
|
|
1057
|
+
| `DateTimeInput` · `FormDateTimeField` | un momento que pasa una vez (un envío programado, una cita) | `'2026-11-01T18:30:00Z'`, en UTC |
|
|
1058
|
+
| `TimeInput` · `FormTimeField` | una hora del día sin fecha (un horario) | `'09:30'`, de 24 horas |
|
|
1059
|
+
| `MonthInput` · `FormMonthField` | el mes de un reporte o de un cierre | `'2026-11'` |
|
|
1060
|
+
|
|
1061
|
+
La fecha con hora se ve en la zona del proyecto (`ToolkitProvider timeZone`) con el nombre de la zona abajo («Hora estándar
|
|
1062
|
+
central»), para que nadie dude en qué hora está escribiendo; `timeZone` la cambia en un solo campo (la hora de una
|
|
1063
|
+
sucursal) y el momento que viaja es el mismo. La hora sale de 24 horas o con a. m. y p. m. según `ToolkitProvider
|
|
1064
|
+
hourCycle`, y viaja igual. Lo que el selector de MUI X acepta y aquí no tiene nombre va en `pickerProps`.
|
|
1065
|
+
|
|
1066
|
+
```jsx
|
|
1067
|
+
import {FormDateTimeField, FormMonthField, FormTimeField} from '@stackcraftmx/calcita/date-pickers';
|
|
1068
|
+
|
|
1069
|
+
<FormDateTimeField name="visitAt" label="Fecha y hora" disablePast />
|
|
1070
|
+
<FormTimeField name="opensAt" label="Abre a las" minTime="07:00" maxTime="21:00" />
|
|
1071
|
+
<FormMonthField name="billingMonth" label="Se cobra en" disableFuture />
|
|
1072
|
+
```
|
|
1073
|
+
|
|
1074
|
+
Con react-hook-form, el campo suelto va dentro de un `Controller` (la puerta de fechas no pide react-hook-form).
|
|
1075
|
+
|
|
1076
|
+
Los minutos van de uno en uno (MUI X trae de 5 en 5); `minutesStep` los cambia. Para algo que se publica con
|
|
1077
|
+
anticipación y dura un mínimo (una promoción, una venta especial), el inicio lleva `minimumMinutesFromNow` (el mínimo se recorre
|
|
1078
|
+
solo con el reloj mientras la pantalla está abierta) y el fin `minDateTime={instantPlusMinutes(startsAt, 30)}`; en yup,
|
|
1079
|
+
las mismas reglas con su mensaje. El servidor vuelve a revisar: entre llenar el formulario y guardarlo pasa el tiempo.
|
|
1080
|
+
|
|
1081
|
+
```jsx
|
|
1082
|
+
import {FormDateTimeField, instantPlusMinutes, minutesAfterRule, minutesFromNowRule} from '@stackcraftmx/calcita/date-pickers';
|
|
1083
|
+
|
|
1084
|
+
const schema = Yup.object({
|
|
1085
|
+
startsAt: Yup.string().required().test(minutesFromNowRule(5)),
|
|
1086
|
+
endsAt: Yup.string().required().test(minutesAfterRule('startsAt', 30)),
|
|
1087
|
+
});
|
|
1088
|
+
|
|
1089
|
+
<FormDateTimeField name="startsAt" label="Empieza" minimumMinutesFromNow={5} />
|
|
1090
|
+
<FormDateTimeField name="endsAt" label="Termina" minDateTime={instantPlusMinutes(values.startsAt, 30)} />
|
|
1091
|
+
```
|
|
1092
|
+
|
|
1093
|
+
### Renglones que se repiten
|
|
1094
|
+
|
|
1095
|
+
`FormRepeatingFields` (de formik y de react-hook-form, con el mismo uso) pinta una lista del formulario: cada renglón con
|
|
1096
|
+
su número y «Quitar», y «Agregar» al final. `minRows` (por omisión 1: con el mínimo, «Quitar» limpia el renglón) y
|
|
1097
|
+
`maxRows`; si un renglón se puede quitar lo decide la pantalla (`removeBlockedReason` da el motivo, `confirmRemove` pide
|
|
1098
|
+
confirmar uno guardado). En escritorio los campos de un renglón van lado a lado (`columns`) y en el teléfono uno debajo de
|
|
1099
|
+
otro. Las reglas de listas marcan el error en SU renglón:
|
|
1100
|
+
|
|
1101
|
+
```jsx
|
|
1102
|
+
import {FormNumberField, FormRepeatingFields, Yup, listTotalAtMostRule, orderedInListRule, uniqueInListRule} from '@stackcraftmx/calcita/forms';
|
|
1103
|
+
|
|
1104
|
+
const schema = Yup.object({
|
|
1105
|
+
prices: Yup.array().of(Yup.object({
|
|
1106
|
+
min_quantity: Yup.string().required()
|
|
1107
|
+
.test(uniqueInListRule('prices', 'min_quantity')) // «Ya está en el renglón 2»
|
|
1108
|
+
.test(orderedInListRule('prices', 'min_quantity')), // «Debe ir entre 10 (renglón 1) y 50 (renglón 3)»
|
|
1109
|
+
})),
|
|
1110
|
+
split: Yup.array().test(listTotalAtMostRule('amount', (values) => values.credit_limit)), // con Money, sin floats
|
|
1111
|
+
});
|
|
1112
|
+
|
|
1113
|
+
<FormRepeatingFields name="prices" label="Precios por volumen" emptyRow={{min_quantity: '', unit_price: ''}} maxRows={6}
|
|
1114
|
+
renderRow={({nameOf}) => (<>
|
|
1115
|
+
<FormNumberField name={nameOf('min_quantity')} label="Desde (piezas)" decimals={0} />
|
|
1116
|
+
<FormNumberField name={nameOf('unit_price')} label="Precio" prefix="$" />
|
|
1117
|
+
</>)} />
|
|
1118
|
+
```
|
|
1119
|
+
|
|
1120
|
+
### Elegir varios
|
|
1121
|
+
|
|
1122
|
+
Tres formas, según cuántas opciones hay, y cada una con su versión de formik y de react-hook-form:
|
|
1123
|
+
|
|
1124
|
+
| Pieza | Para qué | Opciones de varias |
|
|
1125
|
+
|---|---|---|
|
|
1126
|
+
| `CheckboxGroupInput` · `FormCheckboxGroupField` | pocas opciones a la vista (los canales de aviso) | `selectAll`, `row`, `options[].description` |
|
|
1127
|
+
| `SelectInput` · `FormSelectField` con `multiple` | una lista corta (los días) | `selectAll`, `checkboxes` |
|
|
1128
|
+
| `CatalogInput` · `FormCatalogField` con `multiple` | un catálogo largo con buscador (los estados) | `selectAll` (con algo buscado, «Elegir los N que coinciden»), `checkboxes`, `limitTags` |
|
|
1129
|
+
| `TransferListInput` · `FormTransferListField` | elegir muchos viendo qué quedó de cada lado (compradores, sucursales) | `availableTitle`, `chosenTitle`, `searchable`, `listHeight` |
|
|
1130
|
+
|
|
1131
|
+
«Elegir todos» lleva su casilla a medias cuando hay algunos elegidos y no cuenta las opciones apagadas (`disabled`). La
|
|
1132
|
+
lista de transferencia va fuera de una FormSection: necesita el ancho completo.
|
|
1133
|
+
|
|
1134
|
+
Un 422 del servidor en `contacts.2.email` llega a ese renglón (`applyServerProblem`). Con formik, el error de toda la lista
|
|
1135
|
+
(el tope) sale cuando los renglones ya no tienen errores: formik guarda los dos en el mismo lugar; para verlo mientras se
|
|
1136
|
+
escribe va un resumen en vivo en `footer` con `listTotalOf`.
|
|
1137
|
+
|
|
822
1138
|
## Subir archivos
|
|
823
1139
|
|
|
824
1140
|
Dos zonas para soltar archivos con el mismo uso: la de la puerta principal, con puro MUI (un archivo), y la de
|
|
@@ -835,6 +1151,112 @@ import {FileDropzone, buildUploadActors, uploadMachine, uploadWithProgress} from
|
|
|
835
1151
|
`accept` acepta nombres (`'excel'`, `['pdf', 'image']`) o lo de siempre del input (`'.xlsx,.xls'`); `maxSize` va en bytes
|
|
836
1152
|
o con unidades (`'10 MB'`, en base 1000 como el navegador).
|
|
837
1153
|
|
|
1154
|
+
Para otros acomodos, con las mismas reglas y los mismos avisos:
|
|
1155
|
+
|
|
1156
|
+
| Pieza (suelta · formik y react-hook-form) | Para qué | Al formulario llega |
|
|
1157
|
+
|---|---|---|
|
|
1158
|
+
| `FileInput` · `FormFileField` | un archivo del tamaño de un campo (la constancia, el contrato) | el `File`, lo ya guardado (`{name, size}`) o `null` |
|
|
1159
|
+
| `AttachmentsInput` · `FormAttachmentsField` | varios, como en un correo: «Adjuntar» y un chip por archivo | la lista (nuevos y guardados) |
|
|
1160
|
+
| `ImageInput` · `FormImageField` | una foto con su vista previa, en círculo o recuadro | el `File`, la dirección de la guardada o `null` |
|
|
1161
|
+
| `TemplateDownloadButton` | «Descargar la plantilla» (un archivo fijo con `href` o su API con `request`) | — |
|
|
1162
|
+
|
|
1163
|
+
Los cuatro cargadores aceptan `template` para poner «Descargar la plantilla» junto a su botón, y `AttachmentsInput` suma
|
|
1164
|
+
`maxFiles` y `maxTotalSize`. Para armar uno propio (una tarjeta, un botón en la barra) está `useFilePicker`, que da el
|
|
1165
|
+
input, abrir la ventana, soltar encima y la revisión con sus avisos.
|
|
1166
|
+
|
|
1167
|
+
```jsx
|
|
1168
|
+
import {AttachmentsInput, FileInput} from '@stackcraftmx/calcita';
|
|
1169
|
+
|
|
1170
|
+
<FileInput label="Constancia fiscal" value={file} onChange={setFile} accept="pdf" maxSize="2 MB"
|
|
1171
|
+
template={{href: '/plantillas/constancia.pdf'}} />
|
|
1172
|
+
<AttachmentsInput value={files} onChange={setFiles} accept={['pdf', 'image']} maxFiles={5} maxTotalSize="10 MB" />
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
### El cargador mini: sube en cuanto se elige
|
|
1176
|
+
|
|
1177
|
+
Los de arriba solo eligen y el archivo viaja con el formulario. `FileUploadInput` (y `FormFileUploadField` de formik y de
|
|
1178
|
+
react-hook-form) SUBE el archivo en cuanto se elige, en su renglón: para una lista de documentos (lo que pide una solicitud,
|
|
1179
|
+
el expediente de un cliente). Enseña su estado (Por cargar, Subiendo 40 %, Procesando, Cargado, No se cargó), «Cargar» que ya
|
|
1180
|
+
cargado dice «Sustituir», bajar el subido y quitarlo, y abajo el avance en palabras o el motivo del error. Al formulario
|
|
1181
|
+
llega solo el id que da el servidor (`''` mientras sube): `Yup.string().required()` pide el documento.
|
|
1182
|
+
|
|
1183
|
+
```jsx
|
|
1184
|
+
import {FormFileUploadField} from '@stackcraftmx/calcita/forms';
|
|
1185
|
+
|
|
1186
|
+
<FormFileUploadField name="identification_file_id" label="Identificación oficial" accept={['pdf', 'image']} maxSize="5 MB"
|
|
1187
|
+
upload={(file, {signal, onUploadProgress, idempotencyKey}) => documentsApi.upload(file, {signal, onUploadProgress, idempotencyKey})}
|
|
1188
|
+
download={(fileId, transferOptions) => documentsApi.download(fileId, transferOptions)} />
|
|
1189
|
+
```
|
|
1190
|
+
|
|
1191
|
+
`upload` es la subida del proyecto (`uploadWithProgress`, axios o su cliente) y `idOf` dice qué guardar de la respuesta (por
|
|
1192
|
+
omisión `result.id`). Lo del negocio (Aprobado, Falta información) va junto al estado con `actions`, y `onStatusChange`
|
|
1193
|
+
dice en qué va cada renglón para contar «2 de 3 cargados».
|
|
1194
|
+
|
|
1195
|
+
## Documentos, avisos legales y cuenta regresiva
|
|
1196
|
+
|
|
1197
|
+
- `PdfViewerDialog`: un PDF en una ventana con el visor del navegador (sin librerías), con «Abrir en otra pestaña» y
|
|
1198
|
+
«Descargar» siempre a la vista (en el iPhone el visor dentro de la página enseña solo la primera hoja). `src` es la
|
|
1199
|
+
dirección o el archivo (un Blob de su API).
|
|
1200
|
+
- `CookieNotice`: el aviso de cookies abajo, hasta que se acepta ESA versión en el navegador; no bloquea la pantalla.
|
|
1201
|
+
`useCookieConsent` para pintar uno propio.
|
|
1202
|
+
- `TermsAcceptanceDialog`: aceptar los términos antes de seguir; pide leerlos hasta el final, marcar la casilla y «Acepto»,
|
|
1203
|
+
y no se cierra con Escape. Quién aceptó qué versión lo registra su API en `onAccept` (la ventana espera y, si falla, dice
|
|
1204
|
+
el motivo).
|
|
1205
|
+
- `Countdown`: «02:14:30» hasta un momento, con días cuando faltan, lo que dice al llegar a cero y `onComplete`;
|
|
1206
|
+
`useCountdown` da las partes para pintarla a su manera.
|
|
1207
|
+
|
|
1208
|
+
```jsx
|
|
1209
|
+
<CookieNotice version="2026-11" policyHref="/legal/cookies" />
|
|
1210
|
+
<TermsAcceptanceDialog open={!session.terms.accepted} version={session.terms.current} onAccept={({version}) => api.acceptTerms(version)}
|
|
1211
|
+
onDecline={signOut}>
|
|
1212
|
+
<TermsText />
|
|
1213
|
+
</TermsAcceptanceDialog>
|
|
1214
|
+
<Countdown until={registration.closes_at} onComplete={reloadRegistration} completedText="Cerradas" />
|
|
1215
|
+
```
|
|
1216
|
+
|
|
1217
|
+
## Texto con formato
|
|
1218
|
+
|
|
1219
|
+
`@stackcraftmx/calcita/rich-text` trae el editor con Tiptap: estilo (texto, título, subtítulo), negrita, cursiva,
|
|
1220
|
+
subrayado, tachado, listas, cita, código, ligas, alineación, quitar el formato y deshacer, con contador si hay `maxLength`.
|
|
1221
|
+
Viaja HTML; vacío es `''` (así `required()` funciona). Las ligas solo con https, http, mailto o tel (un dominio suelto se
|
|
1222
|
+
completa con https://). `RichTextView` enseña lo guardado pasándolo por el mismo esquema del editor: un `<script>`, un
|
|
1223
|
+
`onclick` o una liga `javascript:` no llegan a la página.
|
|
1224
|
+
|
|
1225
|
+
```jsx
|
|
1226
|
+
import {FormRichTextField, RICH_TEXT_FEATURE, RichTextView} from '@stackcraftmx/calcita/rich-text';
|
|
1227
|
+
|
|
1228
|
+
<FormRichTextField name="notes" label="Notas" maxLength={2000}
|
|
1229
|
+
features={[RICH_TEXT_FEATURE.bold, RICH_TEXT_FEATURE.bulletList, RICH_TEXT_FEATURE.link]} />
|
|
1230
|
+
<RichTextView value={order.notes} />
|
|
1231
|
+
```
|
|
1232
|
+
|
|
1233
|
+
Para lo que la barra no trae: `toolbarActions` (botones propios), `onEditorReady` (el editor de Tiptap) y `extensions`
|
|
1234
|
+
(extensiones de Tiptap del proyecto). Pesa unos 420 kB (134 kB comprimido) y solo se baja en las pantallas que lo usan.
|
|
1235
|
+
|
|
1236
|
+
## México: RFC, CURP, CLABE, e.firma y facturas
|
|
1237
|
+
|
|
1238
|
+
`@stackcraftmx/calcita/mexico` trae lo que casi cualquier sistema en México pide (pide `jsrsasign` solo para abrir la llave):
|
|
1239
|
+
|
|
1240
|
+
- `isValidRfc`, `isValidCurp`, `isValidClabe`: la forma, que la fecha exista y el dígito verificador (el del RFC, con
|
|
1241
|
+
`{strict: true}`). En yup, como reglas con su mensaje: `Yup.string().test(clabeRule())`.
|
|
1242
|
+
- `readCfdi(xmlText)` / `readCfdiFile(file)`: la factura (CFDI 3.3 y 4.0) leída del XML, con los montos en texto para
|
|
1243
|
+
`Money`; `null` si no es factura. `CfdiSummary` la enseña, con el aviso si no es para su RFC o si no está timbrada.
|
|
1244
|
+
- `EfirmaFields`: el .cer, el .key y la contraseña. El certificado se lee en el navegador (`readCertificate`: RFC, CURP, nombre,
|
|
1245
|
+
número de certificado, vigencia) y avisa si venció o es de otro RFC. «Revisar la e.firma» abre la llave con su contraseña y
|
|
1246
|
+
comprueba que es la del certificado, también en el navegador (`verifyEfirmaKey`, con jsrsasign, que se baja hasta que se
|
|
1247
|
+
usa: la llave del SAT va cifrada con 3DES y el navegador no lo trae), y dice el motivo de un «no». Con `onVerifyKey` la
|
|
1248
|
+
revisión la hace su API. Calcita no manda la llave a ningún lado.
|
|
1249
|
+
|
|
1250
|
+
```jsx
|
|
1251
|
+
import {CfdiSummary, EfirmaFields, clabeRule, readCfdiFile} from '@stackcraftmx/calcita/mexico';
|
|
1252
|
+
|
|
1253
|
+
const cfdi = await readCfdiFile(file); // null si no es factura
|
|
1254
|
+
<CfdiSummary cfdi={cfdi} expectedReceiverRfc={company.rfc} />
|
|
1255
|
+
<EfirmaFields value={efirma} onChange={setEfirma} expectedRfc={company.rfc} /> {/* revisa la llave en el navegador */}
|
|
1256
|
+
```
|
|
1257
|
+
|
|
1258
|
+
Revisan la forma y leen los archivos; si el RFC existe, si la factura sigue vigente y si la llave abre lo dice su servidor.
|
|
1259
|
+
|
|
838
1260
|
## Dinero sin problemas de decimales
|
|
839
1261
|
|
|
840
1262
|
En JavaScript `0.1 + 0.2` da `0.30000000000000004`. `Money` guarda los montos en centavos enteros (como el Money de PHP
|
package/cli/calcita.js
CHANGED
|
@@ -14,6 +14,7 @@ import {argv, cwd, exit, stdin, stdout} from 'node:process';
|
|
|
14
14
|
import {parseArgs} from 'node:util';
|
|
15
15
|
|
|
16
16
|
import {askQuestions} from './askQuestions.js';
|
|
17
|
+
import {checkTexts} from './checkTexts.js';
|
|
17
18
|
import {makeComponent} from './makeComponent.js';
|
|
18
19
|
import {makeForm} from './makeForm.js';
|
|
19
20
|
import {makeModule} from './makeModule.js';
|
|
@@ -33,6 +34,8 @@ const HELP = `Calcita: proyectos y esqueletos con la forma de los ejemplos.
|
|
|
33
34
|
calcita make:form <módulo> <Formulario> un formulario con sus reglas y sus textos
|
|
34
35
|
calcita make:component <Componente> un componente en src/core (lo usan varios módulos)
|
|
35
36
|
--module <módulo> … o solo de un módulo
|
|
37
|
+
calcita check:texts revisa que cada t('llave') exista en todos los idiomas, y que los idiomas tengan
|
|
38
|
+
las mismas llaves (lo que si no se descubre en la pantalla)
|
|
36
39
|
|
|
37
40
|
Opciones:
|
|
38
41
|
-y, --yes sin preguntas: lo recomendado, más lo que diga cada opción
|
|
@@ -125,6 +128,17 @@ async function runMakeComponent(componentName) {
|
|
|
125
128
|
stdout.write('\nListo.\n');
|
|
126
129
|
}
|
|
127
130
|
|
|
131
|
+
async function runCheckTexts() {
|
|
132
|
+
const {problems, checkedKeys, textFiles, languages} = await checkTexts({projectRoot: cwd()});
|
|
133
|
+
stdout.write(`Revisé ${checkedKeys} llaves escritas en el código contra ${textFiles.length} archivos de textos (${languages.join(', ') || 'sin idiomas'}).\n`);
|
|
134
|
+
if (problems.length === 0) {
|
|
135
|
+
stdout.write('Todo en su lugar.\n');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
stdout.write(`\n${problems.map((problem) => ` ✗ ${problem}`).join('\n')}\n`);
|
|
139
|
+
throw new CliError(`${problems.length} problema(s) con los textos.`);
|
|
140
|
+
}
|
|
141
|
+
|
|
128
142
|
const COMMANDS = Object.freeze({
|
|
129
143
|
'new': runNew,
|
|
130
144
|
'init': () => runNew('.'),
|
|
@@ -132,6 +146,7 @@ const COMMANDS = Object.freeze({
|
|
|
132
146
|
'make:page': runMakePage,
|
|
133
147
|
'make:form': runMakeForm,
|
|
134
148
|
'make:component': runMakeComponent,
|
|
149
|
+
'check:texts': runCheckTexts,
|
|
135
150
|
});
|
|
136
151
|
|
|
137
152
|
try {
|