@stackcraftmx/calcita 0.47.0 → 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 +173 -12
- package/cli/calcita.js +15 -0
- package/cli/checkTexts.js +209 -0
- package/cli/packageVersions.js +6 -1
- package/cli/projectFiles.js +4 -2
- package/cli/templates/project/README.md.tpl +21 -1
- package/cli/templates/project/eslint.config.js.tpl +27 -0
- package/cli/templates/project/src/app/appTexts.js.tpl +2 -1
- package/cli/templates/project/src/core/publicPaths.js.tpl +10 -2
- package/cli/templates/project/vite.config.js.tpl +8 -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 +3 -2
- package/dist/DataTable/GoToPage.js.map +1 -1
- package/dist/DataTable/ServerTable.js +95 -28
- package/dist/DataTable/ServerTable.js.map +1 -1
- package/dist/DataTable/ServerTableFilterDrawer.js +8 -3
- package/dist/DataTable/ServerTableFilterDrawer.js.map +1 -1
- 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/fixedColumns.js +24 -0
- package/dist/DataTable/fixedColumns.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/datePickers/DateInput.js +28 -22
- package/dist/datePickers/DateInput.js.map +1 -1
- package/dist/datePickers/DateTimeInput.js +33 -27
- package/dist/datePickers/DateTimeInput.js.map +1 -1
- package/dist/datePickers/MonthInput.js +27 -21
- package/dist/datePickers/MonthInput.js.map +1 -1
- package/dist/datePickers/TimeInput.js +26 -20
- package/dist/datePickers/TimeInput.js.map +1 -1
- package/dist/datePickers/usePickerField.js +5 -4
- package/dist/datePickers/usePickerField.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/FormProblemAlert.js +3 -2
- package/dist/forms/FormProblemAlert.js.map +1 -1
- package/dist/forms/SubmitButton.js +7 -2
- package/dist/forms/SubmitButton.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/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/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 +3 -0
- package/dist/forms.js.map +1 -1
- package/dist/hookForm/FormProblemAlert.js +3 -2
- package/dist/hookForm/FormProblemAlert.js.map +1 -1
- package/dist/hookForm/SubmitButton.js +7 -2
- package/dist/hookForm/SubmitButton.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 +186 -163
- package/dist/index.js.map +1 -1
- package/dist/inputs/CatalogInput.js +32 -25
- package/dist/inputs/CatalogInput.js.map +1 -1
- package/dist/inputs/CheckboxGroupInput.js +8 -5
- package/dist/inputs/CheckboxGroupInput.js.map +1 -1
- 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 +1 -0
- package/dist/inputs/MaskedInput.js.map +1 -1
- package/dist/inputs/NumberInput.js +29 -24
- package/dist/inputs/NumberInput.js.map +1 -1
- package/dist/inputs/RepeatingFields.js +8 -5
- package/dist/inputs/RepeatingFields.js.map +1 -1
- package/dist/inputs/SelectInput.js +8 -5
- 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 +8 -5
- package/dist/inputs/TransferListInput.js.map +1 -1
- package/dist/inputs/WizardLayout.js +3 -2
- package/dist/inputs/WizardLayout.js.map +1 -1
- package/dist/kanban/KanbanBoard.js +3 -2
- package/dist/kanban/KanbanBoard.js.map +1 -1
- package/dist/legal/CookieNotice.js +3 -2
- package/dist/legal/CookieNotice.js.map +1 -1
- package/dist/legal/TermsAcceptanceDialog.js +3 -2
- package/dist/legal/TermsAcceptanceDialog.js.map +1 -1
- package/dist/locales/en.js +24 -0
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +24 -0
- 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 +3 -2
- package/dist/mexico/CfdiSummary.js.map +1 -1
- package/dist/mexico/EfirmaFields.js +3 -2
- package/dist/mexico/EfirmaFields.js.map +1 -1
- package/dist/mexico/mexicoIdentifiers.js +5 -0
- package/dist/mexico/mexicoIdentifiers.js.map +1 -1
- package/dist/mexico/mexicoRules.js +9 -4
- package/dist/mexico/mexicoRules.js.map +1 -1
- package/dist/mexico.js +4 -2
- 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 +3 -0
- package/dist/react-hook-form.js.map +1 -1
- package/dist/richText/RichTextEditor.js +7 -4
- package/dist/richText/RichTextEditor.js.map +1 -1
- package/dist/richText/RichTextView.js +3 -2
- package/dist/richText/RichTextView.js.map +1 -1
- 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 +21 -2
- package/dist/table.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 +6 -13
- 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/fixedColumns.d.ts +29 -0
- package/dist/types/DataTable/index.d.ts +6 -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/datePickers/DateInput.d.ts +7 -22
- package/dist/types/datePickers/DateTimeInput.d.ts +7 -27
- package/dist/types/datePickers/MonthInput.d.ts +7 -21
- package/dist/types/datePickers/TimeInput.d.ts +7 -21
- package/dist/types/datePickers/usePickerField.d.ts +5 -1
- 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/FormProblemAlert.d.ts +6 -5
- 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 +1 -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/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/FormProblemAlert.d.ts +6 -5
- 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 +8 -1
- package/dist/types/inputs/CatalogInput.d.ts +7 -24
- package/dist/types/inputs/CheckboxGroupInput.d.ts +7 -18
- 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 +3 -0
- package/dist/types/inputs/NumberInput.d.ts +7 -20
- package/dist/types/inputs/RepeatingFields.d.ts +7 -28
- package/dist/types/inputs/SelectInput.d.ts +7 -20
- package/dist/types/inputs/TextInput.d.ts +3 -0
- package/dist/types/inputs/TransferListInput.d.ts +7 -20
- package/dist/types/inputs/WizardLayout.d.ts +6 -19
- package/dist/types/kanban/KanbanBoard.d.ts +6 -25
- package/dist/types/legal/CookieNotice.d.ts +6 -16
- package/dist/types/legal/TermsAcceptanceDialog.d.ts +6 -18
- package/dist/types/locales/en.d.ts +24 -0
- package/dist/types/locales/es.d.ts +24 -0
- package/dist/types/maps/MapView.d.ts +6 -17
- package/dist/types/mexico/CfdiSummary.d.ts +6 -11
- package/dist/types/mexico/EfirmaFields.d.ts +6 -16
- package/dist/types/mexico/mexicoIdentifiers.d.ts +7 -0
- package/dist/types/mexico/mexicoRules.d.ts +19 -3
- package/dist/types/mexico.d.ts +2 -2
- 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 +1 -0
- package/dist/types/richText/RichTextEditor.d.ts +7 -22
- package/dist/types/richText/RichTextView.d.ts +6 -9
- 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 +9 -11
- package/dist/types/ui/actions/CopyButton.d.ts +6 -12
- 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/cards/RecordCard.d.ts +6 -31
- package/dist/types/ui/cards/RecordCardSkeleton.d.ts +6 -11
- package/dist/types/ui/countdown/Countdown.d.ts +6 -15
- package/dist/types/ui/documents/PdfViewerDialog.d.ts +6 -13
- package/dist/types/ui/filters/DateRangeFilter.d.ts +6 -10
- package/dist/types/ui/filters/FilterDrawer.d.ts +6 -17
- package/dist/types/ui/filters/PeriodRangeSelector.d.ts +6 -13
- package/dist/types/ui/filters/QuickFilters.d.ts +6 -12
- package/dist/types/ui/help/HelpButton.d.ts +6 -10
- package/dist/types/ui/help/HelpCarouselDialog.d.ts +6 -14
- 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 +7 -12
- package/dist/types/ui/timeline/GroupedTimeline.d.ts +6 -23
- package/dist/types/upload/AttachmentsInput.d.ts +11 -1
- package/dist/types/upload/FileDropzone.d.ts +6 -21
- package/dist/types/upload/FileInput.d.ts +7 -24
- package/dist/types/upload/FileUploadInput.d.ts +7 -31
- package/dist/types/upload/ImageInput.d.ts +7 -25
- package/dist/types/upload/TemplateDownloadButton.d.ts +6 -18
- package/dist/ui/actions/ActionsMenu.js +14 -5
- package/dist/ui/actions/ActionsMenu.js.map +1 -1
- package/dist/ui/actions/CopyButton.js +8 -3
- 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/cards/RecordCard.js +4 -3
- package/dist/ui/cards/RecordCard.js.map +1 -1
- package/dist/ui/cards/RecordCardSkeleton.js +8 -3
- package/dist/ui/cards/RecordCardSkeleton.js.map +1 -1
- package/dist/ui/countdown/Countdown.js +3 -2
- package/dist/ui/countdown/Countdown.js.map +1 -1
- package/dist/ui/documents/PdfViewerDialog.js +3 -2
- package/dist/ui/documents/PdfViewerDialog.js.map +1 -1
- package/dist/ui/filters/DateRangeFilter.js +3 -2
- package/dist/ui/filters/DateRangeFilter.js.map +1 -1
- package/dist/ui/filters/FilterDrawer.js +3 -2
- package/dist/ui/filters/FilterDrawer.js.map +1 -1
- 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/help/HelpButton.js +8 -3
- package/dist/ui/help/HelpButton.js.map +1 -1
- package/dist/ui/help/HelpCarouselDialog.js +3 -2
- package/dist/ui/help/HelpCarouselDialog.js.map +1 -1
- 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 +8 -4
- package/dist/ui/navigation/RouteTabs.js.map +1 -1
- package/dist/ui/timeline/GroupedTimeline.js +3 -2
- package/dist/ui/timeline/GroupedTimeline.js.map +1 -1
- package/dist/upload/AttachmentsInput.js +9 -6
- package/dist/upload/AttachmentsInput.js.map +1 -1
- package/dist/upload/FileChip.js +2 -1
- package/dist/upload/FileChip.js.map +1 -1
- package/dist/upload/FileDropzone.js +5 -4
- package/dist/upload/FileDropzone.js.map +1 -1
- package/dist/upload/FileInput.js +9 -6
- package/dist/upload/FileInput.js.map +1 -1
- package/dist/upload/FileUploadInput.js +9 -6
- package/dist/upload/FileUploadInput.js.map +1 -1
- package/dist/upload/ImageInput.js +8 -5
- package/dist/upload/ImageInput.js.map +1 -1
- package/dist/upload/TemplateDownloadButton.js +3 -2
- package/dist/upload/TemplateDownloadButton.js.map +1 -1
- package/package.json +1 -1
- package/cli/templates/project/src/app/combineTexts.js.tpl +0 -31
package/dist/appShell/TopMenu.js
CHANGED
|
@@ -11,7 +11,7 @@ import Menu from "@mui/material/Menu";
|
|
|
11
11
|
import MenuItem from "@mui/material/MenuItem";
|
|
12
12
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
|
13
13
|
import { menuItemLabelOf, menuLinkPropsOf } from "./menuItemText.js";
|
|
14
|
-
import { piecePart, usePieceProps } from "../theme/themePieces.js";
|
|
14
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
|
|
15
15
|
import { warnUnknownProps } from "../toolkit/unknownProps.js";
|
|
16
16
|
const THEME_NAME = "CalcitaTopMenu";
|
|
17
17
|
const TopMenuLink = piecePart(THEME_NAME, "Link", Button);
|
|
@@ -66,7 +66,7 @@ function TopMenuEntry({ menuItem, activeItem }) {
|
|
|
66
66
|
}) })
|
|
67
67
|
] });
|
|
68
68
|
}
|
|
69
|
-
function
|
|
69
|
+
function TopMenuContent(props) {
|
|
70
70
|
const { menuItems, activeItem, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
71
71
|
warnUnknownProps(THEME_NAME, unknownProps);
|
|
72
72
|
const { t } = useToolkitTranslation("layout");
|
|
@@ -80,6 +80,7 @@ function TopMenu(props) {
|
|
|
80
80
|
}
|
|
81
81
|
);
|
|
82
82
|
}
|
|
83
|
+
const TopMenu = withPieceSlots(TopMenuContent, THEME_NAME);
|
|
83
84
|
export {
|
|
84
85
|
TopMenu as default
|
|
85
86
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TopMenu.js","sources":["../../src/appShell/TopMenu.jsx"],"sourcesContent":["// El menú dentro de la barra (menuPosition=\"top\"), para apps de pocos módulos: cada entrada es un botón; la que tiene\n// submenú abre una lista debajo. Las secciones no se pintan aquí (en una fila no hay dónde); en el teléfono el menú es\n// el mismo cajón del estilo lateral, con sus secciones.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaTopMenu con defaultProps y\n// styleOverrides de sus partes: link, root.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {useToolkitNavigation} from '@/toolkit/toolkitContext.js';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport Menu from '@mui/material/Menu';\nimport MenuItem from '@mui/material/MenuItem';\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\n\nimport {menuItemLabelOf, menuLinkPropsOf} from '@/appShell/menuItemText.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.CalcitaTopMenu)\nconst THEME_NAME = 'CalcitaTopMenu';\nconst TopMenuLink = piecePart(THEME_NAME, 'Link', Button);\nconst TopMenuRoot = piecePart(THEME_NAME, 'Root', Box);\n\n// la entrada abierta se marca con una raya abajo, del color principal (en la barra naranja, del color del texto)\nconst ACTIVE_UNDERLINE_PIXELS = 2;\n\n/**\n * Un botón del menú de arriba, con su lista si tiene submenú.\n *\n * @param {{menuItem: object, activeItem: object|null}} props\n */\nfunction TopMenuEntry({menuItem, activeItem}) {\n const {t} = useToolkitTranslation('layout');\n const {Link: RouterLink} = useToolkitNavigation();\n const [anchorElement, setAnchorElement] = useState(null);\n const hasChildren = Array.isArray(menuItem.children) && menuItem.children.length > 0;\n const isActive = menuItem === activeItem || (hasChildren && menuItem.children.includes(activeItem));\n const Icon = menuItem.Icon;\n const buttonSx = {\n color: 'inherit', borderRadius: 1, px: 1.5, whiteSpace: 'nowrap', fontWeight: isActive ? 600 : 500,\n boxShadow: isActive ? `inset 0 -${ACTIVE_UNDERLINE_PIXELS}px 0 currentColor` : 'none',\n };\n\n if (!hasChildren) {\n return (\n <TopMenuLink {...menuLinkPropsOf(menuItem, RouterLink)} startIcon={Icon ? <Icon fontSize=\"small\" /> : undefined}\n aria-current={isActive ? 'page' : undefined} ownSx={buttonSx}>\n {menuItemLabelOf(menuItem, t)}\n </TopMenuLink>\n );\n }\n return (\n <>\n <TopMenuLink onClick={(event) => setAnchorElement(event.currentTarget)} aria-haspopup=\"menu\" aria-expanded={Boolean(anchorElement)}\n startIcon={Icon ? <Icon fontSize=\"small\" /> : undefined} endIcon={<ExpandMoreIcon fontSize=\"small\" />} ownSx={buttonSx}>\n {menuItemLabelOf(menuItem, t)}\n </TopMenuLink>\n <Menu anchorEl={anchorElement} open={Boolean(anchorElement)} onClose={() => setAnchorElement(null)} slotProps={{paper: {sx: {minWidth: 220, mt: 0.5}}}}>\n {menuItem.children.map((child) => {\n const ChildIcon = child.Icon;\n return (\n <MenuItem key={child.to ?? child.href} {...menuLinkPropsOf(child, RouterLink)} selected={child === activeItem} onClick={() => setAnchorElement(null)}>\n {ChildIcon && <ListItemIcon><ChildIcon fontSize=\"small\" /></ListItemIcon>}\n <ListItemText primary={menuItemLabelOf(child, t)} />\n </MenuItem>\n );\n })}\n </Menu>\n </>\n );\n}\n\n/**\n * @param {{menuItems: object[], activeItem: object|null}} props\n */\
|
|
1
|
+
{"version":3,"file":"TopMenu.js","sources":["../../src/appShell/TopMenu.jsx"],"sourcesContent":["// El menú dentro de la barra (menuPosition=\"top\"), para apps de pocos módulos: cada entrada es un botón; la que tiene\n// submenú abre una lista debajo. Las secciones no se pintan aquí (en una fila no hay dónde); en el teléfono el menú es\n// el mismo cajón del estilo lateral, con sus secciones.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaTopMenu con defaultProps y\n// styleOverrides de sus partes: link, root.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {useToolkitNavigation} from '@/toolkit/toolkitContext.js';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport Menu from '@mui/material/Menu';\nimport MenuItem from '@mui/material/MenuItem';\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\n\nimport {menuItemLabelOf, menuLinkPropsOf} from '@/appShell/menuItemText.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.CalcitaTopMenu)\nconst THEME_NAME = 'CalcitaTopMenu';\nconst TopMenuLink = piecePart(THEME_NAME, 'Link', Button);\nconst TopMenuRoot = piecePart(THEME_NAME, 'Root', Box);\n\n// la entrada abierta se marca con una raya abajo, del color principal (en la barra naranja, del color del texto)\nconst ACTIVE_UNDERLINE_PIXELS = 2;\n\n/**\n * Un botón del menú de arriba, con su lista si tiene submenú.\n *\n * @param {{menuItem: object, activeItem: object|null}} props\n */\nfunction TopMenuEntry({menuItem, activeItem}) {\n const {t} = useToolkitTranslation('layout');\n const {Link: RouterLink} = useToolkitNavigation();\n const [anchorElement, setAnchorElement] = useState(null);\n const hasChildren = Array.isArray(menuItem.children) && menuItem.children.length > 0;\n const isActive = menuItem === activeItem || (hasChildren && menuItem.children.includes(activeItem));\n const Icon = menuItem.Icon;\n const buttonSx = {\n color: 'inherit', borderRadius: 1, px: 1.5, whiteSpace: 'nowrap', fontWeight: isActive ? 600 : 500,\n boxShadow: isActive ? `inset 0 -${ACTIVE_UNDERLINE_PIXELS}px 0 currentColor` : 'none',\n };\n\n if (!hasChildren) {\n return (\n <TopMenuLink {...menuLinkPropsOf(menuItem, RouterLink)} startIcon={Icon ? <Icon fontSize=\"small\" /> : undefined}\n aria-current={isActive ? 'page' : undefined} ownSx={buttonSx}>\n {menuItemLabelOf(menuItem, t)}\n </TopMenuLink>\n );\n }\n return (\n <>\n <TopMenuLink onClick={(event) => setAnchorElement(event.currentTarget)} aria-haspopup=\"menu\" aria-expanded={Boolean(anchorElement)}\n startIcon={Icon ? <Icon fontSize=\"small\" /> : undefined} endIcon={<ExpandMoreIcon fontSize=\"small\" />} ownSx={buttonSx}>\n {menuItemLabelOf(menuItem, t)}\n </TopMenuLink>\n <Menu anchorEl={anchorElement} open={Boolean(anchorElement)} onClose={() => setAnchorElement(null)} slotProps={{paper: {sx: {minWidth: 220, mt: 0.5}}}}>\n {menuItem.children.map((child) => {\n const ChildIcon = child.Icon;\n return (\n <MenuItem key={child.to ?? child.href} {...menuLinkPropsOf(child, RouterLink)} selected={child === activeItem} onClick={() => setAnchorElement(null)}>\n {ChildIcon && <ListItemIcon><ChildIcon fontSize=\"small\" /></ListItemIcon>}\n <ListItemText primary={menuItemLabelOf(child, t)} />\n </MenuItem>\n );\n })}\n </Menu>\n </>\n );\n}\n\n/**\n * @param {{menuItems: object[], activeItem: object|null}} props\n */\nfunction TopMenuContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaTopMenu.defaultProps) y encima lo que llega aquí\n const {menuItems, activeItem, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('layout');\n return (\n <TopMenuRoot component=\"nav\" aria-label={t('drawer.ariaLabel')}\n ownSx={{display: {xs: 'none', md: 'flex'}, alignItems: 'stretch', alignSelf: 'stretch', gap: 0.5, minWidth: 0, overflowX: 'auto'}}>\n {menuItems.map((menuItem) => (\n <TopMenuEntry key={menuItem.to ?? menuItem.href ?? menuItemLabelOf(menuItem, t)} menuItem={menuItem} activeItem={activeItem} />\n ))}\n </TopMenuRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst TopMenu = withPieceSlots(TopMenuContent, THEME_NAME);\nexport default TopMenu;\n"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { isValidElement } from "react";
|
|
4
4
|
import Box from "@mui/material/Box";
|
|
5
|
-
import { piecePart, usePieceProps } from "../theme/themePieces.js";
|
|
5
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
|
|
6
6
|
import { warnUnknownProps } from "../toolkit/unknownProps.js";
|
|
7
7
|
const THEME_NAME = "CalcitaWordmark";
|
|
8
8
|
const WordmarkRoot = piecePart(THEME_NAME, "Root", Box);
|
|
@@ -11,7 +11,7 @@ const WORDMARK_HEIGHT_PIXELS = 24;
|
|
|
11
11
|
function isWordmarkPair(wordmark) {
|
|
12
12
|
return wordmark !== null && typeof wordmark === "object" && !isValidElement(wordmark) && !Array.isArray(wordmark) && ("light" in wordmark || "dark" in wordmark);
|
|
13
13
|
}
|
|
14
|
-
function
|
|
14
|
+
function WordmarkContent(props) {
|
|
15
15
|
const { children, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
16
16
|
warnUnknownProps(THEME_NAME, unknownProps);
|
|
17
17
|
return /* @__PURE__ */ jsx(WordmarkRoot, { ownSx: {
|
|
@@ -25,6 +25,7 @@ function Wordmark(props) {
|
|
|
25
25
|
/* @__PURE__ */ jsx(WordmarkMode, { ownSx: (theme) => ({ display: "none", ...theme.applyStyles("dark", { display: "contents" }) }), children: children.dark ?? children.light })
|
|
26
26
|
] }) : children });
|
|
27
27
|
}
|
|
28
|
+
const Wordmark = withPieceSlots(WordmarkContent, THEME_NAME);
|
|
28
29
|
export {
|
|
29
30
|
Wordmark as default,
|
|
30
31
|
isWordmarkPair
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Wordmark.js","sources":["../../src/appShell/Wordmark.jsx"],"sourcesContent":["// El logo ancho de la app (la marca con su nombre en una sola imagen, como el de muchas empresas) en la barra y arriba del\n// menú del teléfono: a 24 px de alto y lo ancho que pida, sin deformarse. Una imagen o un svg toman ese alto solos.\n//\n// Con una imagen para cada modo ({light: <img …/>, dark: <img …/>}: el de color en claro y el blanco en oscuro) se pintan\n// las dos y el modo decide cuál se ve, sin parpadeo al cambiar ni al cargar.\n//\n// OJO, trampa pagada (la prueba en un sistema que ya existía): la regla de la imagen («height 100 %, display block») iba\n// como «& > img» y le ganaba al sx de la imagen del proyecto; quien escondía una de sus dos imágenes con CSS no podía. Ahora\n// va con :where(), que no suma peso: lo que el proyecto le ponga a su imagen gana.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaWordmark con defaultProps y\n// styleOverrides de sus partes: root y mode (la imagen de cada modo).\n//\n// Genérico del paquete: function (regla de la casa).\nimport {isValidElement} from 'react';\nimport Box from '@mui/material/Box';\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.CalcitaWordmark)\nconst THEME_NAME = 'CalcitaWordmark';\nconst WordmarkRoot = piecePart(THEME_NAME, 'Root', Box);\nconst WordmarkMode = piecePart(THEME_NAME, 'Mode', 'span');\n\n// el alto del logo ancho: el de la letra del nombre con su renglón, para que la barra no crezca\nconst WORDMARK_HEIGHT_PIXELS = 24;\n\n/**\n * ¿Llegó una imagen para cada modo ({light, dark}) y no un logo solo?\n *\n * @param {unknown} wordmark\n * @returns {boolean}\n */\nexport function isWordmarkPair(wordmark) {\n return wordmark !== null && typeof wordmark === 'object' && !isValidElement(wordmark) && !Array.isArray(wordmark)\n && ('light' in wordmark || 'dark' in wordmark);\n}\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode | {light?: import('react').ReactNode, dark?: import('react').ReactNode}} props.children el\n * logo (una <img>, un <svg> o lo que pinte el proyecto) o uno para cada modo: {light, dark}\n */\
|
|
1
|
+
{"version":3,"file":"Wordmark.js","sources":["../../src/appShell/Wordmark.jsx"],"sourcesContent":["// El logo ancho de la app (la marca con su nombre en una sola imagen, como el de muchas empresas) en la barra y arriba del\n// menú del teléfono: a 24 px de alto y lo ancho que pida, sin deformarse. Una imagen o un svg toman ese alto solos.\n//\n// Con una imagen para cada modo ({light: <img …/>, dark: <img …/>}: el de color en claro y el blanco en oscuro) se pintan\n// las dos y el modo decide cuál se ve, sin parpadeo al cambiar ni al cargar.\n//\n// OJO, trampa pagada (la prueba en un sistema que ya existía): la regla de la imagen («height 100 %, display block») iba\n// como «& > img» y le ganaba al sx de la imagen del proyecto; quien escondía una de sus dos imágenes con CSS no podía. Ahora\n// va con :where(), que no suma peso: lo que el proyecto le ponga a su imagen gana.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaWordmark con defaultProps y\n// styleOverrides de sus partes: root y mode (la imagen de cada modo).\n//\n// Genérico del paquete: function (regla de la casa).\nimport {isValidElement} from 'react';\nimport Box from '@mui/material/Box';\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.CalcitaWordmark)\nconst THEME_NAME = 'CalcitaWordmark';\nconst WordmarkRoot = piecePart(THEME_NAME, 'Root', Box);\nconst WordmarkMode = piecePart(THEME_NAME, 'Mode', 'span');\n\n// el alto del logo ancho: el de la letra del nombre con su renglón, para que la barra no crezca\nconst WORDMARK_HEIGHT_PIXELS = 24;\n\n/**\n * ¿Llegó una imagen para cada modo ({light, dark}) y no un logo solo?\n *\n * @param {unknown} wordmark\n * @returns {boolean}\n */\nexport function isWordmarkPair(wordmark) {\n return wordmark !== null && typeof wordmark === 'object' && !isValidElement(wordmark) && !Array.isArray(wordmark)\n && ('light' in wordmark || 'dark' in wordmark);\n}\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode | {light?: import('react').ReactNode, dark?: import('react').ReactNode}} props.children el\n * logo (una <img>, un <svg> o lo que pinte el proyecto) o uno para cada modo: {light, dark}\n */\nfunction WordmarkContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaWordmark.defaultProps) y encima lo que llega aquí\n const {children, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n return (\n <WordmarkRoot ownSx={{\n height: WORDMARK_HEIGHT_PIXELS, display: 'flex', alignItems: 'center', flex: '0 0 auto',\n '& :where(img, svg)': {height: '100%', width: 'auto', display: 'block'},\n }}>\n {isWordmarkPair(children) ? (\n <>\n {/* las dos se pintan y el modo decide cuál se ve: display contents deja a la imagen tomar el alto */}\n <WordmarkMode ownSx={(theme) => ({display: 'contents', ...theme.applyStyles('dark', {display: 'none'})})}>{children.light ?? children.dark}</WordmarkMode>\n <WordmarkMode ownSx={(theme) => ({display: 'none', ...theme.applyStyles('dark', {display: 'contents'})})}>{children.dark ?? children.light}</WordmarkMode>\n </>\n ) : children}\n </WordmarkRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst Wordmark = withPieceSlots(WordmarkContent, THEME_NAME);\nexport default Wordmark;\n"],"names":[],"mappings":";;;;;;AAoBA,MAAM,aAAa;AACnB,MAAM,eAAe,UAAU,YAAY,QAAQ,GAAG;AACtD,MAAM,eAAe,UAAU,YAAY,QAAQ,MAAM;AAGzD,MAAM,yBAAyB;AAQxB,SAAS,eAAe,UAAU;AACrC,SAAO,aAAa,QAAQ,OAAO,aAAa,YAAY,CAAC,eAAe,QAAQ,KAAK,CAAC,MAAM,QAAQ,QAAQ,MACxG,WAAW,YAAY,UAAU;AAC7C;AAOA,SAAS,gBAAgB,OAAO;AAE5B,QAAM,EAAC,UAAU,GAAG,iBAAgB,cAAc,OAAO,UAAU;AACnE,mBAAiB,YAAY,YAAY;AACzC,SACI,oBAAC,gBAAa,OAAO;AAAA,IACjB,QAAQ;AAAA,IAAwB,SAAS;AAAA,IAAQ,YAAY;AAAA,IAAU,MAAM;AAAA,IAC7E,sBAAsB,EAAC,QAAQ,QAAQ,OAAO,QAAQ,SAAS,QAAA;AAAA,EAAO,GAErE,UAAA,eAAe,QAAQ,IACpB,qBAAA,UAAA,EAEI,UAAA;AAAA,IAAA,oBAAC,cAAA,EAAa,OAAO,CAAC,WAAW,EAAC,SAAS,YAAY,GAAG,MAAM,YAAY,QAAQ,EAAC,SAAS,QAAO,MAAM,UAAA,SAAS,SAAS,SAAS,MAAK;AAAA,IAC3I,oBAAC,gBAAa,OAAO,CAAC,WAAW,EAAC,SAAS,QAAQ,GAAG,MAAM,YAAY,QAAQ,EAAC,SAAS,WAAA,CAAW,MAAM,UAAA,SAAS,QAAQ,SAAS,MAAA,CAAM;AAAA,EAAA,EAAA,CAC/I,IACA,UACR;AAER;AAGA,MAAM,WAAW,eAAe,iBAAiB,UAAU;"}
|
|
@@ -6,7 +6,7 @@ import Typography from "@mui/material/Typography";
|
|
|
6
6
|
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
|
|
7
7
|
import RadioButtonUncheckedIcon from "@mui/icons-material/RadioButtonUnchecked";
|
|
8
8
|
import { DEFAULT_PASSWORD_POLICY, passwordChecksOf } from "./passwordRules.js";
|
|
9
|
-
import { piecePart, usePieceProps } from "../theme/themePieces.js";
|
|
9
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
|
|
10
10
|
import { warnUnknownProps } from "../toolkit/unknownProps.js";
|
|
11
11
|
const THEME_NAME = "CalcitaPasswordChecklist";
|
|
12
12
|
const ChecklistTitle = piecePart(THEME_NAME, "Title", Typography);
|
|
@@ -24,7 +24,7 @@ const SCREEN_READER_ONLY_SX = {
|
|
|
24
24
|
whiteSpace: "nowrap",
|
|
25
25
|
border: 0
|
|
26
26
|
};
|
|
27
|
-
function
|
|
27
|
+
function PasswordChecklistContent(props) {
|
|
28
28
|
const { password, policy = DEFAULT_PASSWORD_POLICY, id, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
29
29
|
warnUnknownProps(THEME_NAME, unknownProps);
|
|
30
30
|
const { t } = useToolkitTranslation("auth", texts);
|
|
@@ -47,6 +47,7 @@ function PasswordChecklist(props) {
|
|
|
47
47
|
)) })
|
|
48
48
|
] });
|
|
49
49
|
}
|
|
50
|
+
const PasswordChecklist = withPieceSlots(PasswordChecklistContent, THEME_NAME);
|
|
50
51
|
export {
|
|
51
52
|
PasswordChecklist as default
|
|
52
53
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PasswordChecklist.js","sources":["../../src/auth/PasswordChecklist.jsx"],"sourcesContent":["// La lista de lo que debe tener una contraseña nueva, que se va palomeando mientras la persona escribe: dice qué falta\n// ANTES de enviar, en lugar de un «contraseña inválida» después.\n//\n// Para el lector de pantalla cada renglón dice si ya cumple o falta (con el ícono solo, se oía la regla sin saber cómo\n// iba). Va justo debajo del campo de la contraseña nueva.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaPasswordChecklist con defaultProps y\n// styleOverrides de sus partes: title, list, item, hidden.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport CheckCircleIcon from '@mui/icons-material/CheckCircle';\nimport RadioButtonUncheckedIcon from '@mui/icons-material/RadioButtonUnchecked';\n\nimport {DEFAULT_PASSWORD_POLICY, passwordChecksOf} from '@/auth/passwordRules.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.CalcitaPasswordChecklist)\nconst THEME_NAME = 'CalcitaPasswordChecklist';\nconst ChecklistTitle = piecePart(THEME_NAME, 'Title', Typography);\nconst ChecklistList = piecePart(THEME_NAME, 'List', Box);\nconst ChecklistItem = piecePart(THEME_NAME, 'Item', Box);\nconst ChecklistHidden = piecePart(THEME_NAME, 'Hidden', Box);\n\n// texto que solo oye el lector de pantalla (el mismo truco que usa MUI)\nconst SCREEN_READER_ONLY_SX = {\n position: 'absolute', width: '1px', height: '1px', padding: 0, margin: '-1px', overflow: 'hidden', clip: 'rect(0 0 0 0)', whiteSpace: 'nowrap', border: 0,\n};\n\n/**\n * @param {object} props\n * @param {string} props.password lo que lleva escrito la persona\n * @param {object} [props.policy] las reglas; por omisión DEFAULT_PASSWORD_POLICY\n * @param {string} [props.id]\n * @param {object} [props.texts] los textos que cambian, con la forma de `auth` en los textos del paquete\n */\
|
|
1
|
+
{"version":3,"file":"PasswordChecklist.js","sources":["../../src/auth/PasswordChecklist.jsx"],"sourcesContent":["// La lista de lo que debe tener una contraseña nueva, que se va palomeando mientras la persona escribe: dice qué falta\n// ANTES de enviar, en lugar de un «contraseña inválida» después.\n//\n// Para el lector de pantalla cada renglón dice si ya cumple o falta (con el ícono solo, se oía la regla sin saber cómo\n// iba). Va justo debajo del campo de la contraseña nueva.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaPasswordChecklist con defaultProps y\n// styleOverrides de sus partes: title, list, item, hidden.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport CheckCircleIcon from '@mui/icons-material/CheckCircle';\nimport RadioButtonUncheckedIcon from '@mui/icons-material/RadioButtonUnchecked';\n\nimport {DEFAULT_PASSWORD_POLICY, passwordChecksOf} from '@/auth/passwordRules.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.CalcitaPasswordChecklist)\nconst THEME_NAME = 'CalcitaPasswordChecklist';\nconst ChecklistTitle = piecePart(THEME_NAME, 'Title', Typography);\nconst ChecklistList = piecePart(THEME_NAME, 'List', Box);\nconst ChecklistItem = piecePart(THEME_NAME, 'Item', Box);\nconst ChecklistHidden = piecePart(THEME_NAME, 'Hidden', Box);\n\n// texto que solo oye el lector de pantalla (el mismo truco que usa MUI)\nconst SCREEN_READER_ONLY_SX = {\n position: 'absolute', width: '1px', height: '1px', padding: 0, margin: '-1px', overflow: 'hidden', clip: 'rect(0 0 0 0)', whiteSpace: 'nowrap', border: 0,\n};\n\n/**\n * @param {object} props\n * @param {string} props.password lo que lleva escrito la persona\n * @param {object} [props.policy] las reglas; por omisión DEFAULT_PASSWORD_POLICY\n * @param {string} [props.id]\n * @param {object} [props.texts] los textos que cambian, con la forma de `auth` en los textos del paquete\n */\nfunction PasswordChecklistContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaPasswordChecklist.defaultProps) y encima lo que llega aquí\n const {password, policy = DEFAULT_PASSWORD_POLICY, id, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('auth', texts);\n return (\n <Box id={id}>\n <ChecklistTitle variant=\"caption\" color=\"text.secondary\" component=\"p\" ownSx={{mb: 0.5}}>{t('passwordRules.title')}</ChecklistTitle>\n <ChecklistList component=\"ul\" ownSx={{listStyle: 'none', m: 0, p: 0, display: 'grid', gap: 0.5}}>\n {passwordChecksOf(password, policy).map((check) => (\n <ChecklistItem component=\"li\" key={check.rule} data-rule={check.rule} data-met={check.isMet}\n ownSx={{display: 'flex', alignItems: 'center', gap: 1, color: check.isMet ? 'text.primary' : 'text.secondary'}}>\n {check.isMet\n ? <CheckCircleIcon fontSize=\"small\" color=\"success\" aria-hidden />\n : <RadioButtonUncheckedIcon fontSize=\"small\" color=\"disabled\" aria-hidden />}\n <Typography variant=\"body2\" component=\"span\">{t(`passwordRules.${check.rule}`, check.values)}</Typography>\n <ChecklistHidden component=\"span\" ownSx={SCREEN_READER_ONLY_SX}>{check.isMet ? t('passwordRules.met') : t('passwordRules.missing')}</ChecklistHidden>\n </ChecklistItem>\n ))}\n </ChecklistList>\n </Box>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst PasswordChecklist = withPieceSlots(PasswordChecklistContent, THEME_NAME);\nexport default PasswordChecklist;\n"],"names":[],"mappings":";;;;;;;;;;AAqBA,MAAM,aAAa;AACnB,MAAM,iBAAiB,UAAU,YAAY,SAAS,UAAU;AAChE,MAAM,gBAAgB,UAAU,YAAY,QAAQ,GAAG;AACvD,MAAM,gBAAgB,UAAU,YAAY,QAAQ,GAAG;AACvD,MAAM,kBAAkB,UAAU,YAAY,UAAU,GAAG;AAG3D,MAAM,wBAAwB;AAAA,EAC1B,UAAU;AAAA,EAAY,OAAO;AAAA,EAAO,QAAQ;AAAA,EAAO,SAAS;AAAA,EAAG,QAAQ;AAAA,EAAQ,UAAU;AAAA,EAAU,MAAM;AAAA,EAAiB,YAAY;AAAA,EAAU,QAAQ;AAC5J;AASA,SAAS,yBAAyB,OAAO;AAErC,QAAM,EAAC,UAAU,SAAS,yBAAyB,IAAI,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AAChH,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,QAAQ,KAAK;AAC/C,SACI,qBAAC,OAAI,IACD,UAAA;AAAA,IAAA,oBAAC,gBAAA,EAAe,SAAQ,WAAU,OAAM,kBAAiB,WAAU,KAAI,OAAO,EAAC,IAAI,IAAA,GAAO,UAAA,EAAE,qBAAqB,GAAE;AAAA,IACnH,oBAAC,iBAAc,WAAU,MAAK,OAAO,EAAC,WAAW,QAAQ,GAAG,GAAG,GAAG,GAAG,SAAS,QAAQ,KAAK,IAAA,GACtF,UAAA,iBAAiB,UAAU,MAAM,EAAE,IAAI,CAAC,UACrC;AAAA,MAAC;AAAA,MAAA;AAAA,QAAc,WAAU;AAAA,QAAsB,aAAW,MAAM;AAAA,QAAM,YAAU,MAAM;AAAA,QACjF,OAAO,EAAC,SAAS,QAAQ,YAAY,UAAU,KAAK,GAAG,OAAO,MAAM,QAAQ,iBAAiB,iBAAA;AAAA,QAC7F,UAAA;AAAA,UAAA,MAAM,QACD,oBAAC,iBAAA,EAAgB,UAAS,SAAQ,OAAM,WAAU,eAAW,KAAA,CAAC,wBAC7D,0BAAA,EAAyB,UAAS,SAAQ,OAAM,YAAW,eAAW,MAAC;AAAA,UAC9E,oBAAC,YAAA,EAAW,SAAQ,SAAQ,WAAU,QAAQ,UAAA,EAAE,iBAAiB,MAAM,IAAI,IAAI,MAAM,MAAM,GAAE;AAAA,UAC7F,oBAAC,iBAAA,EAAgB,WAAU,QAAO,OAAO,uBAAwB,UAAA,MAAM,QAAQ,EAAE,mBAAmB,IAAI,EAAE,uBAAuB,EAAA,CAAE;AAAA,QAAA;AAAA,MAAA;AAAA,MANpG,MAAM;AAAA,IAAA,CAQ5C,EAAA,CACL;AAAA,EAAA,GACJ;AAER;AAGA,MAAM,oBAAoB,eAAe,0BAA0B,UAAU;"}
|
|
@@ -20,7 +20,7 @@ import { paletteOf } from "../theme/components/paletteOf.js";
|
|
|
20
20
|
import { useToolkitSettings } from "../toolkit/toolkitContext.js";
|
|
21
21
|
import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
|
|
22
22
|
import SegmentedControl from "../ui/filters/SegmentedControl.js";
|
|
23
|
-
import { piecePart, usePieceProps } from "../theme/themePieces.js";
|
|
23
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
|
|
24
24
|
import { warnUnknownProps } from "../toolkit/unknownProps.js";
|
|
25
25
|
const THEME_NAME = "CalcitaEventCalendar";
|
|
26
26
|
const CalendarToolbar = piecePart(THEME_NAME, "Toolbar", Stack);
|
|
@@ -60,7 +60,7 @@ function calendarStylesOf(theme) {
|
|
|
60
60
|
"& .fc-list": { borderRadius: "12px" }
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
|
-
function
|
|
63
|
+
function EventCalendarContent(props) {
|
|
64
64
|
const {
|
|
65
65
|
events,
|
|
66
66
|
initialView = CALENDAR_VIEW.month,
|
|
@@ -152,6 +152,7 @@ function EventCalendar(props) {
|
|
|
152
152
|
) })
|
|
153
153
|
] });
|
|
154
154
|
}
|
|
155
|
+
const EventCalendar = withPieceSlots(EventCalendarContent, THEME_NAME);
|
|
155
156
|
export {
|
|
156
157
|
CALENDAR_VIEW,
|
|
157
158
|
EventCalendar as default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EventCalendar.js","sources":["../../src/calendar/EventCalendar.jsx"],"sourcesContent":["// Un calendario de eventos (@stackcraftmx/calcita/calendar): FullCalendar por dentro, con la barra del framework (anterior y\n// siguiente, «Hoy», el título y la vista con el control segmentado) y los colores del tema. En el idioma de\n// ToolkitProvider, la semana empieza en lunes y marca la hora actual. Las citas van en bloques de su color (el color es\n// información: el tipo de cita), no en puntitos.\n//\n// <EventCalendar events={[{id: '1', title: 'Entrega P-2375', start: '2026-10-20T10:00', end: '2026-10-20T11:00', tone: 'info'}]}\n// onEventClick={openDetail} onDateSelect={openNewEvent} onEventChange={(change) => api.patch(...)} />\n//\n// Arrastrar un evento lo cambia de día u hora: onEventChange recibe lo nuevo y, si truena (el servidor dijo que no), el\n// evento regresa a donde estaba. Sin onEventChange no se puede arrastrar; sin onDateSelect no se pueden elegir días.\n//\n// Se extiende sin tocar el framework: onDatesChange avisa el rango que se ve (para que el backend mande solo esas citas),\n// onViewChange la vista, renderEvent pinta cada cita a su manera (recibe la cita tal cual, con sus campos propios),\n// fullCalendarProps pasa lo demás de FullCalendar (horario laboral, días ocultos, horas visibles…) y texts los textos. El\n// detalle de una cita para su ventana: EventDetails.\n//\n// OJO: las horas se pintan en la zona del navegador (FullCalendar pide un complemento aparte para zonas con nombre).\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaEventCalendar con defaultProps y\n// styleOverrides de sus partes: toolbar, navigation, title, calendar.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useRef, useState} from 'react';\nimport FullCalendar from '@fullcalendar/react';\nimport dayGridPlugin from '@fullcalendar/daygrid';\nimport interactionPlugin from '@fullcalendar/interaction';\nimport listPlugin from '@fullcalendar/list';\nimport timeGridPlugin from '@fullcalendar/timegrid';\nimport spanishLocale from '@fullcalendar/core/locales/es';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport IconButton from '@mui/material/IconButton';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport {useTheme} from '@mui/material/styles';\nimport ChevronLeftRoundedIcon from '@mui/icons-material/ChevronLeftRounded';\nimport ChevronRightRoundedIcon from '@mui/icons-material/ChevronRightRounded';\n\nimport {paletteOf} from '@/theme/components/paletteOf.js';\nimport {useToolkitSettings} from '@/toolkit/toolkitContext.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport SegmentedControl from '@/ui/filters/SegmentedControl.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.CalcitaEventCalendar)\nconst THEME_NAME = 'CalcitaEventCalendar';\nconst CalendarToolbar = piecePart(THEME_NAME, 'Toolbar', Stack);\nconst CalendarNavigation = piecePart(THEME_NAME, 'Navigation', Stack);\nconst CalendarTitle = piecePart(THEME_NAME, 'Title', Typography);\nconst CalendarCalendar = piecePart(THEME_NAME, 'Calendar', Box);\n\n/** Las vistas del calendario (los nombres de FullCalendar). */\nexport const CALENDAR_VIEW = Object.freeze({month: 'dayGridMonth', week: 'timeGridWeek', day: 'timeGridDay', list: 'listWeek'});\n\n// el texto de cada vista en los textos del paquete (calendar.views.*)\nconst VIEW_TEXT_KEY = Object.freeze({\n [CALENDAR_VIEW.month]: 'month', [CALENDAR_VIEW.week]: 'week', [CALENDAR_VIEW.day]: 'day', [CALENDAR_VIEW.list]: 'list',\n});\n// cuántos eventos caben en un día del mes antes del «+2 más»\nconst DAY_MAX_EVENTS = 3;\nconst MONDAY = 1;\n\n/**\n * La primera letra en mayúscula y lo demás como viene: «octubre de 2026» → «Octubre de 2026». OJO: con CSS\n * (text-transform: capitalize) salía «Octubre De 2026»: en español solo va la primera.\n *\n * @param {string} text\n * @returns {string}\n */\nfunction capitalizeFirst(text) {\n return text ? text.charAt(0).toLocaleUpperCase() + text.slice(1) : text;\n}\n\n/**\n * Los colores del calendario sobre el tema (las variables CSS de FullCalendar), en claro y en oscuro.\n *\n * @param {object} theme\n * @returns {object}\n */\nfunction calendarStylesOf(theme) {\n const palette = paletteOf(theme);\n return {\n '--fc-border-color': palette.divider,\n '--fc-page-bg-color': 'transparent',\n '--fc-neutral-bg-color': palette.action.hover,\n '--fc-today-bg-color': `color-mix(in srgb, ${palette.primary.main} 8%, transparent)`,\n '--fc-list-event-hover-bg-color': palette.action.hover,\n '--fc-now-indicator-color': palette.error.main,\n '--fc-highlight-color': `color-mix(in srgb, ${palette.primary.main} 14%, transparent)`,\n '& .fc': {fontFamily: 'inherit', fontSize: theme.typography.body2.fontSize},\n // los números de los días y los encabezados son ligas en FullCalendar: sin subrayado y del color del texto\n '& .fc a': {color: 'inherit', textDecoration: 'none'},\n '& .fc-col-header-cell-cushion': {fontWeight: 600, py: 1},\n '& .fc-event': {borderRadius: '6px', px: 0.5},\n // la hora no se encoge: en un día angosto se recortaba («1C» en lugar de «10»); lo que se corta es el nombre\n '& .fc-event-time': {flexShrink: 0, overflow: 'visible'},\n '& .fc-scrollgrid': {borderRadius: '12px', overflow: 'hidden'},\n '& .fc-list': {borderRadius: '12px'},\n };\n}\n\n/**\n * @param {object} props\n * @param {Array<{id: string, title: string, start: string, end?: string, allDay?: boolean, tone?: string}>} props.events\n * start y end como texto ISO; tone: un color del tema (por omisión primary)\n * @param {string} [props.initialView] una de CALENDAR_VIEW\n * @param {string[]} [props.views] las que se ofrecen en el control segmentado\n * @param {(eventId: string) => void} [props.onEventClick]\n * @param {(range: {start: string, end: string, allDay: boolean}) => void} [props.onDateSelect] al elegir días u horas\n * @param {(change: {id: string, start: string, end: string|null, allDay: boolean}) => Promise<unknown>|void} [props.onEventChange]\n * al arrastrar un evento; si truena, el evento regresa\n * @param {number|'auto'} [props.height]\n * @param {string} props.ariaLabel ya traducido\n * @param {(range: {start: string, end: string, view: string}) => void} [props.onDatesChange] cada que cambia lo que se ve (al\n * abrir, al ir al anterior o siguiente, al cambiar de vista): para pedir al backend solo las citas de ese rango\n * @param {(view: string) => void} [props.onViewChange] al cambiar de vista (CALENDAR_VIEW)\n * @param {(event: any) => import('react').ReactNode} [props.renderEvent] lo de adentro de cada cita (recibe la cita de events\n * tal cual, con sus campos propios)\n * @param {object} [props.fullCalendarProps] lo demás de FullCalendar (businessHours, hiddenDays, slotMinTime, locale…); lo\n * que el calendario controla (las citas, la barra, los eventos de arriba) no se reemplaza desde aquí\n * @param {object} [props.texts] los textos que cambian, con la forma de `calendar` en los textos del paquete\n */\nexport default function EventCalendar(props) {\n // lo que el proyecto puso en su tema (components.CalcitaEventCalendar.defaultProps) y encima lo que llega aquí\n const {\n events, initialView = CALENDAR_VIEW.month, views = Object.values(CALENDAR_VIEW), onEventClick, onDateSelect, onEventChange, height = 'auto', ariaLabel,\n onDatesChange, onViewChange, renderEvent, fullCalendarProps, texts,\n ...unknownProps\n} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const theme = useTheme();\n const palette = paletteOf(theme);\n const {t} = useToolkitTranslation('calendar', texts);\n const {language} = useToolkitSettings();\n const calendarRef = useRef(null);\n const [title, setTitle] = useState('');\n const [view, setView] = useState(initialView);\n const calendarApi = () => calendarRef.current?.getApi();\n\n const coloredEvents = events.map((event) => {\n const color = palette[event.tone] ?? palette.primary;\n return {...event, backgroundColor: color.main, borderColor: color.main, textColor: color.contrastText};\n });\n\n const changeEvent = async ({event, revert}) => {\n try {\n await onEventChange({id: event.id, start: event.startStr, end: event.endStr || null, allDay: event.allDay});\n } catch {\n // el servidor dijo que no: el evento regresa a donde estaba (quien llama ya avisó el error)\n revert();\n }\n };\n\n return (\n <Stack spacing={2} role=\"region\" aria-label={ariaLabel}>\n <CalendarToolbar direction={{xs: 'column', md: 'row'}} spacing={1.5} ownSx={{alignItems: {md: 'center'}, justifyContent: 'space-between'}}>\n <CalendarNavigation direction=\"row\" spacing={1} ownSx={{alignItems: 'center'}}>\n <Tooltip title={t('previous')}>\n <IconButton aria-label={t('previous')} onClick={() => calendarApi()?.prev()}><ChevronLeftRoundedIcon /></IconButton>\n </Tooltip>\n <Tooltip title={t('next')}>\n <IconButton aria-label={t('next')} onClick={() => calendarApi()?.next()}><ChevronRightRoundedIcon /></IconButton>\n </Tooltip>\n <Button variant=\"outlined\" size=\"small\" onClick={() => calendarApi()?.today()}>{t('today')}</Button>\n <CalendarTitle variant=\"h6\" component=\"h2\" ownSx={{pl: 1}} aria-live=\"polite\">{capitalizeFirst(title)}</CalendarTitle>\n </CalendarNavigation>\n {views.length > 1 && (\n <SegmentedControl ariaLabel={t('view')} value={view} onChange={(nextView) => calendarApi()?.changeView(nextView)}\n options={views.map((value) => ({value, label: t(`views.${VIEW_TEXT_KEY[value]}`)}))} />\n )}\n </CalendarToolbar>\n <CalendarCalendar ownSx={calendarStylesOf}>\n {/* primero lo del proyecto (fullCalendarProps); lo de abajo es lo que el calendario controla y le gana */}\n <FullCalendar locale={language === 'es' ? spanishLocale : 'en'} firstDay={MONDAY} {...fullCalendarProps}\n ref={calendarRef} plugins={[dayGridPlugin, timeGridPlugin, listPlugin, interactionPlugin, ...(fullCalendarProps?.plugins ?? [])]}\n initialView={initialView} headerToolbar={false} height={height}\n nowIndicator dayMaxEvents={DAY_MAX_EVENTS} events={coloredEvents} eventDisplay=\"block\"\n eventContent={renderEvent ? (contentInfo) => renderEvent(events.find((event) => event.id === contentInfo.event.id) ?? contentInfo.event) : undefined}\n datesSet={(dateInfo) => {\n setTitle(dateInfo.view.title);\n if (dateInfo.view.type !== view) {\n onViewChange?.(dateInfo.view.type);\n }\n setView(dateInfo.view.type);\n onDatesChange?.({start: dateInfo.startStr, end: dateInfo.endStr, view: dateInfo.view.type});\n }}\n eventClick={onEventClick ? (clickInfo) => onEventClick(clickInfo.event.id) : undefined}\n selectable={Boolean(onDateSelect)} selectMirror\n select={onDateSelect ? (selectInfo) => {\n onDateSelect({start: selectInfo.startStr, end: selectInfo.endStr, allDay: selectInfo.allDay});\n calendarApi()?.unselect();\n } : undefined}\n editable={Boolean(onEventChange)} eventChange={onEventChange ? changeEvent : undefined} />\n </CalendarCalendar>\n </Stack>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EventCalendar.js","sources":["../../src/calendar/EventCalendar.jsx"],"sourcesContent":["// Un calendario de eventos (@stackcraftmx/calcita/calendar): FullCalendar por dentro, con la barra del framework (anterior y\n// siguiente, «Hoy», el título y la vista con el control segmentado) y los colores del tema. En el idioma de\n// ToolkitProvider, la semana empieza en lunes y marca la hora actual. Las citas van en bloques de su color (el color es\n// información: el tipo de cita), no en puntitos.\n//\n// <EventCalendar events={[{id: '1', title: 'Entrega P-2375', start: '2026-10-20T10:00', end: '2026-10-20T11:00', tone: 'info'}]}\n// onEventClick={openDetail} onDateSelect={openNewEvent} onEventChange={(change) => api.patch(...)} />\n//\n// Arrastrar un evento lo cambia de día u hora: onEventChange recibe lo nuevo y, si truena (el servidor dijo que no), el\n// evento regresa a donde estaba. Sin onEventChange no se puede arrastrar; sin onDateSelect no se pueden elegir días.\n//\n// Se extiende sin tocar el framework: onDatesChange avisa el rango que se ve (para que el backend mande solo esas citas),\n// onViewChange la vista, renderEvent pinta cada cita a su manera (recibe la cita tal cual, con sus campos propios),\n// fullCalendarProps pasa lo demás de FullCalendar (horario laboral, días ocultos, horas visibles…) y texts los textos. El\n// detalle de una cita para su ventana: EventDetails.\n//\n// OJO: las horas se pintan en la zona del navegador (FullCalendar pide un complemento aparte para zonas con nombre).\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaEventCalendar con defaultProps y\n// styleOverrides de sus partes: toolbar, navigation, title, calendar.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useRef, useState} from 'react';\nimport FullCalendar from '@fullcalendar/react';\nimport dayGridPlugin from '@fullcalendar/daygrid';\nimport interactionPlugin from '@fullcalendar/interaction';\nimport listPlugin from '@fullcalendar/list';\nimport timeGridPlugin from '@fullcalendar/timegrid';\nimport spanishLocale from '@fullcalendar/core/locales/es';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport IconButton from '@mui/material/IconButton';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport {useTheme} from '@mui/material/styles';\nimport ChevronLeftRoundedIcon from '@mui/icons-material/ChevronLeftRounded';\nimport ChevronRightRoundedIcon from '@mui/icons-material/ChevronRightRounded';\n\nimport {paletteOf} from '@/theme/components/paletteOf.js';\nimport {useToolkitSettings} from '@/toolkit/toolkitContext.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport SegmentedControl from '@/ui/filters/SegmentedControl.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.CalcitaEventCalendar)\nconst THEME_NAME = 'CalcitaEventCalendar';\nconst CalendarToolbar = piecePart(THEME_NAME, 'Toolbar', Stack);\nconst CalendarNavigation = piecePart(THEME_NAME, 'Navigation', Stack);\nconst CalendarTitle = piecePart(THEME_NAME, 'Title', Typography);\nconst CalendarCalendar = piecePart(THEME_NAME, 'Calendar', Box);\n\n/** Las vistas del calendario (los nombres de FullCalendar). */\nexport const CALENDAR_VIEW = Object.freeze({month: 'dayGridMonth', week: 'timeGridWeek', day: 'timeGridDay', list: 'listWeek'});\n\n// el texto de cada vista en los textos del paquete (calendar.views.*)\nconst VIEW_TEXT_KEY = Object.freeze({\n [CALENDAR_VIEW.month]: 'month', [CALENDAR_VIEW.week]: 'week', [CALENDAR_VIEW.day]: 'day', [CALENDAR_VIEW.list]: 'list',\n});\n// cuántos eventos caben en un día del mes antes del «+2 más»\nconst DAY_MAX_EVENTS = 3;\nconst MONDAY = 1;\n\n/**\n * La primera letra en mayúscula y lo demás como viene: «octubre de 2026» → «Octubre de 2026». OJO: con CSS\n * (text-transform: capitalize) salía «Octubre De 2026»: en español solo va la primera.\n *\n * @param {string} text\n * @returns {string}\n */\nfunction capitalizeFirst(text) {\n return text ? text.charAt(0).toLocaleUpperCase() + text.slice(1) : text;\n}\n\n/**\n * Los colores del calendario sobre el tema (las variables CSS de FullCalendar), en claro y en oscuro.\n *\n * @param {object} theme\n * @returns {object}\n */\nfunction calendarStylesOf(theme) {\n const palette = paletteOf(theme);\n return {\n '--fc-border-color': palette.divider,\n '--fc-page-bg-color': 'transparent',\n '--fc-neutral-bg-color': palette.action.hover,\n '--fc-today-bg-color': `color-mix(in srgb, ${palette.primary.main} 8%, transparent)`,\n '--fc-list-event-hover-bg-color': palette.action.hover,\n '--fc-now-indicator-color': palette.error.main,\n '--fc-highlight-color': `color-mix(in srgb, ${palette.primary.main} 14%, transparent)`,\n '& .fc': {fontFamily: 'inherit', fontSize: theme.typography.body2.fontSize},\n // los números de los días y los encabezados son ligas en FullCalendar: sin subrayado y del color del texto\n '& .fc a': {color: 'inherit', textDecoration: 'none'},\n '& .fc-col-header-cell-cushion': {fontWeight: 600, py: 1},\n '& .fc-event': {borderRadius: '6px', px: 0.5},\n // la hora no se encoge: en un día angosto se recortaba («1C» en lugar de «10»); lo que se corta es el nombre\n '& .fc-event-time': {flexShrink: 0, overflow: 'visible'},\n '& .fc-scrollgrid': {borderRadius: '12px', overflow: 'hidden'},\n '& .fc-list': {borderRadius: '12px'},\n };\n}\n\n/**\n * @param {object} props\n * @param {Array<{id: string, title: string, start: string, end?: string, allDay?: boolean, tone?: string}>} props.events\n * start y end como texto ISO; tone: un color del tema (por omisión primary)\n * @param {string} [props.initialView] una de CALENDAR_VIEW\n * @param {string[]} [props.views] las que se ofrecen en el control segmentado\n * @param {(eventId: string) => void} [props.onEventClick]\n * @param {(range: {start: string, end: string, allDay: boolean}) => void} [props.onDateSelect] al elegir días u horas\n * @param {(change: {id: string, start: string, end: string|null, allDay: boolean}) => Promise<unknown>|void} [props.onEventChange]\n * al arrastrar un evento; si truena, el evento regresa\n * @param {number|'auto'} [props.height]\n * @param {string} props.ariaLabel ya traducido\n * @param {(range: {start: string, end: string, view: string}) => void} [props.onDatesChange] cada que cambia lo que se ve (al\n * abrir, al ir al anterior o siguiente, al cambiar de vista): para pedir al backend solo las citas de ese rango\n * @param {(view: string) => void} [props.onViewChange] al cambiar de vista (CALENDAR_VIEW)\n * @param {(event: any) => import('react').ReactNode} [props.renderEvent] lo de adentro de cada cita (recibe la cita de events\n * tal cual, con sus campos propios)\n * @param {object} [props.fullCalendarProps] lo demás de FullCalendar (businessHours, hiddenDays, slotMinTime, locale…); lo\n * que el calendario controla (las citas, la barra, los eventos de arriba) no se reemplaza desde aquí\n * @param {object} [props.texts] los textos que cambian, con la forma de `calendar` en los textos del paquete\n */\nfunction EventCalendarContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaEventCalendar.defaultProps) y encima lo que llega aquí\n const {\n events, initialView = CALENDAR_VIEW.month, views = Object.values(CALENDAR_VIEW), onEventClick, onDateSelect, onEventChange, height = 'auto', ariaLabel,\n onDatesChange, onViewChange, renderEvent, fullCalendarProps, texts,\n ...unknownProps\n} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const theme = useTheme();\n const palette = paletteOf(theme);\n const {t} = useToolkitTranslation('calendar', texts);\n const {language} = useToolkitSettings();\n const calendarRef = useRef(null);\n const [title, setTitle] = useState('');\n const [view, setView] = useState(initialView);\n const calendarApi = () => calendarRef.current?.getApi();\n\n const coloredEvents = events.map((event) => {\n const color = palette[event.tone] ?? palette.primary;\n return {...event, backgroundColor: color.main, borderColor: color.main, textColor: color.contrastText};\n });\n\n const changeEvent = async ({event, revert}) => {\n try {\n await onEventChange({id: event.id, start: event.startStr, end: event.endStr || null, allDay: event.allDay});\n } catch {\n // el servidor dijo que no: el evento regresa a donde estaba (quien llama ya avisó el error)\n revert();\n }\n };\n\n return (\n <Stack spacing={2} role=\"region\" aria-label={ariaLabel}>\n <CalendarToolbar direction={{xs: 'column', md: 'row'}} spacing={1.5} ownSx={{alignItems: {md: 'center'}, justifyContent: 'space-between'}}>\n <CalendarNavigation direction=\"row\" spacing={1} ownSx={{alignItems: 'center'}}>\n <Tooltip title={t('previous')}>\n <IconButton aria-label={t('previous')} onClick={() => calendarApi()?.prev()}><ChevronLeftRoundedIcon /></IconButton>\n </Tooltip>\n <Tooltip title={t('next')}>\n <IconButton aria-label={t('next')} onClick={() => calendarApi()?.next()}><ChevronRightRoundedIcon /></IconButton>\n </Tooltip>\n <Button variant=\"outlined\" size=\"small\" onClick={() => calendarApi()?.today()}>{t('today')}</Button>\n <CalendarTitle variant=\"h6\" component=\"h2\" ownSx={{pl: 1}} aria-live=\"polite\">{capitalizeFirst(title)}</CalendarTitle>\n </CalendarNavigation>\n {views.length > 1 && (\n <SegmentedControl ariaLabel={t('view')} value={view} onChange={(nextView) => calendarApi()?.changeView(nextView)}\n options={views.map((value) => ({value, label: t(`views.${VIEW_TEXT_KEY[value]}`)}))} />\n )}\n </CalendarToolbar>\n <CalendarCalendar ownSx={calendarStylesOf}>\n {/* primero lo del proyecto (fullCalendarProps); lo de abajo es lo que el calendario controla y le gana */}\n <FullCalendar locale={language === 'es' ? spanishLocale : 'en'} firstDay={MONDAY} {...fullCalendarProps}\n ref={calendarRef} plugins={[dayGridPlugin, timeGridPlugin, listPlugin, interactionPlugin, ...(fullCalendarProps?.plugins ?? [])]}\n initialView={initialView} headerToolbar={false} height={height}\n nowIndicator dayMaxEvents={DAY_MAX_EVENTS} events={coloredEvents} eventDisplay=\"block\"\n eventContent={renderEvent ? (contentInfo) => renderEvent(events.find((event) => event.id === contentInfo.event.id) ?? contentInfo.event) : undefined}\n datesSet={(dateInfo) => {\n setTitle(dateInfo.view.title);\n if (dateInfo.view.type !== view) {\n onViewChange?.(dateInfo.view.type);\n }\n setView(dateInfo.view.type);\n onDatesChange?.({start: dateInfo.startStr, end: dateInfo.endStr, view: dateInfo.view.type});\n }}\n eventClick={onEventClick ? (clickInfo) => onEventClick(clickInfo.event.id) : undefined}\n selectable={Boolean(onDateSelect)} selectMirror\n select={onDateSelect ? (selectInfo) => {\n onDateSelect({start: selectInfo.startStr, end: selectInfo.endStr, allDay: selectInfo.allDay});\n calendarApi()?.unselect();\n } : undefined}\n editable={Boolean(onEventChange)} eventChange={onEventChange ? changeEvent : undefined} />\n </CalendarCalendar>\n </Stack>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst EventCalendar = withPieceSlots(EventCalendarContent, THEME_NAME);\nexport default EventCalendar;\n"],"names":[],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ import { initialsOf } from "../appShell/menuItemText.js";
|
|
|
16
16
|
import { reminderOf, isOpenableMeetingUrl, REMINDER_UNIT } from "./calendarEvents.js";
|
|
17
17
|
import { useFormatters } from "../toolkit/useFormatters.js";
|
|
18
18
|
import { useToolkitTranslation } from "../toolkit/useToolkitTranslation.js";
|
|
19
|
-
import { piecePart, usePieceProps } from "../theme/themePieces.js";
|
|
19
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
|
|
20
20
|
import { warnUnknownProps } from "../toolkit/unknownProps.js";
|
|
21
21
|
const THEME_NAME = "CalcitaEventDetails";
|
|
22
22
|
const EventRow = piecePart(THEME_NAME, "Row", Stack);
|
|
@@ -45,7 +45,7 @@ function DetailRow({ Icon, label, children }) {
|
|
|
45
45
|
/* @__PURE__ */ jsx(EventRowContent, { ownSx: { minWidth: 0, flexGrow: 1 }, children })
|
|
46
46
|
] });
|
|
47
47
|
}
|
|
48
|
-
function
|
|
48
|
+
function EventDetailsContent(props) {
|
|
49
49
|
const { event, actions, titleId, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
50
50
|
warnUnknownProps(THEME_NAME, unknownProps);
|
|
51
51
|
const { t } = useToolkitTranslation("calendar", texts);
|
|
@@ -84,6 +84,7 @@ function EventDetails(props) {
|
|
|
84
84
|
actions && /* @__PURE__ */ jsx(EventActions, { direction: "row", spacing: 1, useFlexGap: true, ownSx: { justifyContent: "flex-end", flexWrap: "wrap" }, children: actions })
|
|
85
85
|
] });
|
|
86
86
|
}
|
|
87
|
+
const EventDetails = withPieceSlots(EventDetailsContent, THEME_NAME);
|
|
87
88
|
export {
|
|
88
89
|
ATTENDEE_RESPONSE,
|
|
89
90
|
EventDetails as default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EventDetails.js","sources":["../../src/calendar/EventDetails.jsx"],"sourcesContent":["// El detalle de una cita, para la ventana que se abre al picarla en el calendario: su título con el color de su tipo,\n// cuándo (el día y las horas), dónde, la liga de la reunión con «Unirse», los invitados con su respuesta, el recordatorio y\n// las notas. Pinta lo que la cita traiga; lo que no trae no ocupa lugar.\n//\n// <EventDetails event={{title: 'Junta de cierre', start: '2026-10-20T10:00', end: '2026-10-20T11:00', location: 'Sala 2',\n// meetingUrl: 'https://meet.example.com/abc', attendees: [{id: 'ana', name: 'Ana', response: 'accepted'}],\n// reminderMinutes: 15}}\n// actions={<Button onClick={edit}>Editar</Button>} />\n//\n// No llama a ningún servidor ni abre la reunión por su cuenta: «Unirse» es una liga (solo http o https) y lo demás lo pone la\n// pantalla en actions. Sus textos se cambian con texts (la forma de `calendar` en los textos del paquete).\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaEventDetails con defaultProps y\n// styleOverrides de sus partes: row, rowContent, titleRow, toneDot, linkRow, link, guestsTitle, guest, guestAvatar,\n// guestName, notes, actions.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Avatar from '@mui/material/Avatar';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Chip from '@mui/material/Chip';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport AccessTimeRoundedIcon from '@mui/icons-material/AccessTimeRounded';\nimport NotesRoundedIcon from '@mui/icons-material/NotesRounded';\nimport NotificationsNoneRoundedIcon from '@mui/icons-material/NotificationsNoneRounded';\nimport PeopleOutlineRoundedIcon from '@mui/icons-material/PeopleOutlineRounded';\nimport PlaceOutlinedIcon from '@mui/icons-material/PlaceOutlined';\nimport VideocamOutlinedIcon from '@mui/icons-material/VideocamOutlined';\n\nimport {initialsOf} from '@/appShell/menuItemText.js';\nimport {REMINDER_UNIT, isOpenableMeetingUrl, reminderOf} from '@/calendar/calendarEvents.js';\nimport {useFormatters} from '@/toolkit/useFormatters.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.CalcitaEventDetails)\nconst THEME_NAME = 'CalcitaEventDetails';\nconst EventRow = piecePart(THEME_NAME, 'Row', Stack);\nconst EventRowContent = piecePart(THEME_NAME, 'RowContent', Box);\nconst EventTitleRow = piecePart(THEME_NAME, 'TitleRow', Stack);\nconst EventToneDot = piecePart(THEME_NAME, 'ToneDot', Box);\nconst EventLinkRow = piecePart(THEME_NAME, 'LinkRow', Stack);\nconst EventLink = piecePart(THEME_NAME, 'Link', Typography);\nconst EventGuestsTitle = piecePart(THEME_NAME, 'GuestsTitle', Typography);\nconst EventGuest = piecePart(THEME_NAME, 'Guest', Stack);\nconst EventGuestAvatar = piecePart(THEME_NAME, 'GuestAvatar', Avatar);\nconst EventGuestName = piecePart(THEME_NAME, 'GuestName', Typography);\nconst EventNotes = piecePart(THEME_NAME, 'Notes', Typography);\nconst EventActions = piecePart(THEME_NAME, 'Actions', Stack);\n\n/** Las respuestas de un invitado. */\nexport const ATTENDEE_RESPONSE = Object.freeze({accepted: 'accepted', declined: 'declined', pending: 'pending'});\n// el color de cada respuesta (el color es información: verde va, rojo no va, gris no ha contestado)\nconst RESPONSE_COLOR = Object.freeze({\n [ATTENDEE_RESPONSE.accepted]: 'success', [ATTENDEE_RESPONSE.declined]: 'error', [ATTENDEE_RESPONSE.pending]: 'default',\n});\n// un día completo viene sin hora («2026-10-20»)\nconst WHOLE_DAY_PATTERN = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst ICON_SIZE = 20;\n\n/** Un renglón del detalle: su ícono a la izquierda y lo de adentro. */\nfunction DetailRow({Icon, label, children}) {\n return (\n <EventRow direction=\"row\" spacing={1.5} ownSx={{alignItems: 'flex-start'}} aria-label={label} role=\"group\">\n <Icon sx={{fontSize: ICON_SIZE, color: 'text.secondary', mt: 0.25}} aria-hidden=\"true\" />\n <EventRowContent ownSx={{minWidth: 0, flexGrow: 1}}>{children}</EventRowContent>\n </EventRow>\n );\n}\n\n/**\n * @param {object} props\n * @param {{title: string, start: string, end?: string|null, allDay?: boolean, tone?: string, location?: string, meetingUrl?: string, attendees?: Array<{id: string, name: string, email?: string, response?: 'accepted'|'declined'|'pending'}>, reminderMinutes?: number|null, description?: string}} props.event\n * start y end como texto ISO (o AAAA-MM-DD un día completo); tone: el color de su tipo\n * @param {import('react').ReactNode} [props.actions] botones de la pantalla (editar, borrar, responder…)\n * @param {string} [props.titleId] el id del título: la ventana que lo contiene se nombra con él (aria-labelledby)\n * @param {object} [props.texts] los textos que cambian, con la forma de `calendar` en los textos del paquete\n */\nexport default function EventDetails(props) {\n // lo que el proyecto puso en su tema (components.CalcitaEventDetails.defaultProps) y encima lo que llega aquí\n const {event, actions, titleId, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('calendar', texts);\n const {formatDate, formatTime} = useFormatters();\n const isWholeDay = event.allDay || WHOLE_DAY_PATTERN.test(event.start);\n let when = formatDate(event.start);\n if (!isWholeDay) {\n when = t('details.timeRange', {date: formatDate(event.start), start: formatTime(event.start), end: event.end ? formatTime(event.end) : ''});\n }\n const reminder = reminderOf(event.reminderMinutes);\n const canJoin = isOpenableMeetingUrl(event.meetingUrl);\n\n return (\n <Stack spacing={2}>\n <EventTitleRow direction=\"row\" spacing={1.5} ownSx={{alignItems: 'center'}}>\n <EventToneDot aria-hidden=\"true\" ownSx={{width: 12, height: 12, borderRadius: '4px', flexShrink: 0, bgcolor: `${event.tone ?? 'primary'}.main`}} />\n <Typography id={titleId} variant=\"h6\" component=\"h2\">{event.title}</Typography>\n </EventTitleRow>\n <DetailRow Icon={AccessTimeRoundedIcon} label={t('details.when')}>\n <Typography variant=\"body2\">{isWholeDay ? t('details.allDay', {date: when}) : when}</Typography>\n </DetailRow>\n {event.location && (\n <DetailRow Icon={PlaceOutlinedIcon} label={t('details.location')}>\n <Typography variant=\"body2\">{event.location}</Typography>\n </DetailRow>\n )}\n {event.meetingUrl && (\n <DetailRow Icon={VideocamOutlinedIcon} label={t('details.meeting')}>\n <EventLinkRow direction=\"row\" spacing={1} ownSx={{alignItems: 'center', flexWrap: 'wrap'}} useFlexGap>\n {canJoin && (\n <Button variant=\"contained\" size=\"small\" href={event.meetingUrl} target=\"_blank\" rel=\"noreferrer\">{t('details.join')}</Button>\n )}\n <EventLink variant=\"caption\" color=\"text.secondary\" ownSx={{wordBreak: 'break-all'}}>{event.meetingUrl}</EventLink>\n </EventLinkRow>\n </DetailRow>\n )}\n {event.attendees?.length > 0 && (\n <DetailRow Icon={PeopleOutlineRoundedIcon} label={t('details.attendees')}>\n <EventGuestsTitle variant=\"body2\" ownSx={{mb: 0.75}}>{t('details.attendeesCount', {count: event.attendees.length})}</EventGuestsTitle>\n <Stack spacing={0.75}>\n {event.attendees.map((attendee) => {\n const response = attendee.response ?? ATTENDEE_RESPONSE.pending;\n return (\n <EventGuest key={attendee.id} direction=\"row\" spacing={1} ownSx={{alignItems: 'center'}}>\n <EventGuestAvatar ownSx={{width: 24, height: 24, fontSize: 11}}>{initialsOf(attendee.name)}</EventGuestAvatar>\n <EventGuestName variant=\"body2\" ownSx={{flexGrow: 1, minWidth: 0}} noWrap>{attendee.name}</EventGuestName>\n <Chip size=\"small\" variant=\"outlined\" color={RESPONSE_COLOR[response] ?? 'default'} label={t(`details.response.${response}`)} />\n </EventGuest>\n );\n })}\n </Stack>\n </DetailRow>\n )}\n {reminder.unit !== REMINDER_UNIT.none && (\n <DetailRow Icon={NotificationsNoneRoundedIcon} label={t('details.reminder')}>\n <Typography variant=\"body2\">{t(`details.reminderUnit.${reminder.unit}`, {count: reminder.count})}</Typography>\n </DetailRow>\n )}\n {event.description && (\n <DetailRow Icon={NotesRoundedIcon} label={t('details.notes')}>\n <EventNotes variant=\"body2\" ownSx={{whiteSpace: 'pre-wrap'}}>{event.description}</EventNotes>\n </DetailRow>\n )}\n {actions && <EventActions direction=\"row\" spacing={1} useFlexGap ownSx={{justifyContent: 'flex-end', flexWrap: 'wrap'}}>{actions}</EventActions>}\n </Stack>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EventDetails.js","sources":["../../src/calendar/EventDetails.jsx"],"sourcesContent":["// El detalle de una cita, para la ventana que se abre al picarla en el calendario: su título con el color de su tipo,\n// cuándo (el día y las horas), dónde, la liga de la reunión con «Unirse», los invitados con su respuesta, el recordatorio y\n// las notas. Pinta lo que la cita traiga; lo que no trae no ocupa lugar.\n//\n// <EventDetails event={{title: 'Junta de cierre', start: '2026-10-20T10:00', end: '2026-10-20T11:00', location: 'Sala 2',\n// meetingUrl: 'https://meet.example.com/abc', attendees: [{id: 'ana', name: 'Ana', response: 'accepted'}],\n// reminderMinutes: 15}}\n// actions={<Button onClick={edit}>Editar</Button>} />\n//\n// No llama a ningún servidor ni abre la reunión por su cuenta: «Unirse» es una liga (solo http o https) y lo demás lo pone la\n// pantalla en actions. Sus textos se cambian con texts (la forma de `calendar` en los textos del paquete).\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaEventDetails con defaultProps y\n// styleOverrides de sus partes: row, rowContent, titleRow, toneDot, linkRow, link, guestsTitle, guest, guestAvatar,\n// guestName, notes, actions.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Avatar from '@mui/material/Avatar';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Chip from '@mui/material/Chip';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport AccessTimeRoundedIcon from '@mui/icons-material/AccessTimeRounded';\nimport NotesRoundedIcon from '@mui/icons-material/NotesRounded';\nimport NotificationsNoneRoundedIcon from '@mui/icons-material/NotificationsNoneRounded';\nimport PeopleOutlineRoundedIcon from '@mui/icons-material/PeopleOutlineRounded';\nimport PlaceOutlinedIcon from '@mui/icons-material/PlaceOutlined';\nimport VideocamOutlinedIcon from '@mui/icons-material/VideocamOutlined';\n\nimport {initialsOf} from '@/appShell/menuItemText.js';\nimport {REMINDER_UNIT, isOpenableMeetingUrl, reminderOf} from '@/calendar/calendarEvents.js';\nimport {useFormatters} from '@/toolkit/useFormatters.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.CalcitaEventDetails)\nconst THEME_NAME = 'CalcitaEventDetails';\nconst EventRow = piecePart(THEME_NAME, 'Row', Stack);\nconst EventRowContent = piecePart(THEME_NAME, 'RowContent', Box);\nconst EventTitleRow = piecePart(THEME_NAME, 'TitleRow', Stack);\nconst EventToneDot = piecePart(THEME_NAME, 'ToneDot', Box);\nconst EventLinkRow = piecePart(THEME_NAME, 'LinkRow', Stack);\nconst EventLink = piecePart(THEME_NAME, 'Link', Typography);\nconst EventGuestsTitle = piecePart(THEME_NAME, 'GuestsTitle', Typography);\nconst EventGuest = piecePart(THEME_NAME, 'Guest', Stack);\nconst EventGuestAvatar = piecePart(THEME_NAME, 'GuestAvatar', Avatar);\nconst EventGuestName = piecePart(THEME_NAME, 'GuestName', Typography);\nconst EventNotes = piecePart(THEME_NAME, 'Notes', Typography);\nconst EventActions = piecePart(THEME_NAME, 'Actions', Stack);\n\n/** Las respuestas de un invitado. */\nexport const ATTENDEE_RESPONSE = Object.freeze({accepted: 'accepted', declined: 'declined', pending: 'pending'});\n// el color de cada respuesta (el color es información: verde va, rojo no va, gris no ha contestado)\nconst RESPONSE_COLOR = Object.freeze({\n [ATTENDEE_RESPONSE.accepted]: 'success', [ATTENDEE_RESPONSE.declined]: 'error', [ATTENDEE_RESPONSE.pending]: 'default',\n});\n// un día completo viene sin hora («2026-10-20»)\nconst WHOLE_DAY_PATTERN = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst ICON_SIZE = 20;\n\n/** Un renglón del detalle: su ícono a la izquierda y lo de adentro. */\nfunction DetailRow({Icon, label, children}) {\n return (\n <EventRow direction=\"row\" spacing={1.5} ownSx={{alignItems: 'flex-start'}} aria-label={label} role=\"group\">\n <Icon sx={{fontSize: ICON_SIZE, color: 'text.secondary', mt: 0.25}} aria-hidden=\"true\" />\n <EventRowContent ownSx={{minWidth: 0, flexGrow: 1}}>{children}</EventRowContent>\n </EventRow>\n );\n}\n\n/**\n * @param {object} props\n * @param {{title: string, start: string, end?: string|null, allDay?: boolean, tone?: string, location?: string, meetingUrl?: string, attendees?: Array<{id: string, name: string, email?: string, response?: 'accepted'|'declined'|'pending'}>, reminderMinutes?: number|null, description?: string}} props.event\n * start y end como texto ISO (o AAAA-MM-DD un día completo); tone: el color de su tipo\n * @param {import('react').ReactNode} [props.actions] botones de la pantalla (editar, borrar, responder…)\n * @param {string} [props.titleId] el id del título: la ventana que lo contiene se nombra con él (aria-labelledby)\n * @param {object} [props.texts] los textos que cambian, con la forma de `calendar` en los textos del paquete\n */\nfunction EventDetailsContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaEventDetails.defaultProps) y encima lo que llega aquí\n const {event, actions, titleId, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('calendar', texts);\n const {formatDate, formatTime} = useFormatters();\n const isWholeDay = event.allDay || WHOLE_DAY_PATTERN.test(event.start);\n let when = formatDate(event.start);\n if (!isWholeDay) {\n when = t('details.timeRange', {date: formatDate(event.start), start: formatTime(event.start), end: event.end ? formatTime(event.end) : ''});\n }\n const reminder = reminderOf(event.reminderMinutes);\n const canJoin = isOpenableMeetingUrl(event.meetingUrl);\n\n return (\n <Stack spacing={2}>\n <EventTitleRow direction=\"row\" spacing={1.5} ownSx={{alignItems: 'center'}}>\n <EventToneDot aria-hidden=\"true\" ownSx={{width: 12, height: 12, borderRadius: '4px', flexShrink: 0, bgcolor: `${event.tone ?? 'primary'}.main`}} />\n <Typography id={titleId} variant=\"h6\" component=\"h2\">{event.title}</Typography>\n </EventTitleRow>\n <DetailRow Icon={AccessTimeRoundedIcon} label={t('details.when')}>\n <Typography variant=\"body2\">{isWholeDay ? t('details.allDay', {date: when}) : when}</Typography>\n </DetailRow>\n {event.location && (\n <DetailRow Icon={PlaceOutlinedIcon} label={t('details.location')}>\n <Typography variant=\"body2\">{event.location}</Typography>\n </DetailRow>\n )}\n {event.meetingUrl && (\n <DetailRow Icon={VideocamOutlinedIcon} label={t('details.meeting')}>\n <EventLinkRow direction=\"row\" spacing={1} ownSx={{alignItems: 'center', flexWrap: 'wrap'}} useFlexGap>\n {canJoin && (\n <Button variant=\"contained\" size=\"small\" href={event.meetingUrl} target=\"_blank\" rel=\"noreferrer\">{t('details.join')}</Button>\n )}\n <EventLink variant=\"caption\" color=\"text.secondary\" ownSx={{wordBreak: 'break-all'}}>{event.meetingUrl}</EventLink>\n </EventLinkRow>\n </DetailRow>\n )}\n {event.attendees?.length > 0 && (\n <DetailRow Icon={PeopleOutlineRoundedIcon} label={t('details.attendees')}>\n <EventGuestsTitle variant=\"body2\" ownSx={{mb: 0.75}}>{t('details.attendeesCount', {count: event.attendees.length})}</EventGuestsTitle>\n <Stack spacing={0.75}>\n {event.attendees.map((attendee) => {\n const response = attendee.response ?? ATTENDEE_RESPONSE.pending;\n return (\n <EventGuest key={attendee.id} direction=\"row\" spacing={1} ownSx={{alignItems: 'center'}}>\n <EventGuestAvatar ownSx={{width: 24, height: 24, fontSize: 11}}>{initialsOf(attendee.name)}</EventGuestAvatar>\n <EventGuestName variant=\"body2\" ownSx={{flexGrow: 1, minWidth: 0}} noWrap>{attendee.name}</EventGuestName>\n <Chip size=\"small\" variant=\"outlined\" color={RESPONSE_COLOR[response] ?? 'default'} label={t(`details.response.${response}`)} />\n </EventGuest>\n );\n })}\n </Stack>\n </DetailRow>\n )}\n {reminder.unit !== REMINDER_UNIT.none && (\n <DetailRow Icon={NotificationsNoneRoundedIcon} label={t('details.reminder')}>\n <Typography variant=\"body2\">{t(`details.reminderUnit.${reminder.unit}`, {count: reminder.count})}</Typography>\n </DetailRow>\n )}\n {event.description && (\n <DetailRow Icon={NotesRoundedIcon} label={t('details.notes')}>\n <EventNotes variant=\"body2\" ownSx={{whiteSpace: 'pre-wrap'}}>{event.description}</EventNotes>\n </DetailRow>\n )}\n {actions && <EventActions direction=\"row\" spacing={1} useFlexGap ownSx={{justifyContent: 'flex-end', flexWrap: 'wrap'}}>{actions}</EventActions>}\n </Stack>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst EventDetails = withPieceSlots(EventDetailsContent, THEME_NAME);\nexport default EventDetails;\n"],"names":[],"mappings":"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"}
|
|
@@ -6,32 +6,37 @@ import PickerFrame, { textFieldSlotPropsOf } from "./PickerFrame.js";
|
|
|
6
6
|
import { CALENDAR_DATE_FORMAT } from "./pickerValues.js";
|
|
7
7
|
import { usePickerField } from "./usePickerField.js";
|
|
8
8
|
import { warnUnknownProps } from "../toolkit/unknownProps.js";
|
|
9
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
|
|
10
|
+
const THEME_NAME = "CalcitaDateInput";
|
|
11
|
+
const DateInputPicker = piecePart(THEME_NAME, "Picker", DatePicker);
|
|
9
12
|
function pickerValueOf(calendarDate) {
|
|
10
13
|
return calendarDate ? dayjs(calendarDate) : null;
|
|
11
14
|
}
|
|
12
|
-
function
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
15
|
+
function DateInputContent(props) {
|
|
16
|
+
const {
|
|
17
|
+
name,
|
|
18
|
+
label,
|
|
19
|
+
value,
|
|
20
|
+
onChange,
|
|
21
|
+
onBlur,
|
|
22
|
+
error,
|
|
23
|
+
helperText = " ",
|
|
24
|
+
minDate,
|
|
25
|
+
maxDate,
|
|
26
|
+
disableFuture = false,
|
|
27
|
+
disablePast = false,
|
|
28
|
+
openTo = "day",
|
|
29
|
+
disabled = false,
|
|
30
|
+
inputRef,
|
|
31
|
+
pickerProps,
|
|
32
|
+
messages,
|
|
33
|
+
texts,
|
|
34
|
+
...unknownProps
|
|
35
|
+
} = usePieceProps(props, THEME_NAME);
|
|
36
|
+
warnUnknownProps(THEME_NAME, unknownProps);
|
|
37
|
+
const { language, inputId, errorText, formats } = usePickerField({ name, kind: "date", error, label, messages, texts });
|
|
33
38
|
return /* @__PURE__ */ jsx(PickerFrame, { inputId, label, language, children: /* @__PURE__ */ jsx(
|
|
34
|
-
|
|
39
|
+
DateInputPicker,
|
|
35
40
|
{
|
|
36
41
|
...pickerProps,
|
|
37
42
|
format: formats.date,
|
|
@@ -53,6 +58,7 @@ function DateInput({
|
|
|
53
58
|
}
|
|
54
59
|
) });
|
|
55
60
|
}
|
|
61
|
+
const DateInput = withPieceSlots(DateInputContent, THEME_NAME);
|
|
56
62
|
export {
|
|
57
63
|
CALENDAR_DATE_FORMAT,
|
|
58
64
|
DateInput as default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateInput.js","sources":["../../src/datePickers/DateInput.jsx"],"sourcesContent":["// Campo de FECHA suelto con el DatePicker de MUI X (@stackcraftmx/calcita/date-pickers), con la etiqueta arriba como los\n// demás campos del paquete.\n//\n// Al formulario (y al servidor) viaja la fecha de calendario 'AAAA-MM-DD' en texto; en pantalla se ve DD/MM/AAAA en español\n// y MM/DD/AAAA en inglés, con el calendario y sus textos en el idioma activo. '' = sin fecha. Una fecha de calendario no\n// tiene hora ni zona: nunca se pasa por Date (que la movería de día según la zona).\n//\n// Cada campo trae su LocalizationProvider con dayjs (PickerFrame): la pantalla no tiene que poner nada alrededor.\n//\n// Genérico del paquete: function (regla de la casa).\nimport dayjs from 'dayjs';\nimport {DatePicker} from '@mui/x-date-pickers/DatePicker';\n\nimport PickerFrame, {textFieldSlotPropsOf} from '@/datePickers/PickerFrame.jsx';\nimport {CALENDAR_DATE_FORMAT} from '@/datePickers/pickerValues.js';\nimport {usePickerField} from '@/datePickers/usePickerField.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\nexport {CALENDAR_DATE_FORMAT};\n\n/**\n * Una fecha de calendario 'AAAA-MM-DD' como la quiere el DatePicker; null si está vacía.\n *\n * @param {string|null|undefined} calendarDate\n * @returns {import('dayjs').Dayjs|null}\n */\nfunction pickerValueOf(calendarDate) {\n // dayjs lee 'AAAA-MM-DD' como día local (a diferencia de new Date, que lo toma en UTC y lo mueve de día)\n return calendarDate ? dayjs(calendarDate) : null;\n}\n\n/**\n * @param {object} props\n * @param {string} [props.name]\n * @param {string} props.label ya traducido\n * @param {string|null|undefined} props.value 'AAAA-MM-DD' o ''\n * @param {(value: string) => void} props.onChange recibe 'AAAA-MM-DD' ('' al borrar o con una fecha a medias)\n * @param {() => void} [props.onBlur]\n * @param {string|{key: string, values?: object}} [props.error]\n * @param {string} [props.helperText]\n * @param {string} [props.minDate] 'AAAA-MM-DD'\n * @param {string} [props.maxDate] 'AAAA-MM-DD'\n * @param {boolean} [props.disableFuture] p. ej. una fecha de nacimiento\n * @param {boolean} [props.disablePast] p. ej. una cita\n * @param {'day'|'month'|'year'} [props.openTo] por dónde abre el calendario (year para un nacimiento)\n * @param {boolean} [props.disabled]\n * @param {import('react').Ref<HTMLInputElement>} [props.inputRef]\n * @param {object} [props.pickerProps] lo demás del DatePicker de MUI X que aquí no tiene nombre (shouldDisableDate, slots,\n * slotProps…); value y onChange son del campo\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\
|
|
1
|
+
{"version":3,"file":"DateInput.js","sources":["../../src/datePickers/DateInput.jsx"],"sourcesContent":["// Campo de FECHA suelto con el DatePicker de MUI X (@stackcraftmx/calcita/date-pickers), con la etiqueta arriba como los\n// demás campos del paquete.\n//\n// Al formulario (y al servidor) viaja la fecha de calendario 'AAAA-MM-DD' en texto; en pantalla se ve DD/MM/AAAA en español\n// y MM/DD/AAAA en inglés, con el calendario y sus textos en el idioma activo. '' = sin fecha. Una fecha de calendario no\n// tiene hora ni zona: nunca se pasa por Date (que la movería de día según la zona).\n//\n// Cada campo trae su LocalizationProvider con dayjs (PickerFrame): la pantalla no tiene que poner nada alrededor.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaDateInput con defaultProps, styleOverrides de\n// sus partes (picker) y slots/slotProps para cambiarlas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport dayjs from 'dayjs';\nimport {DatePicker} from '@mui/x-date-pickers/DatePicker';\n\nimport PickerFrame, {textFieldSlotPropsOf} from '@/datePickers/PickerFrame.jsx';\nimport {CALENDAR_DATE_FORMAT} from '@/datePickers/pickerValues.js';\nimport {usePickerField} from '@/datePickers/usePickerField.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaDateInput)\nconst THEME_NAME = 'CalcitaDateInput';\nconst DateInputPicker = piecePart(THEME_NAME, 'Picker', DatePicker);\n\nexport {CALENDAR_DATE_FORMAT};\n\n/**\n * Una fecha de calendario 'AAAA-MM-DD' como la quiere el DatePicker; null si está vacía.\n *\n * @param {string|null|undefined} calendarDate\n * @returns {import('dayjs').Dayjs|null}\n */\nfunction pickerValueOf(calendarDate) {\n // dayjs lee 'AAAA-MM-DD' como día local (a diferencia de new Date, que lo toma en UTC y lo mueve de día)\n return calendarDate ? dayjs(calendarDate) : null;\n}\n\n/**\n * @param {object} props\n * @param {string} [props.name]\n * @param {string} props.label ya traducido\n * @param {string|null|undefined} props.value 'AAAA-MM-DD' o ''\n * @param {(value: string) => void} props.onChange recibe 'AAAA-MM-DD' ('' al borrar o con una fecha a medias)\n * @param {() => void} [props.onBlur]\n * @param {string|{key: string, values?: object}} [props.error]\n * @param {string} [props.helperText]\n * @param {string} [props.minDate] 'AAAA-MM-DD'\n * @param {string} [props.maxDate] 'AAAA-MM-DD'\n * @param {boolean} [props.disableFuture] p. ej. una fecha de nacimiento\n * @param {boolean} [props.disablePast] p. ej. una cita\n * @param {'day'|'month'|'year'} [props.openTo] por dónde abre el calendario (year para un nacimiento)\n * @param {boolean} [props.disabled]\n * @param {import('react').Ref<HTMLInputElement>} [props.inputRef]\n * @param {object} [props.pickerProps] lo demás del DatePicker de MUI X que aquí no tiene nombre (shouldDisableDate, slots,\n * slotProps…); value y onChange son del campo\n * @param {Record<string, string|object>} [props.messages] el texto del error de este campo, por regla de validación\n * ({required: 'Elija la fecha', min: 'Desde mañana'}): gana al de Calcita y al de los textos\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction DateInputContent(props) {\n const {\n name, label, value, onChange, onBlur, error, helperText = ' ', minDate, maxDate, disableFuture = false, disablePast = false,\n openTo = 'day', disabled = false, inputRef, pickerProps, messages, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {language, inputId, errorText, formats} = usePickerField({name, kind: 'date', error, label, messages, texts});\n\n return (\n <PickerFrame inputId={inputId} label={label} language={language}>\n <DateInputPicker\n {...pickerProps}\n format={formats.date}\n value={pickerValueOf(value)}\n minDate={pickerValueOf(minDate) ?? undefined}\n maxDate={pickerValueOf(maxDate) ?? undefined}\n disableFuture={disableFuture}\n disablePast={disablePast}\n disabled={disabled}\n openTo={openTo}\n views={openTo === 'year' ? ['year', 'month', 'day'] : pickerProps?.views}\n inputRef={inputRef}\n // una fecha a medias (25/1_/____) todavía no es fecha: viaja como vacía hasta que se complete\n onChange={(pickedDate) => onChange(pickedDate?.isValid() ? pickedDate.format(CALENDAR_DATE_FORMAT) : '')}\n onClose={() => {\n pickerProps?.onClose?.();\n onBlur?.();\n }}\n slotProps={textFieldSlotPropsOf({id: inputId, name, onBlur, error: Boolean(errorText), helperText: errorText ?? helperText}, pickerProps)}\n />\n </PickerFrame>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst DateInput = withPieceSlots(DateInputContent, THEME_NAME);\nexport default DateInput;\n"],"names":[],"mappings":";;;;;;;;;AAuBA,MAAM,aAAa;AACnB,MAAM,kBAAkB,UAAU,YAAY,UAAU,UAAU;AAUlE,SAAS,cAAc,cAAc;AAEjC,SAAO,eAAe,MAAM,YAAY,IAAI;AAChD;AAwBA,SAAS,iBAAiB,OAAO;AAC7B,QAAM;AAAA,IACF;AAAA,IAAM;AAAA,IAAO;AAAA,IAAO;AAAA,IAAU;AAAA,IAAQ;AAAA,IAAO,aAAa;AAAA,IAAK;AAAA,IAAS;AAAA,IAAS,gBAAgB;AAAA,IAAO,cAAc;AAAA,IACtH,SAAS;AAAA,IAAO,WAAW;AAAA,IAAO;AAAA,IAAU;AAAA,IAAa;AAAA,IAAU;AAAA,IACnE,GAAG;AAAA,EAAA,IACH,cAAc,OAAO,UAAU;AACnC,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,UAAU,SAAS,WAAW,YAAW,eAAe,EAAC,MAAM,MAAM,QAAQ,OAAO,OAAO,UAAU,OAAM;AAElH,SACI,oBAAC,aAAA,EAAY,SAAkB,OAAc,UACzC,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACI,GAAG;AAAA,MACJ,QAAQ,QAAQ;AAAA,MAChB,OAAO,cAAc,KAAK;AAAA,MAC1B,SAAS,cAAc,OAAO,KAAK;AAAA,MACnC,SAAS,cAAc,OAAO,KAAK;AAAA,MACnC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,WAAW,SAAS,CAAC,QAAQ,SAAS,KAAK,IAAI,aAAa;AAAA,MACnE;AAAA,MAEA,UAAU,CAAC,eAAe,SAAS,YAAY,YAAY,WAAW,OAAO,oBAAoB,IAAI,EAAE;AAAA,MACvG,SAAS,MAAM;AACX,qBAAa,UAAA;AACb,iBAAA;AAAA,MACJ;AAAA,MACA,WAAW,qBAAqB,EAAC,IAAI,SAAS,MAAM,QAAQ,OAAO,QAAQ,SAAS,GAAG,YAAY,aAAa,WAAA,GAAa,WAAW;AAAA,IAAA;AAAA,EAAA,GAEhJ;AAER;AAGA,MAAM,YAAY,eAAe,kBAAkB,UAAU;"}
|
|
@@ -2,38 +2,43 @@
|
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import { DateTimePicker } from "@mui/x-date-pickers/DateTimePicker";
|
|
4
4
|
import PickerFrame, { textFieldSlotPropsOf } from "./PickerFrame.js";
|
|
5
|
-
import { timeZoneNameOf, latestInstantOf, earliestInstantFromNow,
|
|
5
|
+
import { DEFAULT_MINUTES_STEP, timeZoneNameOf, latestInstantOf, earliestInstantFromNow, instantTextOf, pickerInstantOf } from "./pickerValues.js";
|
|
6
6
|
import { useCurrentMinute } from "./useCurrentMinute.js";
|
|
7
7
|
import { usePickerField } from "./usePickerField.js";
|
|
8
8
|
import { intlLocaleOf } from "../toolkit/toolkitSettings.js";
|
|
9
9
|
import { useToolkitSettings } from "../toolkit/toolkitContext.js";
|
|
10
10
|
import { warnUnknownProps } from "../toolkit/unknownProps.js";
|
|
11
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../theme/themePieces.js";
|
|
12
|
+
const THEME_NAME = "CalcitaDateTimeInput";
|
|
13
|
+
const DateTimeInputPicker = piecePart(THEME_NAME, "Picker", DateTimePicker);
|
|
11
14
|
const HELPER_SEPARATOR = " · ";
|
|
12
|
-
function
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
15
|
+
function DateTimeInputContent(props) {
|
|
16
|
+
const {
|
|
17
|
+
name,
|
|
18
|
+
label,
|
|
19
|
+
value,
|
|
20
|
+
onChange,
|
|
21
|
+
onBlur,
|
|
22
|
+
error,
|
|
23
|
+
helperText,
|
|
24
|
+
minDateTime,
|
|
25
|
+
minimumMinutesFromNow,
|
|
26
|
+
maxDateTime,
|
|
27
|
+
disableFuture = false,
|
|
28
|
+
disablePast = false,
|
|
29
|
+
minutesStep = DEFAULT_MINUTES_STEP,
|
|
30
|
+
timeZone,
|
|
31
|
+
showTimeZone = true,
|
|
32
|
+
timeZoneLabel,
|
|
33
|
+
disabled = false,
|
|
34
|
+
inputRef,
|
|
35
|
+
pickerProps,
|
|
36
|
+
messages,
|
|
37
|
+
texts,
|
|
38
|
+
...unknownProps
|
|
39
|
+
} = usePieceProps(props, THEME_NAME);
|
|
40
|
+
warnUnknownProps(THEME_NAME, unknownProps);
|
|
41
|
+
const field = usePickerField({ name, kind: "dateTime", error, label, messages, texts });
|
|
37
42
|
const { languages } = useToolkitSettings();
|
|
38
43
|
const shownTimeZone = timeZone ?? field.timeZone;
|
|
39
44
|
const zoneText = showTimeZone ? timeZoneLabel ?? timeZoneNameOf(shownTimeZone, intlLocaleOf(field.language, languages)) : null;
|
|
@@ -42,7 +47,7 @@ function DateTimeInput({
|
|
|
42
47
|
const currentMinute = useCurrentMinute(hasClockRule);
|
|
43
48
|
const earliest = latestInstantOf(minDateTime, hasClockRule ? earliestInstantFromNow(minimumMinutesFromNow, currentMinute) : "");
|
|
44
49
|
return /* @__PURE__ */ jsx(PickerFrame, { inputId: field.inputId, label, language: field.language, children: /* @__PURE__ */ jsx(
|
|
45
|
-
|
|
50
|
+
DateTimeInputPicker,
|
|
46
51
|
{
|
|
47
52
|
...pickerProps,
|
|
48
53
|
timezone: shownTimeZone,
|
|
@@ -69,6 +74,7 @@ function DateTimeInput({
|
|
|
69
74
|
}
|
|
70
75
|
) });
|
|
71
76
|
}
|
|
77
|
+
const DateTimeInput = withPieceSlots(DateTimeInputContent, THEME_NAME);
|
|
72
78
|
export {
|
|
73
79
|
DateTimeInput as default
|
|
74
80
|
};
|