@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubmitButton.js","sources":["../../src/hookForm/SubmitButton.jsx"],"sourcesContent":["// Botón de enviar de react-hook-form: se bloquea y muestra su indicador mientras se envía (un doble clic no manda dos\n// peticiones). Mismo look que el SubmitButton de formik.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormContext, useFormState} from 'react-hook-form';\nimport Button from '@mui/material/Button';\nimport CircularProgress from '@mui/material/CircularProgress';\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode} props.children\n * @param {boolean} [props.disabled]\n * @param {boolean} [props.isPending] cuando el envío lo lleva una máquina de estados y no el handleSubmit\n * @param {object} [props.control] el de useForm, si la pantalla no usa FormProvider\n * @param {object} [props.sx] (y lo demás del Button de MUI: size, fullWidth, startIcon…)\n * @param {'small'|'medium'|'large'} [props.size]\n * @param {boolean} [props.fullWidth]\n * @param {import('react').ReactNode} [props.startIcon]\n */\
|
|
1
|
+
{"version":3,"file":"SubmitButton.js","sources":["../../src/hookForm/SubmitButton.jsx"],"sourcesContent":["// Botón de enviar de react-hook-form: se bloquea y muestra su indicador mientras se envía (un doble clic no manda dos\n// peticiones). Mismo look que el SubmitButton de formik.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaSubmitButton con defaultProps, styleOverrides de\n// sus partes (root) y slots/slotProps para cambiarlas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useFormContext, useFormState} from 'react-hook-form';\nimport Button from '@mui/material/Button';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaSubmitButton)\nconst THEME_NAME = 'CalcitaSubmitButton';\nconst SubmitButtonRoot = piecePart(THEME_NAME, 'Root', Button);\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode} props.children\n * @param {boolean} [props.disabled]\n * @param {boolean} [props.isPending] cuando el envío lo lleva una máquina de estados y no el handleSubmit\n * @param {object} [props.control] el de useForm, si la pantalla no usa FormProvider\n * @param {object} [props.sx] (y lo demás del Button de MUI: size, fullWidth, startIcon…)\n * @param {'small'|'medium'|'large'} [props.size]\n * @param {boolean} [props.fullWidth]\n * @param {import('react').ReactNode} [props.startIcon]\n */\nfunction SubmitButtonContent(props) {\n const {children, disabled, isPending, control, ...buttonProps} = usePieceProps(props, THEME_NAME);\n const formContext = useFormContext();\n const {isSubmitting} = useFormState({control: control ?? formContext?.control});\n const isBusy = Boolean(isPending ?? isSubmitting);\n\n return (\n <SubmitButtonRoot type=\"submit\" variant=\"contained\" size=\"large\" disabled={disabled || isBusy} aria-busy={isBusy} {...buttonProps}>\n {isBusy ? <CircularProgress size={22} color=\"inherit\" /> : children}\n </SubmitButtonRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst SubmitButton = withPieceSlots(SubmitButtonContent, THEME_NAME);\nexport default SubmitButton;\n"],"names":[],"mappings":";;;;;;AAaA,MAAM,aAAa;AACnB,MAAM,mBAAmB,UAAU,YAAY,QAAQ,MAAM;AAa7D,SAAS,oBAAoB,OAAO;AAChC,QAAM,EAAC,UAAU,UAAU,WAAW,SAAS,GAAG,gBAAe,cAAc,OAAO,UAAU;AAChG,QAAM,cAAc,eAAA;AACpB,QAAM,EAAC,iBAAgB,aAAa,EAAC,SAAS,WAAW,aAAa,SAAQ;AAC9E,QAAM,SAAS,QAAQ,aAAa,YAAY;AAEhD,SACI,oBAAC,oBAAiB,MAAK,UAAS,SAAQ,aAAY,MAAK,SAAQ,UAAU,YAAY,QAAQ,aAAW,QAAS,GAAG,aACjH,UAAA,SAAS,oBAAC,kBAAA,EAAiB,MAAM,IAAI,OAAM,WAAU,IAAK,SAAA,CAC/D;AAER;AAGA,MAAM,eAAe,eAAe,qBAAqB,UAAU;"}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
import { splitServerFieldErrors, formLevelMessageOf } from "../forms/serverProblemFields.js";
|
|
1
|
+
import { splitRowFieldErrors, splitServerFieldErrors, formLevelMessageOf } from "../forms/serverProblemFields.js";
|
|
2
2
|
import { fieldErrorsOf } from "../problems.js";
|
|
3
3
|
const SERVER_PROBLEM_ROOT = "root.server";
|
|
4
4
|
const SERVER_ERROR_TYPE = "server";
|
|
5
5
|
function applyServerProblem(error, { setError, getValues }) {
|
|
6
|
-
const
|
|
6
|
+
const { rowFieldErrors, otherErrors } = splitRowFieldErrors(error?.problem?.errors, (path) => getValues(path) !== void 0);
|
|
7
|
+
for (const [path, message] of Object.entries(rowFieldErrors)) {
|
|
8
|
+
setError(path, { type: SERVER_ERROR_TYPE, message }, { shouldFocus: false });
|
|
9
|
+
}
|
|
10
|
+
const errorsByField = fieldErrorsOf(error?.problem ? { ...error.problem, errors: otherErrors } : null);
|
|
7
11
|
const formFieldNames = Object.keys(getValues() ?? {});
|
|
8
12
|
const { fieldErrors } = splitServerFieldErrors(errorsByField, formFieldNames);
|
|
9
13
|
for (const [fieldName, message] of Object.entries(fieldErrors)) {
|
|
10
14
|
setError(fieldName, { type: SERVER_ERROR_TYPE, message }, { shouldFocus: false });
|
|
11
15
|
}
|
|
12
|
-
const
|
|
16
|
+
const hasOnlyRowErrors = Object.keys(rowFieldErrors).length > 0 && Object.keys(errorsByField).length === 0;
|
|
17
|
+
const formLevelMessage = hasOnlyRowErrors ? null : formLevelMessageOf(errorsByField, formFieldNames, error?.message);
|
|
13
18
|
if (formLevelMessage) {
|
|
14
19
|
setError(SERVER_PROBLEM_ROOT, { type: SERVER_ERROR_TYPE, message: formLevelMessage });
|
|
15
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"applyServerProblem.js","sources":["../../src/hookForm/applyServerProblem.js"],"sourcesContent":["// Del error del servidor (RFC 9457) a react-hook-form, con las mismas reglas que el applyServerProblem de formik:\n// - el 422 trae `errors` por campo y cada uno se pinta EN su campo (setError);\n// - lo que no es de un campo (401, 409, 500, sin conexión) o el error de un campo que el formulario no tiene va al aviso\n// de arriba: errors.root.server, que pinta FormProblemAlert.\n//\n// const form = useForm({...});\n// const submit = form.handleSubmit(async (values) => {\n// try { await api.save(values); } catch (error) { applyServerProblem(error, form); }\n// });\n//\n// Función pura, no renderiza: function (regla de la casa).\nimport {formLevelMessageOf, splitServerFieldErrors} from '@/forms/serverProblemFields.js';\nimport {fieldErrorsOf} from '@/problems.js';\n\n/** Dónde queda el aviso de arriba en los errores de react-hook-form. */\nexport const SERVER_PROBLEM_ROOT = 'root.server';\nconst SERVER_ERROR_TYPE = 'server';\n\n/**\n * @param {unknown} error normalmente un ApiError (trae problem y message ya traducidos)\n * @param {{setError: Function, getValues: Function}} form lo que regresa useForm\n */\nexport function applyServerProblem(error, {setError, getValues}) {\n const errorsByField = fieldErrorsOf(error?.problem);\n const formFieldNames = Object.keys(getValues() ?? {});\n const {fieldErrors} = splitServerFieldErrors(errorsByField, formFieldNames);\n\n for (const [fieldName, message] of Object.entries(fieldErrors)) {\n setError(fieldName, {type: SERVER_ERROR_TYPE, message}, {shouldFocus: false});\n }\n\n const formLevelMessage = formLevelMessageOf(errorsByField, formFieldNames, error?.message);\n if (formLevelMessage) {\n setError(SERVER_PROBLEM_ROOT, {type: SERVER_ERROR_TYPE, message: formLevelMessage});\n }\n}\n"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"applyServerProblem.js","sources":["../../src/hookForm/applyServerProblem.js"],"sourcesContent":["// Del error del servidor (RFC 9457) a react-hook-form, con las mismas reglas que el applyServerProblem de formik:\n// - el 422 trae `errors` por campo y cada uno se pinta EN su campo (setError); el de un campo dentro de un renglón que el\n// formulario tiene ('contacts.2.email', FormRepeatingFields) va a ese renglón;\n// - lo que no es de un campo (401, 409, 500, sin conexión) o el error de un campo que el formulario no tiene va al aviso\n// de arriba: errors.root.server, que pinta FormProblemAlert.\n//\n// const form = useForm({...});\n// const submit = form.handleSubmit(async (values) => {\n// try { await api.save(values); } catch (error) { applyServerProblem(error, form); }\n// });\n//\n// Función pura, no renderiza: function (regla de la casa).\nimport {formLevelMessageOf, splitRowFieldErrors, splitServerFieldErrors} from '@/forms/serverProblemFields.js';\nimport {fieldErrorsOf} from '@/problems.js';\n\n/** Dónde queda el aviso de arriba en los errores de react-hook-form. */\nexport const SERVER_PROBLEM_ROOT = 'root.server';\nconst SERVER_ERROR_TYPE = 'server';\n\n/**\n * @param {unknown} error normalmente un ApiError (trae problem y message ya traducidos)\n * @param {{setError: Function, getValues: Function}} form lo que regresa useForm\n */\nexport function applyServerProblem(error, {setError, getValues}) {\n // primero los de un renglón ('contacts.2.email'), con su ruta completa; los demás, como siempre\n const {rowFieldErrors, otherErrors} = splitRowFieldErrors(error?.problem?.errors, (path) => getValues(path) !== undefined);\n for (const [path, message] of Object.entries(rowFieldErrors)) {\n setError(path, {type: SERVER_ERROR_TYPE, message}, {shouldFocus: false});\n }\n const errorsByField = fieldErrorsOf(error?.problem ? {...error.problem, errors: otherErrors} : null);\n const formFieldNames = Object.keys(getValues() ?? {});\n const {fieldErrors} = splitServerFieldErrors(errorsByField, formFieldNames);\n\n for (const [fieldName, message] of Object.entries(fieldErrors)) {\n setError(fieldName, {type: SERVER_ERROR_TYPE, message}, {shouldFocus: false});\n }\n\n // si todo cayó en renglones, tampoco se repite arriba\n const hasOnlyRowErrors = Object.keys(rowFieldErrors).length > 0 && Object.keys(errorsByField).length === 0;\n const formLevelMessage = hasOnlyRowErrors ? null : formLevelMessageOf(errorsByField, formFieldNames, error?.message);\n if (formLevelMessage) {\n setError(SERVER_PROBLEM_ROOT, {type: SERVER_ERROR_TYPE, message: formLevelMessage});\n }\n}\n"],"names":[],"mappings":";;AAgBY,MAAC,sBAAsB;AACnC,MAAM,oBAAoB;AAMnB,SAAS,mBAAmB,OAAO,EAAC,UAAU,UAAS,GAAG;AAE7D,QAAM,EAAC,gBAAgB,YAAW,IAAI,oBAAoB,OAAO,SAAS,QAAQ,CAAC,SAAS,UAAU,IAAI,MAAM,MAAS;AACzH,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,cAAc,GAAG;AAC1D,aAAS,MAAM,EAAC,MAAM,mBAAmB,QAAO,GAAG,EAAC,aAAa,MAAK,CAAC;AAAA,EAC3E;AACA,QAAM,gBAAgB,cAAc,OAAO,UAAU,EAAC,GAAG,MAAM,SAAS,QAAQ,YAAW,IAAI,IAAI;AACnG,QAAM,iBAAiB,OAAO,KAAK,UAAS,KAAM,CAAA,CAAE;AACpD,QAAM,EAAC,YAAW,IAAI,uBAAuB,eAAe,cAAc;AAE1E,aAAW,CAAC,WAAW,OAAO,KAAK,OAAO,QAAQ,WAAW,GAAG;AAC5D,aAAS,WAAW,EAAC,MAAM,mBAAmB,QAAO,GAAG,EAAC,aAAa,MAAK,CAAC;AAAA,EAChF;AAGA,QAAM,mBAAmB,OAAO,KAAK,cAAc,EAAE,SAAS,KAAK,OAAO,KAAK,aAAa,EAAE,WAAW;AACzG,QAAM,mBAAmB,mBAAmB,OAAO,mBAAmB,eAAe,gBAAgB,OAAO,OAAO;AACnH,MAAI,kBAAkB;AAClB,aAAS,qBAAqB,EAAC,MAAM,mBAAmB,SAAS,iBAAgB,CAAC;AAAA,EACtF;AACJ;"}
|
|
@@ -15,7 +15,7 @@ import Typography from "@mui/material/Typography";
|
|
|
15
15
|
import ArrowBackRoundedIcon from "@mui/icons-material/ArrowBackRounded";
|
|
16
16
|
import { PHONE_MEDIA_QUERY, DESKTOP_MEDIA_QUERY } from "../appShell/shellSizes.js";
|
|
17
17
|
import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
|
|
18
|
-
import { piecePart, usePieceProps } from "../theme/themePieces.js";
|
|
18
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
|
|
19
19
|
import { warnUnknownProps } from "../toolkit/unknownProps.js";
|
|
20
20
|
const THEME_NAME = "CalcitaInboxLayout";
|
|
21
21
|
const InboxLabelDot = piecePart(THEME_NAME, "LabelDot", Box);
|
|
@@ -52,7 +52,7 @@ function FolderRow({ folder, isSelected, onSelect, t }) {
|
|
|
52
52
|
unreadCount > 0 && /* @__PURE__ */ jsx(InboxFolderCount, { variant: "caption", ownSx: { fontWeight: 700 }, "aria-label": t("unreadCount", { count: unreadCount }), children: unreadCount })
|
|
53
53
|
] });
|
|
54
54
|
}
|
|
55
|
-
function
|
|
55
|
+
function InboxLayoutContent(props) {
|
|
56
56
|
const {
|
|
57
57
|
folders,
|
|
58
58
|
labels = [],
|
|
@@ -119,6 +119,7 @@ function InboxLayout(props) {
|
|
|
119
119
|
] })
|
|
120
120
|
] });
|
|
121
121
|
}
|
|
122
|
+
const InboxLayout = withPieceSlots(InboxLayoutContent, THEME_NAME);
|
|
122
123
|
export {
|
|
123
124
|
InboxLayout as default
|
|
124
125
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InboxLayout.js","sources":["../../src/inbox/InboxLayout.jsx"],"sourcesContent":["// El acomodo de una bandeja tipo correo: las carpetas, la lista y la lectura. En escritorio, tres columnas; en el teléfono,\n// una a la vez: las carpetas como pestañas arriba de la lista y, al abrir un mensaje, la lectura con «Regresar».\n//\n// <InboxLayout folders={folders} selectedFolderId={folderId} onSelectFolder={setFolderId} toolbar={<Buscar y Redactar />}\n// list={<MessageList … />} detail={<MessageView … />} isDetailOpen={Boolean(selectedId)} onCloseDetail={() => setSelectedId(null)} />\n//\n// Debajo de las carpetas, las etiquetas del proyecto (labels) con su punto de color, como Gmail; se eligen igual que una\n// carpeta. foldersHeader pone algo arriba de las carpetas (un botón «Redactar») y texts cambia cualquier texto.\n//\n// Escritorio o teléfono se decide con CSS (no con useMediaQuery): así el servidor pinta lo mismo que el navegador.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaInboxLayout con defaultProps y\n// styleOverrides de sus partes: labelDot, folder, folderIcon, folderCount, root, folders, foldersHeader, labelsTitle,\n// listPane, phoneTabs, phoneTabBadge, listHeader, list, detail, backButton.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Badge from '@mui/material/Badge';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport List from '@mui/material/List';\nimport ListItemButton from '@mui/material/ListItemButton';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport ListSubheader from '@mui/material/ListSubheader';\nimport Paper from '@mui/material/Paper';\nimport Tab from '@mui/material/Tab';\nimport Tabs from '@mui/material/Tabs';\nimport Typography from '@mui/material/Typography';\nimport ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded';\n\nimport {DESKTOP_MEDIA_QUERY, PHONE_MEDIA_QUERY} from '@/appShell/shellSizes.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaInboxLayout)\nconst THEME_NAME = 'CalcitaInboxLayout';\nconst InboxLabelDot = piecePart(THEME_NAME, 'LabelDot', Box);\nconst InboxFolder = piecePart(THEME_NAME, 'Folder', ListItemButton);\nconst InboxFolderIcon = piecePart(THEME_NAME, 'FolderIcon', ListItemIcon);\nconst InboxFolderCount = piecePart(THEME_NAME, 'FolderCount', Typography);\nconst InboxRoot = piecePart(THEME_NAME, 'Root', Box);\nconst InboxFolders = piecePart(THEME_NAME, 'Folders', Paper);\nconst InboxFoldersHeader = piecePart(THEME_NAME, 'FoldersHeader', Box);\nconst InboxLabelsTitle = piecePart(THEME_NAME, 'LabelsTitle', ListSubheader);\nconst InboxListPane = piecePart(THEME_NAME, 'ListPane', Paper);\nconst InboxPhoneTabs = piecePart(THEME_NAME, 'PhoneTabs', Tabs);\nconst InboxPhoneTabBadge = piecePart(THEME_NAME, 'PhoneTabBadge', Badge);\nconst InboxListHeader = piecePart(THEME_NAME, 'ListHeader', Box);\nconst InboxList = piecePart(THEME_NAME, 'List', Box);\nconst InboxDetail = piecePart(THEME_NAME, 'Detail', Paper);\nconst InboxBackButton = piecePart(THEME_NAME, 'BackButton', Button);\n\nconst FOLDERS_WIDTH_PIXELS = 220;\nconst LIST_WIDTH_PIXELS = 380;\n// la bandeja ocupa el alto de la ventana (menos la barra y el encabezado de la página): cada columna desliza por dentro\nconst DESKTOP_HEIGHT = 'calc(100dvh - 220px)';\nconst DESKTOP_MIN_HEIGHT_PIXELS = 480;\nconst LABEL_DOT_PIXELS = 10;\n\n/** Un renglón de carpeta o etiqueta: su ícono (o su punto de color), su nombre y cuántos sin leer. */\nfunction FolderRow({folder, isSelected, onSelect, t}) {\n const {id, label, Icon, color, unreadCount} = folder;\n let icon = null;\n if (Icon) {\n icon = <Icon fontSize=\"small\" />;\n } else if (color) {\n icon = <InboxLabelDot aria-hidden=\"true\" ownSx={{width: LABEL_DOT_PIXELS, height: LABEL_DOT_PIXELS, borderRadius: '50%', bgcolor: `${color}.main`, ml: 0.5}} />;\n }\n return (\n <InboxFolder selected={isSelected} onClick={() => onSelect(id)} ownSx={{borderRadius: 2}}>\n {icon && <InboxFolderIcon ownSx={{minWidth: 36}}>{icon}</InboxFolderIcon>}\n <ListItemText primary={label} />\n {unreadCount > 0 && <InboxFolderCount variant=\"caption\" ownSx={{fontWeight: 700}} aria-label={t('unreadCount', {count: unreadCount})}>{unreadCount}</InboxFolderCount>}\n </InboxFolder>\n );\n}\n\n/**\n * @param {object} props\n * @param {Array<{id: string, label: string, Icon?: import('react').ElementType, unreadCount?: number}>} props.folders\n * @param {Array<{id: string, label: string, color?: string, unreadCount?: number}>} [props.labels] las etiquetas, debajo de las\n * carpetas con su punto de color (un color del tema); su id no debe repetir el de una carpeta\n * @param {string} props.selectedFolderId la carpeta o etiqueta elegida\n * @param {(folderId: string) => void} props.onSelectFolder\n * @param {import('react').ReactNode} [props.toolbar] arriba de la lista (buscar, redactar)\n * @param {import('react').ReactNode} props.list normalmente MessageList\n * @param {import('react').ReactNode} props.detail normalmente MessageView\n * @param {boolean} [props.isDetailOpen] en el teléfono, se ve la lectura en lugar de la lista\n * @param {() => void} [props.onCloseDetail] «Regresar» del teléfono\n * @param {import('react').ReactNode} [props.foldersHeader] arriba de las carpetas en escritorio (un botón «Redactar»)\n * @param {object} [props.texts] los textos que cambian, con la forma de `inbox` en los textos del paquete\n */\nexport default function InboxLayout(props) {\n // lo que el proyecto puso en su tema (components.CalcitaInboxLayout.defaultProps) y encima lo que llega aquí\n const {\n folders, labels = [], selectedFolderId, onSelectFolder, toolbar, list, detail, isDetailOpen = false, onCloseDetail, foldersHeader, texts,\n ...unknownProps\n} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('inbox', texts);\n\n return (\n <InboxRoot ownSx={{\n display: 'grid', gap: 2,\n [DESKTOP_MEDIA_QUERY]: {\n gridTemplateColumns: `${FOLDERS_WIDTH_PIXELS}px ${LIST_WIDTH_PIXELS}px minmax(0, 1fr)`, height: DESKTOP_HEIGHT, minHeight: DESKTOP_MIN_HEIGHT_PIXELS,\n },\n }}>\n {/* las carpetas: columna en escritorio */}\n <InboxFolders variant=\"outlined\" component=\"nav\" aria-label={t('folders')} ownSx={{p: 1, overflowY: 'auto', borderRadius: 3, [PHONE_MEDIA_QUERY]: {display: 'none'}}}>\n {foldersHeader && <InboxFoldersHeader ownSx={{p: 0.5, pb: 1}}>{foldersHeader}</InboxFoldersHeader>}\n <List disablePadding>\n {folders.map((folder) => (\n <FolderRow key={folder.id} folder={folder} isSelected={folder.id === selectedFolderId} onSelect={onSelectFolder} t={t} />\n ))}\n </List>\n {labels.length > 0 && (\n <List disablePadding aria-label={t('labels')}\n subheader={<InboxLabelsTitle disableSticky ownSx={{bgcolor: 'transparent', lineHeight: 2.5, mt: 1}}>{t('labels')}</InboxLabelsTitle>}>\n {labels.map((label) => (\n <FolderRow key={label.id} folder={label} isSelected={label.id === selectedFolderId} onSelect={onSelectFolder} t={t} />\n ))}\n </List>\n )}\n </InboxFolders>\n\n {/* la lista, con las carpetas como pestañas en el teléfono */}\n <InboxListPane variant=\"outlined\" ownSx={{display: 'flex', flexDirection: 'column', minHeight: 0, borderRadius: 3, overflow: 'hidden',\n [PHONE_MEDIA_QUERY]: isDetailOpen ? {display: 'none'} : {}}}>\n <InboxPhoneTabs value={selectedFolderId} onChange={(event, folderId) => onSelectFolder(folderId)} variant=\"scrollable\" aria-label={t('folders')}\n ownSx={{px: 1, [DESKTOP_MEDIA_QUERY]: {display: 'none'}}}>\n {[...folders, ...labels].map(({id, label, unreadCount}) => (\n <Tab key={id} value={id} label={unreadCount > 0 ? <InboxPhoneTabBadge color=\"primary\" badgeContent={unreadCount} ownSx={{pr: 1.5}}>{label}</InboxPhoneTabBadge> : label} />\n ))}\n </InboxPhoneTabs>\n {toolbar && <InboxListHeader ownSx={{p: 1.5, pb: 1}}>{toolbar}</InboxListHeader>}\n <InboxList ownSx={{flex: 1, minHeight: 0, overflowY: 'auto', px: 1, pb: 1}}>{list}</InboxList>\n </InboxListPane>\n\n {/* la lectura: en el teléfono solo con un mensaje abierto, con su «Regresar» */}\n <InboxDetail variant=\"outlined\" ownSx={{p: {xs: 2, md: 3}, overflowY: 'auto', borderRadius: 3, [PHONE_MEDIA_QUERY]: isDetailOpen ? {} : {display: 'none'}}}>\n {onCloseDetail && (\n <InboxBackButton startIcon={<ArrowBackRoundedIcon />} onClick={onCloseDetail} ownSx={{mb: 1, [DESKTOP_MEDIA_QUERY]: {display: 'none'}}}>{t('back')}</InboxBackButton>\n )}\n {detail}\n </InboxDetail>\n </InboxRoot>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InboxLayout.js","sources":["../../src/inbox/InboxLayout.jsx"],"sourcesContent":["// El acomodo de una bandeja tipo correo: las carpetas, la lista y la lectura. En escritorio, tres columnas; en el teléfono,\n// una a la vez: las carpetas como pestañas arriba de la lista y, al abrir un mensaje, la lectura con «Regresar».\n//\n// <InboxLayout folders={folders} selectedFolderId={folderId} onSelectFolder={setFolderId} toolbar={<Buscar y Redactar />}\n// list={<MessageList … />} detail={<MessageView … />} isDetailOpen={Boolean(selectedId)} onCloseDetail={() => setSelectedId(null)} />\n//\n// Debajo de las carpetas, las etiquetas del proyecto (labels) con su punto de color, como Gmail; se eligen igual que una\n// carpeta. foldersHeader pone algo arriba de las carpetas (un botón «Redactar») y texts cambia cualquier texto.\n//\n// Escritorio o teléfono se decide con CSS (no con useMediaQuery): así el servidor pinta lo mismo que el navegador.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaInboxLayout con defaultProps y\n// styleOverrides de sus partes: labelDot, folder, folderIcon, folderCount, root, folders, foldersHeader, labelsTitle,\n// listPane, phoneTabs, phoneTabBadge, listHeader, list, detail, backButton.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Badge from '@mui/material/Badge';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport List from '@mui/material/List';\nimport ListItemButton from '@mui/material/ListItemButton';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport ListSubheader from '@mui/material/ListSubheader';\nimport Paper from '@mui/material/Paper';\nimport Tab from '@mui/material/Tab';\nimport Tabs from '@mui/material/Tabs';\nimport Typography from '@mui/material/Typography';\nimport ArrowBackRoundedIcon from '@mui/icons-material/ArrowBackRounded';\n\nimport {DESKTOP_MEDIA_QUERY, PHONE_MEDIA_QUERY} from '@/appShell/shellSizes.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaInboxLayout)\nconst THEME_NAME = 'CalcitaInboxLayout';\nconst InboxLabelDot = piecePart(THEME_NAME, 'LabelDot', Box);\nconst InboxFolder = piecePart(THEME_NAME, 'Folder', ListItemButton);\nconst InboxFolderIcon = piecePart(THEME_NAME, 'FolderIcon', ListItemIcon);\nconst InboxFolderCount = piecePart(THEME_NAME, 'FolderCount', Typography);\nconst InboxRoot = piecePart(THEME_NAME, 'Root', Box);\nconst InboxFolders = piecePart(THEME_NAME, 'Folders', Paper);\nconst InboxFoldersHeader = piecePart(THEME_NAME, 'FoldersHeader', Box);\nconst InboxLabelsTitle = piecePart(THEME_NAME, 'LabelsTitle', ListSubheader);\nconst InboxListPane = piecePart(THEME_NAME, 'ListPane', Paper);\nconst InboxPhoneTabs = piecePart(THEME_NAME, 'PhoneTabs', Tabs);\nconst InboxPhoneTabBadge = piecePart(THEME_NAME, 'PhoneTabBadge', Badge);\nconst InboxListHeader = piecePart(THEME_NAME, 'ListHeader', Box);\nconst InboxList = piecePart(THEME_NAME, 'List', Box);\nconst InboxDetail = piecePart(THEME_NAME, 'Detail', Paper);\nconst InboxBackButton = piecePart(THEME_NAME, 'BackButton', Button);\n\nconst FOLDERS_WIDTH_PIXELS = 220;\nconst LIST_WIDTH_PIXELS = 380;\n// la bandeja ocupa el alto de la ventana (menos la barra y el encabezado de la página): cada columna desliza por dentro\nconst DESKTOP_HEIGHT = 'calc(100dvh - 220px)';\nconst DESKTOP_MIN_HEIGHT_PIXELS = 480;\nconst LABEL_DOT_PIXELS = 10;\n\n/** Un renglón de carpeta o etiqueta: su ícono (o su punto de color), su nombre y cuántos sin leer. */\nfunction FolderRow({folder, isSelected, onSelect, t}) {\n const {id, label, Icon, color, unreadCount} = folder;\n let icon = null;\n if (Icon) {\n icon = <Icon fontSize=\"small\" />;\n } else if (color) {\n icon = <InboxLabelDot aria-hidden=\"true\" ownSx={{width: LABEL_DOT_PIXELS, height: LABEL_DOT_PIXELS, borderRadius: '50%', bgcolor: `${color}.main`, ml: 0.5}} />;\n }\n return (\n <InboxFolder selected={isSelected} onClick={() => onSelect(id)} ownSx={{borderRadius: 2}}>\n {icon && <InboxFolderIcon ownSx={{minWidth: 36}}>{icon}</InboxFolderIcon>}\n <ListItemText primary={label} />\n {unreadCount > 0 && <InboxFolderCount variant=\"caption\" ownSx={{fontWeight: 700}} aria-label={t('unreadCount', {count: unreadCount})}>{unreadCount}</InboxFolderCount>}\n </InboxFolder>\n );\n}\n\n/**\n * @param {object} props\n * @param {Array<{id: string, label: string, Icon?: import('react').ElementType, unreadCount?: number}>} props.folders\n * @param {Array<{id: string, label: string, color?: string, unreadCount?: number}>} [props.labels] las etiquetas, debajo de las\n * carpetas con su punto de color (un color del tema); su id no debe repetir el de una carpeta\n * @param {string} props.selectedFolderId la carpeta o etiqueta elegida\n * @param {(folderId: string) => void} props.onSelectFolder\n * @param {import('react').ReactNode} [props.toolbar] arriba de la lista (buscar, redactar)\n * @param {import('react').ReactNode} props.list normalmente MessageList\n * @param {import('react').ReactNode} props.detail normalmente MessageView\n * @param {boolean} [props.isDetailOpen] en el teléfono, se ve la lectura en lugar de la lista\n * @param {() => void} [props.onCloseDetail] «Regresar» del teléfono\n * @param {import('react').ReactNode} [props.foldersHeader] arriba de las carpetas en escritorio (un botón «Redactar»)\n * @param {object} [props.texts] los textos que cambian, con la forma de `inbox` en los textos del paquete\n */\nfunction InboxLayoutContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaInboxLayout.defaultProps) y encima lo que llega aquí\n const {\n folders, labels = [], selectedFolderId, onSelectFolder, toolbar, list, detail, isDetailOpen = false, onCloseDetail, foldersHeader, texts,\n ...unknownProps\n} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('inbox', texts);\n\n return (\n <InboxRoot ownSx={{\n display: 'grid', gap: 2,\n [DESKTOP_MEDIA_QUERY]: {\n gridTemplateColumns: `${FOLDERS_WIDTH_PIXELS}px ${LIST_WIDTH_PIXELS}px minmax(0, 1fr)`, height: DESKTOP_HEIGHT, minHeight: DESKTOP_MIN_HEIGHT_PIXELS,\n },\n }}>\n {/* las carpetas: columna en escritorio */}\n <InboxFolders variant=\"outlined\" component=\"nav\" aria-label={t('folders')} ownSx={{p: 1, overflowY: 'auto', borderRadius: 3, [PHONE_MEDIA_QUERY]: {display: 'none'}}}>\n {foldersHeader && <InboxFoldersHeader ownSx={{p: 0.5, pb: 1}}>{foldersHeader}</InboxFoldersHeader>}\n <List disablePadding>\n {folders.map((folder) => (\n <FolderRow key={folder.id} folder={folder} isSelected={folder.id === selectedFolderId} onSelect={onSelectFolder} t={t} />\n ))}\n </List>\n {labels.length > 0 && (\n <List disablePadding aria-label={t('labels')}\n subheader={<InboxLabelsTitle disableSticky ownSx={{bgcolor: 'transparent', lineHeight: 2.5, mt: 1}}>{t('labels')}</InboxLabelsTitle>}>\n {labels.map((label) => (\n <FolderRow key={label.id} folder={label} isSelected={label.id === selectedFolderId} onSelect={onSelectFolder} t={t} />\n ))}\n </List>\n )}\n </InboxFolders>\n\n {/* la lista, con las carpetas como pestañas en el teléfono */}\n <InboxListPane variant=\"outlined\" ownSx={{display: 'flex', flexDirection: 'column', minHeight: 0, borderRadius: 3, overflow: 'hidden',\n [PHONE_MEDIA_QUERY]: isDetailOpen ? {display: 'none'} : {}}}>\n <InboxPhoneTabs value={selectedFolderId} onChange={(event, folderId) => onSelectFolder(folderId)} variant=\"scrollable\" aria-label={t('folders')}\n ownSx={{px: 1, [DESKTOP_MEDIA_QUERY]: {display: 'none'}}}>\n {[...folders, ...labels].map(({id, label, unreadCount}) => (\n <Tab key={id} value={id} label={unreadCount > 0 ? <InboxPhoneTabBadge color=\"primary\" badgeContent={unreadCount} ownSx={{pr: 1.5}}>{label}</InboxPhoneTabBadge> : label} />\n ))}\n </InboxPhoneTabs>\n {toolbar && <InboxListHeader ownSx={{p: 1.5, pb: 1}}>{toolbar}</InboxListHeader>}\n <InboxList ownSx={{flex: 1, minHeight: 0, overflowY: 'auto', px: 1, pb: 1}}>{list}</InboxList>\n </InboxListPane>\n\n {/* la lectura: en el teléfono solo con un mensaje abierto, con su «Regresar» */}\n <InboxDetail variant=\"outlined\" ownSx={{p: {xs: 2, md: 3}, overflowY: 'auto', borderRadius: 3, [PHONE_MEDIA_QUERY]: isDetailOpen ? {} : {display: 'none'}}}>\n {onCloseDetail && (\n <InboxBackButton startIcon={<ArrowBackRoundedIcon />} onClick={onCloseDetail} ownSx={{mb: 1, [DESKTOP_MEDIA_QUERY]: {display: 'none'}}}>{t('back')}</InboxBackButton>\n )}\n {detail}\n </InboxDetail>\n </InboxRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst InboxLayout = withPieceSlots(InboxLayoutContent, THEME_NAME);\nexport default InboxLayout;\n"],"names":[],"mappings":"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"}
|
|
@@ -21,7 +21,7 @@ import { useFormatters } from "../toolkit/useFormatters.js";
|
|
|
21
21
|
import { tagOf } from "../ui/labels/tagOf.js";
|
|
22
22
|
import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
|
|
23
23
|
import ActionsMenu from "../ui/actions/ActionsMenu.js";
|
|
24
|
-
import { piecePart, usePieceProps } from "../theme/themePieces.js";
|
|
24
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
|
|
25
25
|
import { warnUnknownProps } from "../toolkit/unknownProps.js";
|
|
26
26
|
const THEME_NAME = "CalcitaMessageList";
|
|
27
27
|
const MessagesEmpty = piecePart(THEME_NAME, "Empty", Typography);
|
|
@@ -44,7 +44,7 @@ const MessagesSubject = piecePart(THEME_NAME, "Subject", Typography);
|
|
|
44
44
|
const MessagesLabels = piecePart(THEME_NAME, "Labels", Stack);
|
|
45
45
|
const UNREAD_DOT_PIXELS = 8;
|
|
46
46
|
const AVATAR_PIXELS = 40;
|
|
47
|
-
function
|
|
47
|
+
function MessageListContent(props) {
|
|
48
48
|
const {
|
|
49
49
|
messages,
|
|
50
50
|
selectedId = null,
|
|
@@ -132,6 +132,7 @@ function MessageList(props) {
|
|
|
132
132
|
) }, message.id);
|
|
133
133
|
}) });
|
|
134
134
|
}
|
|
135
|
+
const MessageList = withPieceSlots(MessageListContent, THEME_NAME);
|
|
135
136
|
export {
|
|
136
137
|
MessageList as default
|
|
137
138
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageList.js","sources":["../../src/inbox/MessageList.jsx"],"sourcesContent":["// La lista de mensajes de una bandeja tipo correo: quién lo manda (y cuántos mensajes trae la conversación), el asunto con sus\n// etiquetas, el principio del texto, la fecha corta, la estrella y el clip si trae archivos. Los no leídos van en negritas con\n// su punto.\n//\n// Lo de un producto, todo hacia afuera (la lista no guarda nada ni llama a ningún servidor):\n// - elegir varios: con onSelectionChange el monograma de cada mensaje se vuelve su casilla (como Gmail en el teléfono) y la\n// pantalla pone las acciones de lo elegido (SelectionActions: archivar, borrar, marcar como leído…);\n// - «⋯» de cada mensaje con las acciones que dé la pantalla (messageActions);\n// - renderMessage para pintar lo de adentro de cada renglón a su manera, y texts para cualquier texto.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaMessageList con defaultProps y\n// styleOverrides de sus partes: empty, selectedAvatar, item, actions, starButton, itemButton, avatarSlot, avatarButton,\n// avatar, body, text, topRow, unreadDot, sender, threadCount, date, subject, labels.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Avatar from '@mui/material/Avatar';\nimport Box from '@mui/material/Box';\nimport ButtonBase from '@mui/material/ButtonBase';\nimport Chip from '@mui/material/Chip';\nimport IconButton from '@mui/material/IconButton';\nimport List from '@mui/material/List';\nimport ListItem from '@mui/material/ListItem';\nimport ListItemAvatar from '@mui/material/ListItemAvatar';\nimport ListItemButton from '@mui/material/ListItemButton';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport AttachFileRoundedIcon from '@mui/icons-material/AttachFileRounded';\nimport CheckRoundedIcon from '@mui/icons-material/CheckRounded';\nimport StarBorderRoundedIcon from '@mui/icons-material/StarBorderRounded';\nimport StarRoundedIcon from '@mui/icons-material/StarRounded';\n\nimport {initialsOf} from '@/appShell/menuItemText.js';\nimport {inboxDateOf} from '@/inbox/inboxDates.js';\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport {tagOf} from '@/ui/labels/tagOf.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport ActionsMenu from '@/ui/actions/ActionsMenu.jsx';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaMessageList)\nconst THEME_NAME = 'CalcitaMessageList';\nconst MessagesEmpty = piecePart(THEME_NAME, 'Empty', Typography);\nconst MessagesSelectedAvatar = piecePart(THEME_NAME, 'SelectedAvatar', Avatar);\nconst MessagesItem = piecePart(THEME_NAME, 'Item', ListItem);\nconst MessagesActions = piecePart(THEME_NAME, 'Actions', Stack);\nconst MessagesStarButton = piecePart(THEME_NAME, 'StarButton', IconButton);\nconst MessagesItemButton = piecePart(THEME_NAME, 'ItemButton', ListItemButton);\nconst MessagesAvatarSlot = piecePart(THEME_NAME, 'AvatarSlot', ListItemAvatar);\nconst MessagesAvatarButton = piecePart(THEME_NAME, 'AvatarButton', ButtonBase);\nconst MessagesAvatar = piecePart(THEME_NAME, 'Avatar', Avatar);\nconst MessagesBody = piecePart(THEME_NAME, 'Body', Box);\nconst MessagesText = piecePart(THEME_NAME, 'Text', Box);\nconst MessagesTopRow = piecePart(THEME_NAME, 'TopRow', Stack);\nconst MessagesUnreadDot = piecePart(THEME_NAME, 'UnreadDot', Box);\nconst MessagesSender = piecePart(THEME_NAME, 'Sender', Typography);\nconst MessagesThreadCount = piecePart(THEME_NAME, 'ThreadCount', Typography);\nconst MessagesDate = piecePart(THEME_NAME, 'Date', Typography);\nconst MessagesSubject = piecePart(THEME_NAME, 'Subject', Typography);\nconst MessagesLabels = piecePart(THEME_NAME, 'Labels', Stack);\n\nconst UNREAD_DOT_PIXELS = 8;\nconst AVATAR_PIXELS = 40;\n\n/**\n * @param {object} props\n * @param {Array<{id: string, from: {name: string, email: string}, subject: string, preview: string, receivedAt: string, isUnread?: boolean, isStarred?: boolean, hasAttachments?: boolean, threadCount?: number, labels?: Array<string|{label: string, color?: string}>} & Record<string, any>>} props.messages\n * cada mensaje puede traer sus campos propios (llegan a renderMessage y a messageActions tal cual). threadCount: cuántos\n * mensajes trae la conversación (con 2 o más se pinta «(3)»); labels: texto o {label, color} del tema\n * @param {string|null} [props.selectedId] el mensaje abierto\n * @param {(messageId: string) => void} props.onSelect abrir un mensaje\n * @param {(messageId: string) => void} [props.onToggleStar]\n * @param {string[]} [props.selectedIds] los elegidos para una acción en grupo\n * @param {(messageIds: string[]) => void} [props.onSelectionChange] con él, cada mensaje se puede elegir picando su monograma\n * @param {(message: any) => Array<{key: string, label: string, icon?: import('react').ReactNode, color?: string, disabled?: boolean, onClick: () => void}>} [props.messageActions]\n * las acciones del «⋯» de cada mensaje (archivar, posponer, mover…); sin ellas no hay «⋯»\n * @param {(message: any) => import('react').ReactNode} [props.renderMessage] lo de adentro de cada renglón, a su manera\n * @param {string} [props.emptyText] ya traducido; por omisión el del paquete\n * @param {object} [props.texts] los textos que cambian, con la forma de `inbox` en los textos del paquete\n */\nexport default function MessageList(props) {\n // lo que el proyecto puso en su tema (components.CalcitaMessageList.defaultProps) y encima lo que llega aquí\n const {\n messages, selectedId = null, onSelect, onToggleStar, selectedIds = [], onSelectionChange, messageActions, renderMessage, emptyText, texts,\n ...unknownProps\n} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('inbox', texts);\n const formatters = useFormatters();\n\n if (messages.length === 0) {\n return <MessagesEmpty variant=\"body2\" color=\"text.secondary\" ownSx={{p: 3, textAlign: 'center'}}>{emptyText ?? t('empty')}</MessagesEmpty>;\n }\n\n const toggleSelected = (messageId, isChecked) => {\n onSelectionChange(isChecked ? [...selectedIds, messageId] : selectedIds.filter((id) => id !== messageId));\n };\n\n return (\n <List disablePadding aria-label={t('listLabel')}>\n {messages.map((message) => {\n const weight = message.isUnread ? 700 : 400;\n const isChecked = selectedIds.includes(message.id);\n const avatar = <MessagesSelectedAvatar ownSx={{width: AVATAR_PIXELS, height: AVATAR_PIXELS}}>{initialsOf(message.from.name)}</MessagesSelectedAvatar>;\n return (\n <MessagesItem key={message.id} disablePadding secondaryAction={(onToggleStar || messageActions) && (\n <MessagesActions direction=\"row\" ownSx={{alignItems: 'center'}}>\n {onToggleStar && (\n <MessagesStarButton size=\"small\" onClick={() => onToggleStar(message.id)} aria-pressed={Boolean(message.isStarred)}\n aria-label={message.isStarred ? t('unstar') : t('star')} ownSx={{color: message.isStarred ? 'warning.main' : 'text.secondary'}}>\n {message.isStarred ? <StarRoundedIcon fontSize=\"small\" /> : <StarBorderRoundedIcon fontSize=\"small\" />}\n </MessagesStarButton>\n )}\n {messageActions && <ActionsMenu label={t('messageActions', {subject: message.subject})} actions={messageActions(message)} />}\n </MessagesActions>\n )} ownSx={{'& .MuiListItemSecondaryAction-root': {right: 4}}}>\n <MessagesItemButton selected={message.id === selectedId || isChecked} onClick={() => onSelect(message.id)} alignItems=\"flex-start\"\n ownSx={{borderRadius: 2, pr: onToggleStar && messageActions ? 10 : 6}}>\n <MessagesAvatarSlot ownSx={{mt: 0.5}}>\n {/* elegir: el monograma es la casilla (el clic no abre el mensaje). Un botón con papel de casilla y\n no el Checkbox de MUI: el tema le pinta a la casilla marcada un cuadro blanco detrás de su dibujo\n y la palomita salía como un cuadro */}\n {onSelectionChange ? (\n <MessagesAvatarButton role=\"checkbox\" aria-checked={isChecked} aria-label={t('select', {subject: message.subject})}\n ownSx={{borderRadius: '50%'}}\n onClick={(event) => {\n event.stopPropagation();\n toggleSelected(message.id, !isChecked);\n }}>\n {isChecked ? (\n <MessagesAvatar ownSx={{width: AVATAR_PIXELS, height: AVATAR_PIXELS, bgcolor: 'primary.main', color: 'primary.contrastText'}}>\n <CheckRoundedIcon />\n </MessagesAvatar>\n ) : avatar}\n </MessagesAvatarButton>\n ) : avatar}\n </MessagesAvatarSlot>\n {renderMessage ? <MessagesBody ownSx={{minWidth: 0, flex: 1}}>{renderMessage(message)}</MessagesBody> : (\n <MessagesText ownSx={{minWidth: 0, flex: 1}}>\n <MessagesTopRow direction=\"row\" spacing={1} ownSx={{alignItems: 'center'}}>\n {message.isUnread && (\n <MessagesUnreadDot component=\"span\" aria-label={t('unread')} ownSx={{width: UNREAD_DOT_PIXELS, height: UNREAD_DOT_PIXELS, borderRadius: '50%', bgcolor: 'primary.main', flexShrink: 0}} />\n )}\n <MessagesSender variant=\"body2\" noWrap ownSx={{fontWeight: weight, flex: 1}}>\n {message.from.name}\n {message.threadCount > 1 && (\n <MessagesThreadCount component=\"span\" variant=\"caption\" color=\"text.secondary\" ownSx={{ml: 0.5}} aria-label={t('threadCount', {count: message.threadCount})}>\n ({message.threadCount})\n </MessagesThreadCount>\n )}\n </MessagesSender>\n {message.hasAttachments && <AttachFileRoundedIcon fontSize=\"inherit\" color=\"action\" aria-label={t('attachments')} />}\n <MessagesDate variant=\"caption\" color=\"text.secondary\" ownSx={{flexShrink: 0, fontVariantNumeric: 'tabular-nums'}}>\n {inboxDateOf(message.receivedAt, new Date(), formatters)}\n </MessagesDate>\n </MessagesTopRow>\n <MessagesSubject variant=\"body2\" noWrap ownSx={{fontWeight: weight}}>{message.subject}</MessagesSubject>\n <Typography variant=\"body2\" color=\"text.secondary\" noWrap>{message.preview}</Typography>\n {message.labels?.length > 0 && (\n <MessagesLabels direction=\"row\" spacing={0.5} useFlexGap ownSx={{flexWrap: 'wrap', mt: 0.5}}>\n {message.labels.map((rawLabel) => {\n const label = tagOf(rawLabel);\n return <Chip key={label.label} size=\"small\" variant=\"outlined\" color={label.color} label={label.label} />;\n })}\n </MessagesLabels>\n )}\n </MessagesText>\n )}\n </MessagesItemButton>\n </MessagesItem>\n );\n })}\n </List>\n );\n}\n"],"names":["CheckRoundedIcon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MessageList.js","sources":["../../src/inbox/MessageList.jsx"],"sourcesContent":["// La lista de mensajes de una bandeja tipo correo: quién lo manda (y cuántos mensajes trae la conversación), el asunto con sus\n// etiquetas, el principio del texto, la fecha corta, la estrella y el clip si trae archivos. Los no leídos van en negritas con\n// su punto.\n//\n// Lo de un producto, todo hacia afuera (la lista no guarda nada ni llama a ningún servidor):\n// - elegir varios: con onSelectionChange el monograma de cada mensaje se vuelve su casilla (como Gmail en el teléfono) y la\n// pantalla pone las acciones de lo elegido (SelectionActions: archivar, borrar, marcar como leído…);\n// - «⋯» de cada mensaje con las acciones que dé la pantalla (messageActions);\n// - renderMessage para pintar lo de adentro de cada renglón a su manera, y texts para cualquier texto.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaMessageList con defaultProps y\n// styleOverrides de sus partes: empty, selectedAvatar, item, actions, starButton, itemButton, avatarSlot, avatarButton,\n// avatar, body, text, topRow, unreadDot, sender, threadCount, date, subject, labels.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Avatar from '@mui/material/Avatar';\nimport Box from '@mui/material/Box';\nimport ButtonBase from '@mui/material/ButtonBase';\nimport Chip from '@mui/material/Chip';\nimport IconButton from '@mui/material/IconButton';\nimport List from '@mui/material/List';\nimport ListItem from '@mui/material/ListItem';\nimport ListItemAvatar from '@mui/material/ListItemAvatar';\nimport ListItemButton from '@mui/material/ListItemButton';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport AttachFileRoundedIcon from '@mui/icons-material/AttachFileRounded';\nimport CheckRoundedIcon from '@mui/icons-material/CheckRounded';\nimport StarBorderRoundedIcon from '@mui/icons-material/StarBorderRounded';\nimport StarRoundedIcon from '@mui/icons-material/StarRounded';\n\nimport {initialsOf} from '@/appShell/menuItemText.js';\nimport {inboxDateOf} from '@/inbox/inboxDates.js';\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport {tagOf} from '@/ui/labels/tagOf.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport ActionsMenu from '@/ui/actions/ActionsMenu.jsx';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaMessageList)\nconst THEME_NAME = 'CalcitaMessageList';\nconst MessagesEmpty = piecePart(THEME_NAME, 'Empty', Typography);\nconst MessagesSelectedAvatar = piecePart(THEME_NAME, 'SelectedAvatar', Avatar);\nconst MessagesItem = piecePart(THEME_NAME, 'Item', ListItem);\nconst MessagesActions = piecePart(THEME_NAME, 'Actions', Stack);\nconst MessagesStarButton = piecePart(THEME_NAME, 'StarButton', IconButton);\nconst MessagesItemButton = piecePart(THEME_NAME, 'ItemButton', ListItemButton);\nconst MessagesAvatarSlot = piecePart(THEME_NAME, 'AvatarSlot', ListItemAvatar);\nconst MessagesAvatarButton = piecePart(THEME_NAME, 'AvatarButton', ButtonBase);\nconst MessagesAvatar = piecePart(THEME_NAME, 'Avatar', Avatar);\nconst MessagesBody = piecePart(THEME_NAME, 'Body', Box);\nconst MessagesText = piecePart(THEME_NAME, 'Text', Box);\nconst MessagesTopRow = piecePart(THEME_NAME, 'TopRow', Stack);\nconst MessagesUnreadDot = piecePart(THEME_NAME, 'UnreadDot', Box);\nconst MessagesSender = piecePart(THEME_NAME, 'Sender', Typography);\nconst MessagesThreadCount = piecePart(THEME_NAME, 'ThreadCount', Typography);\nconst MessagesDate = piecePart(THEME_NAME, 'Date', Typography);\nconst MessagesSubject = piecePart(THEME_NAME, 'Subject', Typography);\nconst MessagesLabels = piecePart(THEME_NAME, 'Labels', Stack);\n\nconst UNREAD_DOT_PIXELS = 8;\nconst AVATAR_PIXELS = 40;\n\n/**\n * @param {object} props\n * @param {Array<{id: string, from: {name: string, email: string}, subject: string, preview: string, receivedAt: string, isUnread?: boolean, isStarred?: boolean, hasAttachments?: boolean, threadCount?: number, labels?: Array<string|{label: string, color?: string}>} & Record<string, any>>} props.messages\n * cada mensaje puede traer sus campos propios (llegan a renderMessage y a messageActions tal cual). threadCount: cuántos\n * mensajes trae la conversación (con 2 o más se pinta «(3)»); labels: texto o {label, color} del tema\n * @param {string|null} [props.selectedId] el mensaje abierto\n * @param {(messageId: string) => void} props.onSelect abrir un mensaje\n * @param {(messageId: string) => void} [props.onToggleStar]\n * @param {string[]} [props.selectedIds] los elegidos para una acción en grupo\n * @param {(messageIds: string[]) => void} [props.onSelectionChange] con él, cada mensaje se puede elegir picando su monograma\n * @param {(message: any) => Array<{key: string, label: string, icon?: import('react').ReactNode, color?: string, disabled?: boolean, onClick: () => void}>} [props.messageActions]\n * las acciones del «⋯» de cada mensaje (archivar, posponer, mover…); sin ellas no hay «⋯»\n * @param {(message: any) => import('react').ReactNode} [props.renderMessage] lo de adentro de cada renglón, a su manera\n * @param {string} [props.emptyText] ya traducido; por omisión el del paquete\n * @param {object} [props.texts] los textos que cambian, con la forma de `inbox` en los textos del paquete\n */\nfunction MessageListContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaMessageList.defaultProps) y encima lo que llega aquí\n const {\n messages, selectedId = null, onSelect, onToggleStar, selectedIds = [], onSelectionChange, messageActions, renderMessage, emptyText, texts,\n ...unknownProps\n} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('inbox', texts);\n const formatters = useFormatters();\n\n if (messages.length === 0) {\n return <MessagesEmpty variant=\"body2\" color=\"text.secondary\" ownSx={{p: 3, textAlign: 'center'}}>{emptyText ?? t('empty')}</MessagesEmpty>;\n }\n\n const toggleSelected = (messageId, isChecked) => {\n onSelectionChange(isChecked ? [...selectedIds, messageId] : selectedIds.filter((id) => id !== messageId));\n };\n\n return (\n <List disablePadding aria-label={t('listLabel')}>\n {messages.map((message) => {\n const weight = message.isUnread ? 700 : 400;\n const isChecked = selectedIds.includes(message.id);\n const avatar = <MessagesSelectedAvatar ownSx={{width: AVATAR_PIXELS, height: AVATAR_PIXELS}}>{initialsOf(message.from.name)}</MessagesSelectedAvatar>;\n return (\n <MessagesItem key={message.id} disablePadding secondaryAction={(onToggleStar || messageActions) && (\n <MessagesActions direction=\"row\" ownSx={{alignItems: 'center'}}>\n {onToggleStar && (\n <MessagesStarButton size=\"small\" onClick={() => onToggleStar(message.id)} aria-pressed={Boolean(message.isStarred)}\n aria-label={message.isStarred ? t('unstar') : t('star')} ownSx={{color: message.isStarred ? 'warning.main' : 'text.secondary'}}>\n {message.isStarred ? <StarRoundedIcon fontSize=\"small\" /> : <StarBorderRoundedIcon fontSize=\"small\" />}\n </MessagesStarButton>\n )}\n {messageActions && <ActionsMenu label={t('messageActions', {subject: message.subject})} actions={messageActions(message)} />}\n </MessagesActions>\n )} ownSx={{'& .MuiListItemSecondaryAction-root': {right: 4}}}>\n <MessagesItemButton selected={message.id === selectedId || isChecked} onClick={() => onSelect(message.id)} alignItems=\"flex-start\"\n ownSx={{borderRadius: 2, pr: onToggleStar && messageActions ? 10 : 6}}>\n <MessagesAvatarSlot ownSx={{mt: 0.5}}>\n {/* elegir: el monograma es la casilla (el clic no abre el mensaje). Un botón con papel de casilla y\n no el Checkbox de MUI: el tema le pinta a la casilla marcada un cuadro blanco detrás de su dibujo\n y la palomita salía como un cuadro */}\n {onSelectionChange ? (\n <MessagesAvatarButton role=\"checkbox\" aria-checked={isChecked} aria-label={t('select', {subject: message.subject})}\n ownSx={{borderRadius: '50%'}}\n onClick={(event) => {\n event.stopPropagation();\n toggleSelected(message.id, !isChecked);\n }}>\n {isChecked ? (\n <MessagesAvatar ownSx={{width: AVATAR_PIXELS, height: AVATAR_PIXELS, bgcolor: 'primary.main', color: 'primary.contrastText'}}>\n <CheckRoundedIcon />\n </MessagesAvatar>\n ) : avatar}\n </MessagesAvatarButton>\n ) : avatar}\n </MessagesAvatarSlot>\n {renderMessage ? <MessagesBody ownSx={{minWidth: 0, flex: 1}}>{renderMessage(message)}</MessagesBody> : (\n <MessagesText ownSx={{minWidth: 0, flex: 1}}>\n <MessagesTopRow direction=\"row\" spacing={1} ownSx={{alignItems: 'center'}}>\n {message.isUnread && (\n <MessagesUnreadDot component=\"span\" aria-label={t('unread')} ownSx={{width: UNREAD_DOT_PIXELS, height: UNREAD_DOT_PIXELS, borderRadius: '50%', bgcolor: 'primary.main', flexShrink: 0}} />\n )}\n <MessagesSender variant=\"body2\" noWrap ownSx={{fontWeight: weight, flex: 1}}>\n {message.from.name}\n {message.threadCount > 1 && (\n <MessagesThreadCount component=\"span\" variant=\"caption\" color=\"text.secondary\" ownSx={{ml: 0.5}} aria-label={t('threadCount', {count: message.threadCount})}>\n ({message.threadCount})\n </MessagesThreadCount>\n )}\n </MessagesSender>\n {message.hasAttachments && <AttachFileRoundedIcon fontSize=\"inherit\" color=\"action\" aria-label={t('attachments')} />}\n <MessagesDate variant=\"caption\" color=\"text.secondary\" ownSx={{flexShrink: 0, fontVariantNumeric: 'tabular-nums'}}>\n {inboxDateOf(message.receivedAt, new Date(), formatters)}\n </MessagesDate>\n </MessagesTopRow>\n <MessagesSubject variant=\"body2\" noWrap ownSx={{fontWeight: weight}}>{message.subject}</MessagesSubject>\n <Typography variant=\"body2\" color=\"text.secondary\" noWrap>{message.preview}</Typography>\n {message.labels?.length > 0 && (\n <MessagesLabels direction=\"row\" spacing={0.5} useFlexGap ownSx={{flexWrap: 'wrap', mt: 0.5}}>\n {message.labels.map((rawLabel) => {\n const label = tagOf(rawLabel);\n return <Chip key={label.label} size=\"small\" variant=\"outlined\" color={label.color} label={label.label} />;\n })}\n </MessagesLabels>\n )}\n </MessagesText>\n )}\n </MessagesItemButton>\n </MessagesItem>\n );\n })}\n </List>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst MessageList = withPieceSlots(MessageListContent, THEME_NAME);\nexport default MessageList;\n"],"names":["CheckRoundedIcon"],"mappings":"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"}
|
|
@@ -14,7 +14,7 @@ import { useFormatters } from "../toolkit/useFormatters.js";
|
|
|
14
14
|
import { inboxDateOf } from "./inboxDates.js";
|
|
15
15
|
import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
|
|
16
16
|
import { tagOf } from "../ui/labels/tagOf.js";
|
|
17
|
-
import { piecePart, usePieceProps } from "../theme/themePieces.js";
|
|
17
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
|
|
18
18
|
import { warnUnknownProps } from "../toolkit/unknownProps.js";
|
|
19
19
|
const THEME_NAME = "CalcitaMessageView";
|
|
20
20
|
const MessageHeaderPart = piecePart(THEME_NAME, "Header", Stack);
|
|
@@ -67,7 +67,7 @@ function MessageBody({ entry, t, onAttachmentClick, renderBody }) {
|
|
|
67
67
|
renderBody ? renderBody(entry) : /* @__PURE__ */ jsx(MessageBodyPart, { variant: "body1", component: "div", ownSx: { whiteSpace: "pre-wrap", overflowWrap: "anywhere" }, children: entry.body })
|
|
68
68
|
] });
|
|
69
69
|
}
|
|
70
|
-
function
|
|
70
|
+
function MessageViewContent(props) {
|
|
71
71
|
const { message, actions, footer, onAttachmentClick, onExpand, renderBody, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
72
72
|
warnUnknownProps(THEME_NAME, unknownProps);
|
|
73
73
|
const { t } = useToolkitTranslation("inbox", texts);
|
|
@@ -116,6 +116,7 @@ function MessageView(props) {
|
|
|
116
116
|
footer
|
|
117
117
|
] });
|
|
118
118
|
}
|
|
119
|
+
const MessageView = withPieceSlots(MessageViewContent, THEME_NAME);
|
|
119
120
|
export {
|
|
120
121
|
MessageView as default
|
|
121
122
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageView.js","sources":["../../src/inbox/MessageView.jsx"],"sourcesContent":["// La lectura de un mensaje o de una conversación completa: el asunto con sus etiquetas y, debajo, cada mensaje de la\n// conversación (los anteriores encogidos en un renglón con quién y cuándo, como Gmail; al picarlos se abren). De cada uno:\n// quién lo manda (con su correo), para quién y con copia a quién, la fecha completa, sus archivos y el texto. Arriba, las\n// acciones que quiera el proyecto (responder, archivar, posponer, borrar); abajo, lo que quiera poner (una respuesta rápida).\n//\n// El texto se pinta como TEXTO, con sus saltos de renglón: nunca como HTML (un correo con HTML adentro sería un XSS). Si un\n// proyecto necesita HTML, lo pinta con renderBody y es SU responsabilidad limpiarlo antes (DOMPurify o su backend).\n//\n// Todo hacia afuera: onAttachmentClick al picar un archivo (descargarlo, verlo), onExpand al abrir un mensaje anterior (para\n// marcarlo como leído), renderBody, footer y texts.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaMessageView con defaultProps y\n// styleOverrides de sus partes: header, headerText, recipients, body, empty, labels, attachments, divider, collapsed,\n// collapsedAvatar, collapsedText, collapsedSender, collapsedDate.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Avatar from '@mui/material/Avatar';\nimport Box from '@mui/material/Box';\nimport ButtonBase from '@mui/material/ButtonBase';\nimport Chip from '@mui/material/Chip';\nimport Divider from '@mui/material/Divider';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport AttachFileRoundedIcon from '@mui/icons-material/AttachFileRounded';\n\nimport {initialsOf} from '@/appShell/menuItemText.js';\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport {inboxDateOf} from '@/inbox/inboxDates.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {tagOf} from '@/ui/labels/tagOf.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaMessageView)\nconst THEME_NAME = 'CalcitaMessageView';\nconst MessageHeaderPart = piecePart(THEME_NAME, 'Header', Stack);\nconst MessageHeaderText = piecePart(THEME_NAME, 'HeaderText', Box);\nconst MessageRecipients = piecePart(THEME_NAME, 'Recipients', Stack);\nconst MessageBodyPart = piecePart(THEME_NAME, 'Body', Typography);\nconst MessageEmpty = piecePart(THEME_NAME, 'Empty', Typography);\nconst MessageLabels = piecePart(THEME_NAME, 'Labels', Stack);\nconst MessageAttachments = piecePart(THEME_NAME, 'Attachments', Stack);\nconst MessageDivider = piecePart(THEME_NAME, 'Divider', Divider);\nconst MessageCollapsed = piecePart(THEME_NAME, 'Collapsed', ButtonBase);\nconst MessageCollapsedAvatar = piecePart(THEME_NAME, 'CollapsedAvatar', Avatar);\nconst MessageCollapsedText = piecePart(THEME_NAME, 'CollapsedText', Box);\nconst MessageCollapsedSender = piecePart(THEME_NAME, 'CollapsedSender', Typography);\nconst MessageCollapsedDate = piecePart(THEME_NAME, 'CollapsedDate', Typography);\n\nconst PREVIEW_LENGTH = 90;\n\n/** Quién manda, para quién, con copia a quién y cuándo. */\nfunction MessageHeader({entry, t}) {\n const {formatDateTime} = useFormatters();\n return (\n <MessageHeaderPart direction=\"row\" spacing={1.5} ownSx={{alignItems: 'center'}}>\n <Avatar>{initialsOf(entry.from.name)}</Avatar>\n <MessageHeaderText ownSx={{minWidth: 0, flex: 1}}>\n <Typography variant=\"subtitle2\" component=\"p\" noWrap>\n {entry.from.name} <Typography component=\"span\" variant=\"body2\" color=\"text.secondary\"><{entry.from.email}></Typography>\n </Typography>\n {entry.to?.length > 0 && <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">{t('to', {to: entry.to.join(', ')})}</Typography>}\n {entry.cc?.length > 0 && <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">{t('cc', {cc: entry.cc.join(', ')})}</Typography>}\n {/* la fecha debajo y no a la derecha: en el teléfono apretaba el «Para» a dos renglones */}\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">{formatDateTime(entry.receivedAt)}</Typography>\n </MessageHeaderText>\n </MessageHeaderPart>\n );\n}\n\n/** Un mensaje abierto: su encabezado, sus archivos y su texto. */\nfunction MessageBody({entry, t, onAttachmentClick, renderBody}) {\n return (\n <Stack spacing={2}>\n <MessageHeader entry={entry} t={t} />\n {entry.attachments?.length > 0 && (\n <MessageRecipients direction=\"row\" spacing={1} useFlexGap ownSx={{flexWrap: 'wrap'}} aria-label={t('attachments')} role=\"group\">\n {entry.attachments.map((attachment) => (\n <Chip key={attachment.name} icon={<AttachFileRoundedIcon />} variant=\"outlined\"\n label={attachment.size ? `${attachment.name} · ${attachment.size}` : attachment.name}\n {...(onAttachmentClick && {onClick: () => onAttachmentClick(attachment, entry), 'aria-label': t('openAttachment', {name: attachment.name})})} />\n ))}\n </MessageRecipients>\n )}\n {renderBody ? renderBody(entry) : (\n <MessageBodyPart variant=\"body1\" component=\"div\" ownSx={{whiteSpace: 'pre-wrap', overflowWrap: 'anywhere'}}>{entry.body}</MessageBodyPart>\n )}\n </Stack>\n );\n}\n\n/**\n * @param {object} props\n * @param {{id?: string, subject: string, from: {name: string, email: string}, to?: string[], cc?: string[], receivedAt: string, body: string, attachments?: Array<{name: string, size?: string} & Record<string, any>>, labels?: Array<string|{label: string, color?: string}>, thread?: Array<{id: string, from: {name: string, email: string}, to?: string[], cc?: string[], receivedAt: string, body: string, attachments?: Array<{name: string, size?: string}>}>}|null} props.message\n * el mensaje más nuevo de la conversación; thread: los anteriores, del más viejo al más nuevo (encogidos). null: todavía\n * no se elige ninguno\n * @param {import('react').ReactNode} [props.actions] los botones de arriba\n * @param {import('react').ReactNode} [props.footer] lo de abajo (una respuesta rápida, firmas…)\n * @param {(attachment: any, message: any) => void} [props.onAttachmentClick] al picar un archivo; sin él los archivos solo se ven\n * @param {(threadMessageId: string) => void} [props.onExpand] al abrir un mensaje anterior de la conversación\n * @param {(message: any) => import('react').ReactNode} [props.renderBody] el texto a su manera (HTML ya limpio por el proyecto)\n * @param {object} [props.texts] los textos que cambian, con la forma de `inbox` en los textos del paquete\n */\nexport default function MessageView(props) {\n // lo que el proyecto puso en su tema (components.CalcitaMessageView.defaultProps) y encima lo que llega aquí\n const {message, actions, footer, onAttachmentClick, onExpand, renderBody, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('inbox', texts);\n const formatters = useFormatters();\n // los mensajes anteriores que la persona abrió (empiezan encogidos), de qué conversación: al cambiar de mensaje se olvidan\n const [expanded, setExpanded] = useState({messageId: null, ids: []});\n\n if (!message) {\n return <MessageEmpty variant=\"body2\" color=\"text.secondary\" ownSx={{p: 4, textAlign: 'center'}}>{t('noMessageSelected')}</MessageEmpty>;\n }\n\n const expandedIds = expanded.messageId === message.id ? expanded.ids : [];\n const expand = (threadMessageId) => {\n setExpanded({messageId: message.id, ids: [...expandedIds, threadMessageId]});\n onExpand?.(threadMessageId);\n };\n\n return (\n <Stack spacing={2} component=\"article\" aria-label={message.subject}>\n {actions && <MessageLabels direction=\"row\" spacing={0.5} useFlexGap ownSx={{flexWrap: 'wrap', alignItems: 'center'}}>{actions}</MessageLabels>}\n <Box>\n <Typography variant=\"h5\" component=\"h2\">{message.subject}</Typography>\n {message.labels?.length > 0 && (\n <MessageAttachments direction=\"row\" spacing={0.5} useFlexGap ownSx={{flexWrap: 'wrap', mt: 1}}>\n {message.labels.map((rawLabel) => {\n const label = tagOf(rawLabel);\n return <Chip key={label.label} size=\"small\" variant=\"outlined\" color={label.color} label={label.label} />;\n })}\n </MessageAttachments>\n )}\n </Box>\n {message.thread?.length > 0 && (\n <Typography variant=\"caption\" color=\"text.secondary\">{t('threadCount', {count: message.thread.length + 1})}</Typography>\n )}\n {/* los anteriores: encogidos en un renglón; abiertos, completos y con su línea abajo */}\n {message.thread?.map((entry) => (expandedIds.includes(entry.id) ? (\n <Box key={entry.id}>\n <MessageBody entry={entry} t={t} onAttachmentClick={onAttachmentClick} renderBody={renderBody} />\n <MessageDivider ownSx={{mt: 2}} />\n </Box>\n ) : (\n <MessageCollapsed key={entry.id} onClick={() => expand(entry.id)} aria-label={t('expandMessage', {name: entry.from.name, date: inboxDateOf(entry.receivedAt, new Date(), formatters)})}\n ownSx={{justifyContent: 'flex-start', textAlign: 'left', borderRadius: 2, p: 1, mx: -1, gap: 1.5, '&:hover': {bgcolor: 'action.hover'}}}>\n <MessageCollapsedAvatar ownSx={{width: 32, height: 32, fontSize: 13}}>{initialsOf(entry.from.name)}</MessageCollapsedAvatar>\n <MessageCollapsedText ownSx={{minWidth: 0, flex: 1}}>\n <MessageCollapsedSender variant=\"body2\" ownSx={{fontWeight: 600}} noWrap>{entry.from.name}</MessageCollapsedSender>\n <Typography variant=\"body2\" color=\"text.secondary\" noWrap>{entry.body.replace(/\\s+/g, ' ').slice(0, PREVIEW_LENGTH)}</Typography>\n </MessageCollapsedText>\n <MessageCollapsedDate variant=\"caption\" color=\"text.secondary\" ownSx={{flexShrink: 0}}>{inboxDateOf(entry.receivedAt, new Date(), formatters)}</MessageCollapsedDate>\n </MessageCollapsed>\n )))}\n {message.thread?.length > 0 && <Divider />}\n <MessageBody entry={message} t={t} onAttachmentClick={onAttachmentClick} renderBody={renderBody} />\n {footer}\n </Stack>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MessageView.js","sources":["../../src/inbox/MessageView.jsx"],"sourcesContent":["// La lectura de un mensaje o de una conversación completa: el asunto con sus etiquetas y, debajo, cada mensaje de la\n// conversación (los anteriores encogidos en un renglón con quién y cuándo, como Gmail; al picarlos se abren). De cada uno:\n// quién lo manda (con su correo), para quién y con copia a quién, la fecha completa, sus archivos y el texto. Arriba, las\n// acciones que quiera el proyecto (responder, archivar, posponer, borrar); abajo, lo que quiera poner (una respuesta rápida).\n//\n// El texto se pinta como TEXTO, con sus saltos de renglón: nunca como HTML (un correo con HTML adentro sería un XSS). Si un\n// proyecto necesita HTML, lo pinta con renderBody y es SU responsabilidad limpiarlo antes (DOMPurify o su backend).\n//\n// Todo hacia afuera: onAttachmentClick al picar un archivo (descargarlo, verlo), onExpand al abrir un mensaje anterior (para\n// marcarlo como leído), renderBody, footer y texts.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaMessageView con defaultProps y\n// styleOverrides de sus partes: header, headerText, recipients, body, empty, labels, attachments, divider, collapsed,\n// collapsedAvatar, collapsedText, collapsedSender, collapsedDate.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Avatar from '@mui/material/Avatar';\nimport Box from '@mui/material/Box';\nimport ButtonBase from '@mui/material/ButtonBase';\nimport Chip from '@mui/material/Chip';\nimport Divider from '@mui/material/Divider';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport AttachFileRoundedIcon from '@mui/icons-material/AttachFileRounded';\n\nimport {initialsOf} from '@/appShell/menuItemText.js';\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport {inboxDateOf} from '@/inbox/inboxDates.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {tagOf} from '@/ui/labels/tagOf.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaMessageView)\nconst THEME_NAME = 'CalcitaMessageView';\nconst MessageHeaderPart = piecePart(THEME_NAME, 'Header', Stack);\nconst MessageHeaderText = piecePart(THEME_NAME, 'HeaderText', Box);\nconst MessageRecipients = piecePart(THEME_NAME, 'Recipients', Stack);\nconst MessageBodyPart = piecePart(THEME_NAME, 'Body', Typography);\nconst MessageEmpty = piecePart(THEME_NAME, 'Empty', Typography);\nconst MessageLabels = piecePart(THEME_NAME, 'Labels', Stack);\nconst MessageAttachments = piecePart(THEME_NAME, 'Attachments', Stack);\nconst MessageDivider = piecePart(THEME_NAME, 'Divider', Divider);\nconst MessageCollapsed = piecePart(THEME_NAME, 'Collapsed', ButtonBase);\nconst MessageCollapsedAvatar = piecePart(THEME_NAME, 'CollapsedAvatar', Avatar);\nconst MessageCollapsedText = piecePart(THEME_NAME, 'CollapsedText', Box);\nconst MessageCollapsedSender = piecePart(THEME_NAME, 'CollapsedSender', Typography);\nconst MessageCollapsedDate = piecePart(THEME_NAME, 'CollapsedDate', Typography);\n\nconst PREVIEW_LENGTH = 90;\n\n/** Quién manda, para quién, con copia a quién y cuándo. */\nfunction MessageHeader({entry, t}) {\n const {formatDateTime} = useFormatters();\n return (\n <MessageHeaderPart direction=\"row\" spacing={1.5} ownSx={{alignItems: 'center'}}>\n <Avatar>{initialsOf(entry.from.name)}</Avatar>\n <MessageHeaderText ownSx={{minWidth: 0, flex: 1}}>\n <Typography variant=\"subtitle2\" component=\"p\" noWrap>\n {entry.from.name} <Typography component=\"span\" variant=\"body2\" color=\"text.secondary\"><{entry.from.email}></Typography>\n </Typography>\n {entry.to?.length > 0 && <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">{t('to', {to: entry.to.join(', ')})}</Typography>}\n {entry.cc?.length > 0 && <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">{t('cc', {cc: entry.cc.join(', ')})}</Typography>}\n {/* la fecha debajo y no a la derecha: en el teléfono apretaba el «Para» a dos renglones */}\n <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">{formatDateTime(entry.receivedAt)}</Typography>\n </MessageHeaderText>\n </MessageHeaderPart>\n );\n}\n\n/** Un mensaje abierto: su encabezado, sus archivos y su texto. */\nfunction MessageBody({entry, t, onAttachmentClick, renderBody}) {\n return (\n <Stack spacing={2}>\n <MessageHeader entry={entry} t={t} />\n {entry.attachments?.length > 0 && (\n <MessageRecipients direction=\"row\" spacing={1} useFlexGap ownSx={{flexWrap: 'wrap'}} aria-label={t('attachments')} role=\"group\">\n {entry.attachments.map((attachment) => (\n <Chip key={attachment.name} icon={<AttachFileRoundedIcon />} variant=\"outlined\"\n label={attachment.size ? `${attachment.name} · ${attachment.size}` : attachment.name}\n {...(onAttachmentClick && {onClick: () => onAttachmentClick(attachment, entry), 'aria-label': t('openAttachment', {name: attachment.name})})} />\n ))}\n </MessageRecipients>\n )}\n {renderBody ? renderBody(entry) : (\n <MessageBodyPart variant=\"body1\" component=\"div\" ownSx={{whiteSpace: 'pre-wrap', overflowWrap: 'anywhere'}}>{entry.body}</MessageBodyPart>\n )}\n </Stack>\n );\n}\n\n/**\n * @param {object} props\n * @param {{id?: string, subject: string, from: {name: string, email: string}, to?: string[], cc?: string[], receivedAt: string, body: string, attachments?: Array<{name: string, size?: string} & Record<string, any>>, labels?: Array<string|{label: string, color?: string}>, thread?: Array<{id: string, from: {name: string, email: string}, to?: string[], cc?: string[], receivedAt: string, body: string, attachments?: Array<{name: string, size?: string}>}>}|null} props.message\n * el mensaje más nuevo de la conversación; thread: los anteriores, del más viejo al más nuevo (encogidos). null: todavía\n * no se elige ninguno\n * @param {import('react').ReactNode} [props.actions] los botones de arriba\n * @param {import('react').ReactNode} [props.footer] lo de abajo (una respuesta rápida, firmas…)\n * @param {(attachment: any, message: any) => void} [props.onAttachmentClick] al picar un archivo; sin él los archivos solo se ven\n * @param {(threadMessageId: string) => void} [props.onExpand] al abrir un mensaje anterior de la conversación\n * @param {(message: any) => import('react').ReactNode} [props.renderBody] el texto a su manera (HTML ya limpio por el proyecto)\n * @param {object} [props.texts] los textos que cambian, con la forma de `inbox` en los textos del paquete\n */\nfunction MessageViewContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaMessageView.defaultProps) y encima lo que llega aquí\n const {message, actions, footer, onAttachmentClick, onExpand, renderBody, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('inbox', texts);\n const formatters = useFormatters();\n // los mensajes anteriores que la persona abrió (empiezan encogidos), de qué conversación: al cambiar de mensaje se olvidan\n const [expanded, setExpanded] = useState({messageId: null, ids: []});\n\n if (!message) {\n return <MessageEmpty variant=\"body2\" color=\"text.secondary\" ownSx={{p: 4, textAlign: 'center'}}>{t('noMessageSelected')}</MessageEmpty>;\n }\n\n const expandedIds = expanded.messageId === message.id ? expanded.ids : [];\n const expand = (threadMessageId) => {\n setExpanded({messageId: message.id, ids: [...expandedIds, threadMessageId]});\n onExpand?.(threadMessageId);\n };\n\n return (\n <Stack spacing={2} component=\"article\" aria-label={message.subject}>\n {actions && <MessageLabels direction=\"row\" spacing={0.5} useFlexGap ownSx={{flexWrap: 'wrap', alignItems: 'center'}}>{actions}</MessageLabels>}\n <Box>\n <Typography variant=\"h5\" component=\"h2\">{message.subject}</Typography>\n {message.labels?.length > 0 && (\n <MessageAttachments direction=\"row\" spacing={0.5} useFlexGap ownSx={{flexWrap: 'wrap', mt: 1}}>\n {message.labels.map((rawLabel) => {\n const label = tagOf(rawLabel);\n return <Chip key={label.label} size=\"small\" variant=\"outlined\" color={label.color} label={label.label} />;\n })}\n </MessageAttachments>\n )}\n </Box>\n {message.thread?.length > 0 && (\n <Typography variant=\"caption\" color=\"text.secondary\">{t('threadCount', {count: message.thread.length + 1})}</Typography>\n )}\n {/* los anteriores: encogidos en un renglón; abiertos, completos y con su línea abajo */}\n {message.thread?.map((entry) => (expandedIds.includes(entry.id) ? (\n <Box key={entry.id}>\n <MessageBody entry={entry} t={t} onAttachmentClick={onAttachmentClick} renderBody={renderBody} />\n <MessageDivider ownSx={{mt: 2}} />\n </Box>\n ) : (\n <MessageCollapsed key={entry.id} onClick={() => expand(entry.id)} aria-label={t('expandMessage', {name: entry.from.name, date: inboxDateOf(entry.receivedAt, new Date(), formatters)})}\n ownSx={{justifyContent: 'flex-start', textAlign: 'left', borderRadius: 2, p: 1, mx: -1, gap: 1.5, '&:hover': {bgcolor: 'action.hover'}}}>\n <MessageCollapsedAvatar ownSx={{width: 32, height: 32, fontSize: 13}}>{initialsOf(entry.from.name)}</MessageCollapsedAvatar>\n <MessageCollapsedText ownSx={{minWidth: 0, flex: 1}}>\n <MessageCollapsedSender variant=\"body2\" ownSx={{fontWeight: 600}} noWrap>{entry.from.name}</MessageCollapsedSender>\n <Typography variant=\"body2\" color=\"text.secondary\" noWrap>{entry.body.replace(/\\s+/g, ' ').slice(0, PREVIEW_LENGTH)}</Typography>\n </MessageCollapsedText>\n <MessageCollapsedDate variant=\"caption\" color=\"text.secondary\" ownSx={{flexShrink: 0}}>{inboxDateOf(entry.receivedAt, new Date(), formatters)}</MessageCollapsedDate>\n </MessageCollapsed>\n )))}\n {message.thread?.length > 0 && <Divider />}\n <MessageBody entry={message} t={t} onAttachmentClick={onAttachmentClick} renderBody={renderBody} />\n {footer}\n </Stack>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst MessageView = withPieceSlots(MessageViewContent, THEME_NAME);\nexport default MessageView;\n"],"names":[],"mappings":"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"}
|