@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SecretField.js","sources":["../../../src/ui/actions/SecretField.jsx"],"sourcesContent":["// Un secreto que se enseña UNA vez (una clave de acceso, un token recién creado): tapado por omisión, con el ojo para verlo\n// y el botón para copiarlo.\n//\n// Tapado porque la pantalla se comparte, se graba o la ve quien pasa por atrás; el botón de copiar evita seleccionarlo a\n// mano y dejar un carácter afuera. Si el navegador no deja copiar, se destapa para copiarlo a mano.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useId, useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport IconButton from '@mui/material/IconButton';\nimport InputAdornment from '@mui/material/InputAdornment';\nimport TextField from '@mui/material/TextField';\nimport Tooltip from '@mui/material/Tooltip';\nimport CheckIcon from '@mui/icons-material/CheckRounded';\nimport CopyIcon from '@mui/icons-material/ContentCopyOutlined';\nimport VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';\nimport VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';\n\nimport FieldFrame from '@/inputs/FieldFrame.jsx';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\nconst COPIED_FEEDBACK_MILLISECONDS = 2000;\nconst MONOSPACE_FONT = 'ui-monospace, SFMono-Regular, Menlo, monospace';\n\n/**\n * @param {object} props\n * @param {string} props.value el secreto\n * @param {string} props.label ya traducido\n * @param {string} [props.helperText] p. ej. «Guárdela: no se vuelve a enseñar»\n * @param {() => void} [props.onCopied]\n * @param {(isRevealed: boolean) => void} [props.onRevealChange] se destapó o se tapó (para registrar quién vio el secreto)\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\
|
|
1
|
+
{"version":3,"file":"SecretField.js","sources":["../../../src/ui/actions/SecretField.jsx"],"sourcesContent":["// Un secreto que se enseña UNA vez (una clave de acceso, un token recién creado): tapado por omisión, con el ojo para verlo\n// y el botón para copiarlo.\n//\n// Tapado porque la pantalla se comparte, se graba o la ve quien pasa por atrás; el botón de copiar evita seleccionarlo a\n// mano y dejar un carácter afuera. Si el navegador no deja copiar, se destapa para copiarlo a mano.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaSecretField con defaultProps, styleOverrides de\n// sus partes (field) y slots/slotProps para cambiarlas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useId, useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport IconButton from '@mui/material/IconButton';\nimport InputAdornment from '@mui/material/InputAdornment';\nimport TextField from '@mui/material/TextField';\nimport Tooltip from '@mui/material/Tooltip';\nimport CheckIcon from '@mui/icons-material/CheckRounded';\nimport CopyIcon from '@mui/icons-material/ContentCopyOutlined';\nimport VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';\nimport VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';\n\nimport FieldFrame from '@/inputs/FieldFrame.jsx';\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.CalcitaSecretField)\nconst THEME_NAME = 'CalcitaSecretField';\nconst SecretFieldField = piecePart(THEME_NAME, 'Field', TextField);\n\nconst COPIED_FEEDBACK_MILLISECONDS = 2000;\nconst MONOSPACE_FONT = 'ui-monospace, SFMono-Regular, Menlo, monospace';\n\n/**\n * @param {object} props\n * @param {string} props.value el secreto\n * @param {string} props.label ya traducido\n * @param {string} [props.helperText] p. ej. «Guárdela: no se vuelve a enseñar»\n * @param {() => void} [props.onCopied]\n * @param {(isRevealed: boolean) => void} [props.onRevealChange] se destapó o se tapó (para registrar quién vio el secreto)\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction SecretFieldContent(props) {\n const {value, label, helperText = ' ', onCopied, onRevealChange, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const generatedId = useId();\n const inputId = `secret-${generatedId}`;\n const [isRevealed, setIsRevealedState] = useState(false);\n const setIsRevealed = (nextIsRevealed) => {\n setIsRevealedState(nextIsRevealed);\n onRevealChange?.(nextIsRevealed);\n };\n const [isCopied, setIsCopied] = useState(false);\n const revealLabel = isRevealed ? t('form.hidePassword') : t('form.showPassword');\n\n const copy = async () => {\n try {\n await navigator.clipboard.writeText(value);\n setIsCopied(true);\n onCopied?.();\n setTimeout(() => setIsCopied(false), COPIED_FEEDBACK_MILLISECONDS);\n } catch {\n // sin permiso de portapapeles: se destapa para copiarlo a mano\n setIsRevealed(true);\n }\n };\n\n return (\n <FieldFrame inputId={inputId} label={label}>\n <SecretFieldField\n id={inputId}\n fullWidth\n size=\"small\"\n value={value}\n helperText={helperText}\n type={isRevealed ? 'text' : 'password'}\n slotProps={{\n htmlInput: {readOnly: true, spellCheck: false, autoComplete: 'off', style: {fontFamily: MONOSPACE_FONT}},\n input: {\n endAdornment: (\n <InputAdornment position=\"end\">\n <Tooltip title={revealLabel}>\n <IconButton size=\"small\" aria-label={revealLabel} onClick={() => setIsRevealed(!isRevealed)}>\n {isRevealed ? <VisibilityOffOutlinedIcon fontSize=\"small\" /> : <VisibilityOutlinedIcon fontSize=\"small\" />}\n </IconButton>\n </Tooltip>\n <Tooltip title={isCopied ? t('form.copied') : t('form.copy')}>\n <IconButton size=\"small\" aria-label={t('form.copy')} onClick={copy} color={isCopied ? 'success' : 'default'}>\n {isCopied ? <CheckIcon fontSize=\"small\" /> : <CopyIcon fontSize=\"small\" />}\n </IconButton>\n </Tooltip>\n </InputAdornment>\n ),\n },\n }}\n />\n </FieldFrame>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst SecretField = withPieceSlots(SecretFieldContent, THEME_NAME);\nexport default SecretField;\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AA0BA,MAAM,aAAa;AACnB,MAAM,mBAAmB,UAAU,YAAY,SAAS,SAAS;AAEjE,MAAM,+BAA+B;AACrC,MAAM,iBAAiB;AAWvB,SAAS,mBAAmB,OAAO;AAC/B,QAAM,EAAC,OAAO,OAAO,aAAa,KAAK,UAAU,gBAAgB,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AAC1H,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,QAAM,cAAc,MAAA;AACpB,QAAM,UAAU,UAAU,WAAW;AACrC,QAAM,CAAC,YAAY,kBAAkB,IAAI,SAAS,KAAK;AACvD,QAAM,gBAAgB,CAAC,mBAAmB;AACtC,uBAAmB,cAAc;AACjC,qBAAiB,cAAc;AAAA,EACnC;AACA,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,KAAK;AAC9C,QAAM,cAAc,aAAa,EAAE,mBAAmB,IAAI,EAAE,mBAAmB;AAE/E,QAAM,OAAO,YAAY;AACrB,QAAI;AACA,YAAM,UAAU,UAAU,UAAU,KAAK;AACzC,kBAAY,IAAI;AAChB,iBAAA;AACA,iBAAW,MAAM,YAAY,KAAK,GAAG,4BAA4B;AAAA,IACrE,QAAQ;AAEJ,oBAAc,IAAI;AAAA,IACtB;AAAA,EACJ;AAEA,SACI,oBAAC,YAAA,EAAW,SAAkB,OAC1B,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACG,IAAI;AAAA,MACJ,WAAS;AAAA,MACT,MAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,MAAM,aAAa,SAAS;AAAA,MAC5B,WAAW;AAAA,QACP,WAAW,EAAC,UAAU,MAAM,YAAY,OAAO,cAAc,OAAO,OAAO,EAAC,YAAY,eAAA,EAAc;AAAA,QACtG,OAAO;AAAA,UACH,cACI,qBAAC,gBAAA,EAAe,UAAS,OACrB,UAAA;AAAA,YAAA,oBAAC,SAAA,EAAQ,OAAO,aACZ,UAAA,oBAAC,YAAA,EAAW,MAAK,SAAQ,cAAY,aAAa,SAAS,MAAM,cAAc,CAAC,UAAU,GACrF,UAAA,aAAa,oBAAC,2BAAA,EAA0B,UAAS,QAAA,CAAQ,IAAK,oBAAC,wBAAA,EAAuB,UAAS,QAAA,CAAQ,EAAA,CAC5G,GACJ;AAAA,YACA,oBAAC,SAAA,EAAQ,OAAO,WAAW,EAAE,aAAa,IAAI,EAAE,WAAW,GACvD,UAAA,oBAAC,YAAA,EAAW,MAAK,SAAQ,cAAY,EAAE,WAAW,GAAG,SAAS,MAAM,OAAO,WAAW,YAAY,WAC7F,qBAAW,oBAAC,WAAA,EAAU,UAAS,QAAA,CAAQ,IAAK,oBAAC,UAAA,EAAS,UAAS,QAAA,CAAQ,GAC5E,EAAA,CACJ;AAAA,UAAA,EAAA,CACJ;AAAA,QAAA;AAAA,MAER;AAAA,IACJ;AAAA,EAAA,GAER;AAER;AAGA,MAAM,cAAc,eAAe,oBAAoB,UAAU;"}
|
|
@@ -18,7 +18,7 @@ import { usesMobileTabBar } from "../../appShell/tabBarRule.js";
|
|
|
18
18
|
import { minimalFloatingStylesOf } from "../../theme/components/minimalComponents.js";
|
|
19
19
|
import { isGlassTheme, glassStylesOf } from "../../theme/glassSurface.js";
|
|
20
20
|
import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
|
|
21
|
-
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
21
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
|
|
22
22
|
import { warnUnknownProps } from "../../toolkit/unknownProps.js";
|
|
23
23
|
const THEME_NAME = "CalcitaSelectionActions";
|
|
24
24
|
const SelectionBar = piecePart(THEME_NAME, "Bar", Stack);
|
|
@@ -49,7 +49,7 @@ function bottomCapsuleSxOf(theme) {
|
|
|
49
49
|
...aboveMobileTabBarOf(FLOATING_GAP_PIXELS)
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
-
function
|
|
52
|
+
function SelectionActionsContent(props) {
|
|
53
53
|
const { countText, actions = [], onClear, phoneLayout = SELECTION_PHONE_LAYOUT.top, texts, sx, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
54
54
|
warnUnknownProps(THEME_NAME, unknownProps);
|
|
55
55
|
const theme = useTheme();
|
|
@@ -144,6 +144,7 @@ function SelectionActions(props) {
|
|
|
144
144
|
] })
|
|
145
145
|
] });
|
|
146
146
|
}
|
|
147
|
+
const SelectionActions = withPieceSlots(SelectionActionsContent, THEME_NAME);
|
|
147
148
|
export {
|
|
148
149
|
SELECTION_PHONE_LAYOUT,
|
|
149
150
|
SelectionActions as default,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SelectionActions.js","sources":["../../../src/ui/actions/SelectionActions.jsx"],"sourcesContent":["// Las acciones de lo elegido en una lista («5 pedidos elegidos · Cancelar · Borrar · Quitar selección»), en el lugar que le\n// toca según el equipo. Una sola pieza para que cada lista con casillas (la tabla de servidor, una propia) no repita dónde\n// va cada cosa:\n// - escritorio, y el teléfono sin barra de pestañas abajo (el tema de MUI sin vidrio): un renglón donde se pone la pieza,\n// cada acción como botón con su texto;\n// - teléfono con vidrio, o minimalista con cápsulas (usesMobileTabBar), según phoneLayout (SELECTION_PHONE_LAYOUT):\n// top (por omisión): arriba, en la barra flotante, «5 elegidos ✕» y las acciones como íconos en su propia cápsula,\n// como Apple separa los grupos; las que no caben, al «⋯» (BarActions);\n// en los dos, mientras hay algo elegido, el renglón de arriba queda solo para lo elegido (BarActions exclusive): las\n// demás cápsulas de la pantalla y la lupa se esconden, como el modo de edición del iPhone;\n// split: como iOS en modo de edición (Fotos, Mail, Archivos): arriba «5 elegidos ✕» y abajo, encima de las pestañas,\n// una cápsula fija con las acciones, donde llega el pulgar. Mientras se ve, pide su alto al marco\n// (FLOATING_BOTTOM_SPACE_CSS_VARIABLE) para no tapar el final de la página.\n// Lo pidió el autor: en el teléfono, configurable, y por omisión todo arriba.\n//\n// Con vidrio, la cápsula de arriba deja sus botones del color del texto (BarCapsule: la regla de la barra); abajo, una acción\n// destructiva (color: 'error') conserva su rojo, como pide la guía de Apple para lo que borra.\n//\n// Cada acción puede regresar una promesa: mientras corre, las demás se apagan (nadie cancela dos veces lo mismo).\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaSelectionActions con defaultProps y\n// styleOverrides de sus partes: bar, count, clear, phoneCount, phoneActions.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport GlobalStyles from '@mui/material/GlobalStyles';\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 CloseRoundedIcon from '@mui/icons-material/CloseRounded';\n\nimport BarActionButton from '@/appShell/BarActionButton.jsx';\nimport BarActions from '@/appShell/BarActions.jsx';\nimport BarCapsule from '@/appShell/BarCapsule.jsx';\nimport {\n FLOATING_BOTTOM_SPACE_CSS_VARIABLE, GLASS_PANEL_GAP_PIXELS, PHONE_MEDIA_QUERY, aboveMobileTabBarOf,\n} from '@/appShell/shellSizes.js';\nimport {usesMobileTabBar} from '@/appShell/tabBarRule.js';\nimport {minimalFloatingStylesOf} from '@/theme/components/minimalComponents.js';\nimport {glassStylesOf, isGlassTheme} from '@/theme/glassSurface.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.CalcitaSelectionActions)\nconst THEME_NAME = 'CalcitaSelectionActions';\nconst SelectionBar = piecePart(THEME_NAME, 'Bar', Stack);\nconst SelectionCount = piecePart(THEME_NAME, 'Count', Typography);\nconst SelectionClear = piecePart(THEME_NAME, 'Clear', Button);\nconst SelectionPhoneCount = piecePart(THEME_NAME, 'PhoneCount', Typography);\nconst SelectionPhoneActions = piecePart(THEME_NAME, 'PhoneActions', Box);\n\n/** Dónde van las acciones de lo elegido en el teléfono con barra de pestañas abajo: todo arriba o divididas (iOS). */\nexport const SELECTION_PHONE_LAYOUT = Object.freeze({top: 'top', split: 'split'});\n\n// lo que se separa la cápsula de abajo de la barra de pestañas (px), lo mismo que el aviso de versión nueva\nconst FLOATING_GAP_PIXELS = 8;\n// lo que pide al marco mientras flota abajo: su alto (48) y su separación, con aire\nconst FLOATING_BOTTOM_SPACE_PIXELS = 64;\n// lo que solo se ve en el teléfono\nconst PHONE_ONLY_SX = {display: 'none', [PHONE_MEDIA_QUERY]: {display: 'flex'}};\n\n/**\n * ¿En el teléfono lo elegido sale de su renglón (arriba o abajo)? La misma regla que la barra de pestañas de abajo: con ella,\n * el renglón de la pantalla se queda con lo suyo (el conteo de la tabla) y las acciones flotan.\n *\n * @param {object} theme\n * @returns {boolean}\n */\nexport function selectionFloatsOnPhone(theme) {\n return usesMobileTabBar(theme);\n}\n\n/**\n * La cápsula fija abajo, centrada en la ventana, encima de la barra de pestañas.\n *\n * @param {object} theme\n * @returns {object}\n */\nfunction bottomCapsuleSxOf(theme) {\n return {\n ...(isGlassTheme(theme) ? glassStylesOf(theme) : minimalFloatingStylesOf(theme)),\n position: 'fixed',\n left: '50%',\n transform: 'translateX(-50%)',\n zIndex: theme.zIndex.appBar,\n alignItems: 'center',\n gap: 0.5,\n width: 'max-content',\n maxWidth: `calc(100% - ${GLASS_PANEL_GAP_PIXELS * 2}px)`,\n borderRadius: '999px',\n p: 0.5,\n ...aboveMobileTabBarOf(FLOATING_GAP_PIXELS),\n };\n}\n\n/**\n * @param {object} props\n * @param {string} props.countText «5 pedidos elegidos», ya traducido. La pieza se pinta mientras la pantalla la ponga: con\n * nada elegido, no la ponga\n * @param {Array<{key: string, label: string, icon?: import('react').ReactNode, color?: 'inherit'|'primary'|'secondary'|'error'|'info'|'success'|'warning', disabled?: boolean, onClick: () => unknown}>} [props.actions]\n * label ya traducido; en el teléfono se ve el ícono (sin él, el texto). onClick puede regresar una promesa\n * @param {() => void} props.onClear quitar la selección\n * @param {'top'|'split'} [props.phoneLayout] SELECTION_PHONE_LAYOUT; por omisión todo arriba\n * @param {object} [props.texts] los textos que cambian, con la forma de `common`: {selection: {clear, actionsLabel, summaryLabel}}\n * @param {object} [props.sx] estilos del renglón\n */\nexport default function SelectionActions(props) {\n // lo que el proyecto puso en su tema (components.CalcitaSelectionActions.defaultProps) y encima lo que llega aquí\n const {countText, actions = [], onClear, phoneLayout = SELECTION_PHONE_LAYOUT.top, texts, sx, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const theme = useTheme();\n const {t} = useToolkitTranslation('common', texts);\n const [runningActionKey, setRunningActionKey] = useState(null);\n const floatsOnPhone = selectionFloatsOnPhone(theme);\n const extraSx = Array.isArray(sx) ? sx : [sx];\n\n const runAction = async (action) => {\n setRunningActionKey(action.key);\n try {\n await action.onClick();\n } finally {\n setRunningActionKey(null);\n }\n };\n const isDisabledOf = (action) => runningActionKey !== null || Boolean(action.disabled);\n\n const clearButton = (\n <Tooltip title={t('selection.clear')}>\n <IconButton aria-label={t('selection.clear')} onClick={onClear}>\n <CloseRoundedIcon />\n </IconButton>\n </Tooltip>\n );\n\n // el renglón: escritorio siempre; en el teléfono, solo si ahí no flota\n const row = (\n <SelectionBar role=\"toolbar\" aria-label={t('selection.actionsLabel')} direction=\"row\" spacing={1} useFlexGap\n ownSx={[{flexGrow: 1, alignItems: 'center', flexWrap: 'wrap', minHeight: 32},\n floatsOnPhone && {[PHONE_MEDIA_QUERY]: {display: 'none'}}, ...extraSx]}>\n <SelectionCount variant=\"body2\" ownSx={{fontWeight: 600, mr: 1}}>{countText}</SelectionCount>\n {actions.map((action) => (\n <Button key={action.key} size=\"small\" color={action.color ?? 'primary'} startIcon={action.icon}\n disabled={isDisabledOf(action)} onClick={() => runAction(action)}>\n {action.label}\n </Button>\n ))}\n <SelectionClear size=\"small\" color=\"inherit\" startIcon={<CloseRoundedIcon />} onClick={onClear} ownSx={{ml: 'auto'}}>\n {t('selection.clear')}\n </SelectionClear>\n </SelectionBar>\n );\n\n if (!floatsOnPhone) {\n return row;\n }\n\n const showsBottomCapsule = phoneLayout === SELECTION_PHONE_LAYOUT.split && actions.length > 0;\n\n return (\n <>\n {row}\n {/* arriba: con las demás cápsulas flotantes de la pantalla (BarActions), antes que ellas. Sin label en BarActions:\n el nombre ya lo lleva la cápsula (dos grupos anidados con el mismo nombre se leen dos veces) */}\n <BarActions bare exclusive order={-2} sx={PHONE_ONLY_SX} inlineSx={PHONE_ONLY_SX}>\n <BarCapsule aria-label={t('selection.summaryLabel')} sx={{pl: 2}}>\n <SelectionPhoneCount variant=\"body2\" role=\"status\" aria-live=\"polite\" ownSx={{fontWeight: 600, whiteSpace: 'nowrap', mr: 0.5}}>\n {countText}\n </SelectionPhoneCount>\n {clearButton}\n </BarCapsule>\n </BarActions>\n {phoneLayout === SELECTION_PHONE_LAYOUT.top && actions.length > 0 && (\n <BarActions label={t('selection.actionsLabel')} exclusive order={-1} sx={PHONE_ONLY_SX} inlineSx={PHONE_ONLY_SX}>\n {actions.map((action) => (\n <BarActionButton key={action.key} label={action.label} icon={action.icon} color={action.color}\n disabled={isDisabledOf(action)} onClick={() => runAction(action)} />\n ))}\n </BarActions>\n )}\n {showsBottomCapsule && (\n <>\n <GlobalStyles styles={{':root': {[FLOATING_BOTTOM_SPACE_CSS_VARIABLE]: `${FLOATING_BOTTOM_SPACE_PIXELS}px`}}} />\n <SelectionPhoneActions role=\"toolbar\" aria-label={t('selection.actionsLabel')} ownSx={[bottomCapsuleSxOf, PHONE_ONLY_SX]}>\n {actions.map((action) => (action.icon ? (\n <Tooltip key={action.key} title={action.label}>\n {/* el span deja ver el tooltip aunque el botón esté apagado */}\n <span>\n <IconButton aria-label={action.label} color={action.color ?? 'default'} disabled={isDisabledOf(action)}\n onClick={() => runAction(action)}>\n {action.icon}\n </IconButton>\n </span>\n </Tooltip>\n ) : (\n <Button key={action.key} size=\"small\" color={action.color ?? 'primary'} disabled={isDisabledOf(action)}\n onClick={() => runAction(action)}>\n {action.label}\n </Button>\n )))}\n </SelectionPhoneActions>\n </>\n )}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SelectionActions.js","sources":["../../../src/ui/actions/SelectionActions.jsx"],"sourcesContent":["// Las acciones de lo elegido en una lista («5 pedidos elegidos · Cancelar · Borrar · Quitar selección»), en el lugar que le\n// toca según el equipo. Una sola pieza para que cada lista con casillas (la tabla de servidor, una propia) no repita dónde\n// va cada cosa:\n// - escritorio, y el teléfono sin barra de pestañas abajo (el tema de MUI sin vidrio): un renglón donde se pone la pieza,\n// cada acción como botón con su texto;\n// - teléfono con vidrio, o minimalista con cápsulas (usesMobileTabBar), según phoneLayout (SELECTION_PHONE_LAYOUT):\n// top (por omisión): arriba, en la barra flotante, «5 elegidos ✕» y las acciones como íconos en su propia cápsula,\n// como Apple separa los grupos; las que no caben, al «⋯» (BarActions);\n// en los dos, mientras hay algo elegido, el renglón de arriba queda solo para lo elegido (BarActions exclusive): las\n// demás cápsulas de la pantalla y la lupa se esconden, como el modo de edición del iPhone;\n// split: como iOS en modo de edición (Fotos, Mail, Archivos): arriba «5 elegidos ✕» y abajo, encima de las pestañas,\n// una cápsula fija con las acciones, donde llega el pulgar. Mientras se ve, pide su alto al marco\n// (FLOATING_BOTTOM_SPACE_CSS_VARIABLE) para no tapar el final de la página.\n// Lo pidió el autor: en el teléfono, configurable, y por omisión todo arriba.\n//\n// Con vidrio, la cápsula de arriba deja sus botones del color del texto (BarCapsule: la regla de la barra); abajo, una acción\n// destructiva (color: 'error') conserva su rojo, como pide la guía de Apple para lo que borra.\n//\n// Cada acción puede regresar una promesa: mientras corre, las demás se apagan (nadie cancela dos veces lo mismo).\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaSelectionActions con defaultProps y\n// styleOverrides de sus partes: bar, count, clear, phoneCount, phoneActions.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport GlobalStyles from '@mui/material/GlobalStyles';\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 CloseRoundedIcon from '@mui/icons-material/CloseRounded';\n\nimport BarActionButton from '@/appShell/BarActionButton.jsx';\nimport BarActions from '@/appShell/BarActions.jsx';\nimport BarCapsule from '@/appShell/BarCapsule.jsx';\nimport {\n FLOATING_BOTTOM_SPACE_CSS_VARIABLE, GLASS_PANEL_GAP_PIXELS, PHONE_MEDIA_QUERY, aboveMobileTabBarOf,\n} from '@/appShell/shellSizes.js';\nimport {usesMobileTabBar} from '@/appShell/tabBarRule.js';\nimport {minimalFloatingStylesOf} from '@/theme/components/minimalComponents.js';\nimport {glassStylesOf, isGlassTheme} from '@/theme/glassSurface.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.CalcitaSelectionActions)\nconst THEME_NAME = 'CalcitaSelectionActions';\nconst SelectionBar = piecePart(THEME_NAME, 'Bar', Stack);\nconst SelectionCount = piecePart(THEME_NAME, 'Count', Typography);\nconst SelectionClear = piecePart(THEME_NAME, 'Clear', Button);\nconst SelectionPhoneCount = piecePart(THEME_NAME, 'PhoneCount', Typography);\nconst SelectionPhoneActions = piecePart(THEME_NAME, 'PhoneActions', Box);\n\n/** Dónde van las acciones de lo elegido en el teléfono con barra de pestañas abajo: todo arriba o divididas (iOS). */\nexport const SELECTION_PHONE_LAYOUT = Object.freeze({top: 'top', split: 'split'});\n\n// lo que se separa la cápsula de abajo de la barra de pestañas (px), lo mismo que el aviso de versión nueva\nconst FLOATING_GAP_PIXELS = 8;\n// lo que pide al marco mientras flota abajo: su alto (48) y su separación, con aire\nconst FLOATING_BOTTOM_SPACE_PIXELS = 64;\n// lo que solo se ve en el teléfono\nconst PHONE_ONLY_SX = {display: 'none', [PHONE_MEDIA_QUERY]: {display: 'flex'}};\n\n/**\n * ¿En el teléfono lo elegido sale de su renglón (arriba o abajo)? La misma regla que la barra de pestañas de abajo: con ella,\n * el renglón de la pantalla se queda con lo suyo (el conteo de la tabla) y las acciones flotan.\n *\n * @param {object} theme\n * @returns {boolean}\n */\nexport function selectionFloatsOnPhone(theme) {\n return usesMobileTabBar(theme);\n}\n\n/**\n * La cápsula fija abajo, centrada en la ventana, encima de la barra de pestañas.\n *\n * @param {object} theme\n * @returns {object}\n */\nfunction bottomCapsuleSxOf(theme) {\n return {\n ...(isGlassTheme(theme) ? glassStylesOf(theme) : minimalFloatingStylesOf(theme)),\n position: 'fixed',\n left: '50%',\n transform: 'translateX(-50%)',\n zIndex: theme.zIndex.appBar,\n alignItems: 'center',\n gap: 0.5,\n width: 'max-content',\n maxWidth: `calc(100% - ${GLASS_PANEL_GAP_PIXELS * 2}px)`,\n borderRadius: '999px',\n p: 0.5,\n ...aboveMobileTabBarOf(FLOATING_GAP_PIXELS),\n };\n}\n\n/**\n * @param {object} props\n * @param {string} props.countText «5 pedidos elegidos», ya traducido. La pieza se pinta mientras la pantalla la ponga: con\n * nada elegido, no la ponga\n * @param {Array<{key: string, label: string, icon?: import('react').ReactNode, color?: 'inherit'|'primary'|'secondary'|'error'|'info'|'success'|'warning', disabled?: boolean, onClick: () => unknown}>} [props.actions]\n * label ya traducido; en el teléfono se ve el ícono (sin él, el texto). onClick puede regresar una promesa\n * @param {() => void} props.onClear quitar la selección\n * @param {'top'|'split'} [props.phoneLayout] SELECTION_PHONE_LAYOUT; por omisión todo arriba\n * @param {object} [props.texts] los textos que cambian, con la forma de `common`: {selection: {clear, actionsLabel, summaryLabel}}\n * @param {object} [props.sx] estilos del renglón\n */\nfunction SelectionActionsContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaSelectionActions.defaultProps) y encima lo que llega aquí\n const {countText, actions = [], onClear, phoneLayout = SELECTION_PHONE_LAYOUT.top, texts, sx, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const theme = useTheme();\n const {t} = useToolkitTranslation('common', texts);\n const [runningActionKey, setRunningActionKey] = useState(null);\n const floatsOnPhone = selectionFloatsOnPhone(theme);\n const extraSx = Array.isArray(sx) ? sx : [sx];\n\n const runAction = async (action) => {\n setRunningActionKey(action.key);\n try {\n await action.onClick();\n } finally {\n setRunningActionKey(null);\n }\n };\n const isDisabledOf = (action) => runningActionKey !== null || Boolean(action.disabled);\n\n const clearButton = (\n <Tooltip title={t('selection.clear')}>\n <IconButton aria-label={t('selection.clear')} onClick={onClear}>\n <CloseRoundedIcon />\n </IconButton>\n </Tooltip>\n );\n\n // el renglón: escritorio siempre; en el teléfono, solo si ahí no flota\n const row = (\n <SelectionBar role=\"toolbar\" aria-label={t('selection.actionsLabel')} direction=\"row\" spacing={1} useFlexGap\n ownSx={[{flexGrow: 1, alignItems: 'center', flexWrap: 'wrap', minHeight: 32},\n floatsOnPhone && {[PHONE_MEDIA_QUERY]: {display: 'none'}}, ...extraSx]}>\n <SelectionCount variant=\"body2\" ownSx={{fontWeight: 600, mr: 1}}>{countText}</SelectionCount>\n {actions.map((action) => (\n <Button key={action.key} size=\"small\" color={action.color ?? 'primary'} startIcon={action.icon}\n disabled={isDisabledOf(action)} onClick={() => runAction(action)}>\n {action.label}\n </Button>\n ))}\n <SelectionClear size=\"small\" color=\"inherit\" startIcon={<CloseRoundedIcon />} onClick={onClear} ownSx={{ml: 'auto'}}>\n {t('selection.clear')}\n </SelectionClear>\n </SelectionBar>\n );\n\n if (!floatsOnPhone) {\n return row;\n }\n\n const showsBottomCapsule = phoneLayout === SELECTION_PHONE_LAYOUT.split && actions.length > 0;\n\n return (\n <>\n {row}\n {/* arriba: con las demás cápsulas flotantes de la pantalla (BarActions), antes que ellas. Sin label en BarActions:\n el nombre ya lo lleva la cápsula (dos grupos anidados con el mismo nombre se leen dos veces) */}\n <BarActions bare exclusive order={-2} sx={PHONE_ONLY_SX} inlineSx={PHONE_ONLY_SX}>\n <BarCapsule aria-label={t('selection.summaryLabel')} sx={{pl: 2}}>\n <SelectionPhoneCount variant=\"body2\" role=\"status\" aria-live=\"polite\" ownSx={{fontWeight: 600, whiteSpace: 'nowrap', mr: 0.5}}>\n {countText}\n </SelectionPhoneCount>\n {clearButton}\n </BarCapsule>\n </BarActions>\n {phoneLayout === SELECTION_PHONE_LAYOUT.top && actions.length > 0 && (\n <BarActions label={t('selection.actionsLabel')} exclusive order={-1} sx={PHONE_ONLY_SX} inlineSx={PHONE_ONLY_SX}>\n {actions.map((action) => (\n <BarActionButton key={action.key} label={action.label} icon={action.icon} color={action.color}\n disabled={isDisabledOf(action)} onClick={() => runAction(action)} />\n ))}\n </BarActions>\n )}\n {showsBottomCapsule && (\n <>\n <GlobalStyles styles={{':root': {[FLOATING_BOTTOM_SPACE_CSS_VARIABLE]: `${FLOATING_BOTTOM_SPACE_PIXELS}px`}}} />\n <SelectionPhoneActions role=\"toolbar\" aria-label={t('selection.actionsLabel')} ownSx={[bottomCapsuleSxOf, PHONE_ONLY_SX]}>\n {actions.map((action) => (action.icon ? (\n <Tooltip key={action.key} title={action.label}>\n {/* el span deja ver el tooltip aunque el botón esté apagado */}\n <span>\n <IconButton aria-label={action.label} color={action.color ?? 'default'} disabled={isDisabledOf(action)}\n onClick={() => runAction(action)}>\n {action.icon}\n </IconButton>\n </span>\n </Tooltip>\n ) : (\n <Button key={action.key} size=\"small\" color={action.color ?? 'primary'} disabled={isDisabledOf(action)}\n onClick={() => runAction(action)}>\n {action.label}\n </Button>\n )))}\n </SelectionPhoneActions>\n </>\n )}\n </>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst SelectionActions = withPieceSlots(SelectionActionsContent, THEME_NAME);\nexport default SelectionActions;\n"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@ import Typography from "@mui/material/Typography";
|
|
|
13
13
|
import ExpandMoreRoundedIcon from "@mui/icons-material/ExpandMoreRounded";
|
|
14
14
|
import OpenInNewRoundedIcon from "@mui/icons-material/OpenInNewRounded";
|
|
15
15
|
import { initialsOf } from "../../appShell/menuItemText.js";
|
|
16
|
-
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
16
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
|
|
17
17
|
import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
|
|
18
18
|
import { warnUnknownProps } from "../../toolkit/unknownProps.js";
|
|
19
19
|
import ActionsMenu from "../actions/ActionsMenu.js";
|
|
@@ -29,7 +29,7 @@ const RecordCardFact = piecePart(THEME_NAME, "Fact", Box);
|
|
|
29
29
|
const RecordCardHighlight = piecePart(THEME_NAME, "Highlight", Box);
|
|
30
30
|
const RecordCardFooter = piecePart(THEME_NAME, "Footer", Stack);
|
|
31
31
|
const RecordCardDetails = piecePart(THEME_NAME, "Details", Box);
|
|
32
|
-
function
|
|
32
|
+
function RecordCardContent(props) {
|
|
33
33
|
const {
|
|
34
34
|
title,
|
|
35
35
|
eyebrow,
|
|
@@ -65,7 +65,7 @@ function RecordCard(props) {
|
|
|
65
65
|
};
|
|
66
66
|
const hasBody = groups.length > 0 || highlight || trailing;
|
|
67
67
|
const desktopColumns = columns ?? `${groups.length > 0 ? `repeat(${groups.length}, minmax(0, 1fr))` : ""}${highlight ? " auto" : ""}${trailing ? " auto" : ""}`.trim();
|
|
68
|
-
return /* @__PURE__ */ jsxs(RecordCardRoot, { variant: "outlined", component: "article", "aria-labelledby": titleId, ownSx: { p: { xs: 2, sm: 2.5 }, minWidth: 0,
|
|
68
|
+
return /* @__PURE__ */ jsxs(RecordCardRoot, { variant: "outlined", component: "article", "aria-labelledby": titleId, ownSx: { p: { xs: 2, sm: 2.5 }, minWidth: 0 }, sx, children: [
|
|
69
69
|
header ?? /* @__PURE__ */ jsxs(RecordCardHeader, { direction: "row", ownSx: { gap: 1.5, alignItems: "flex-start", flexWrap: { xs: "wrap", sm: "nowrap" } }, children: [
|
|
70
70
|
avatar && /* @__PURE__ */ jsx(RecordCardAvatar, { ownSx: { width: 44, height: 44, bgcolor: "action.selected", color: "text.primary", fontSize: 16, fontWeight: 600 }, children: typeof avatar === "string" ? initialsOf(avatar) : avatar }),
|
|
71
71
|
/* @__PURE__ */ jsxs(RecordCardTitles, { ownSx: { flex: 1, minWidth: 0, order: 1 }, children: [
|
|
@@ -139,6 +139,7 @@ function RecordCard(props) {
|
|
|
139
139
|
details && /* @__PURE__ */ jsx(Collapse, { in: isDetailsOpen, unmountOnExit: true, children: /* @__PURE__ */ jsx(RecordCardDetails, { id: detailsId, ownSx: { mt: 2, pt: 2, borderTop: 1, borderColor: "divider" }, children: details }) })
|
|
140
140
|
] });
|
|
141
141
|
}
|
|
142
|
+
const RecordCard = withPieceSlots(RecordCardContent, THEME_NAME);
|
|
142
143
|
export {
|
|
143
144
|
RecordCard as default
|
|
144
145
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecordCard.js","sources":["../../../src/ui/cards/RecordCard.jsx"],"sourcesContent":["// La tarjeta de un registro (un pedido, un cliente, una solicitud) para listas donde una tabla se queda corta: cada registro\n// con su identidad arriba, sus datos agrupados en el cuerpo y lo que se puede hacer con él. Para una lista de tarjetas,\n// una debajo de otra; con RecordCardSkeleton mientras carga.\n//\n// encabezado avatar (iniciales o ícono), eyebrow (el folio), title, subtitle; a la derecha status (estatus e\n// insignias) y el menú «⋯» (actions)\n// cuerpo groups: grupos de datos {title?, facts: [{label, value}]} lado a lado en escritorio y uno debajo de otro en\n// el teléfono; highlight: el dato principal, grande (el total)\n// abajo footer (botones, una cuenta regresiva, un formulario corto) y details: lo que se despliega con «Ver\n// detalle» (una tabla, un historial), que avisa con onDetailsToggle\n//\n// El ORDEN es el que se da y nada se reacomoda solo: los grupos de izquierda a derecha (de arriba abajo en el teléfono) y\n// los datos de cada grupo en el orden de facts. Para un orden obligatorio (el de un sistema que ya existe, donde el estatus\n// va después de las fechas), trailing es la última columna del cuerpo y columns fija el ancho de cada una.\n//\n// La tarjeta NO se pica entera (la regla de la casa: una acción, un botón): para abrir el registro, onOpen pone su botón.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaRecordCard con defaultProps y\n// styleOverrides de sus partes: root, header, avatar, titles, status, body, group, fact, highlight, footer, details.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useId, useState} from 'react';\nimport Avatar from '@mui/material/Avatar';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Collapse from '@mui/material/Collapse';\nimport IconButton from '@mui/material/IconButton';\nimport Paper from '@mui/material/Paper';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport ExpandMoreRoundedIcon from '@mui/icons-material/ExpandMoreRounded';\nimport OpenInNewRoundedIcon from '@mui/icons-material/OpenInNewRounded';\n\nimport {initialsOf} from '@/appShell/menuItemText.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport ActionsMenu from '@/ui/actions/ActionsMenu.jsx';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaRecordCard)\nconst THEME_NAME = 'CalcitaRecordCard';\nconst RecordCardRoot = piecePart(THEME_NAME, 'Root', Paper);\nconst RecordCardHeader = piecePart(THEME_NAME, 'Header', Stack);\nconst RecordCardAvatar = piecePart(THEME_NAME, 'Avatar', Avatar);\nconst RecordCardTitles = piecePart(THEME_NAME, 'Titles', Box);\nconst RecordCardStatus = piecePart(THEME_NAME, 'Status', Stack);\nconst RecordCardBody = piecePart(THEME_NAME, 'Body', Box);\nconst RecordCardGroup = piecePart(THEME_NAME, 'Group', Box);\nconst RecordCardFact = piecePart(THEME_NAME, 'Fact', Box);\nconst RecordCardHighlight = piecePart(THEME_NAME, 'Highlight', Box);\nconst RecordCardFooter = piecePart(THEME_NAME, 'Footer', Stack);\nconst RecordCardDetails = piecePart(THEME_NAME, 'Details', Box);\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode} props.title el nombre del registro, ya traducido\n * @param {import('react').ReactNode} [props.eyebrow] arriba del título: el folio o el tipo\n * @param {import('react').ReactNode} [props.subtitle] abajo del título\n * @param {string|import('react').ReactNode} [props.avatar] un texto (de él salen las iniciales) o un ícono\n * @param {import('react').ReactNode} [props.status] a la derecha: StatusChip, IconBadge…\n * @param {Parameters<typeof import('@/ui/actions/ActionsMenu.jsx').default>[0]['actions']} [props.actions] el menú «⋯», con sus secciones,\n * separadores, ligas y submenús (los renglones de ActionsMenu)\n * @param {Array<{key?: string, title?: import('react').ReactNode, facts?: Array<{label: import('react').ReactNode, value: import('react').ReactNode, emphasis?: boolean}>, content?: import('react').ReactNode}>} [props.groups]\n * los datos, en grupos; emphasis los pone en negritas; content en lugar de facts para un grupo libre (una barra, unas\n * insignias, un enlace)\n * @param {import('react').ReactNode} [props.header] un encabezado propio en lugar del de la casa (avatar, títulos, estatus)\n * @param {import('react').ReactNode} [props.children] contenido libre entre el cuerpo y lo de abajo\n * @param {{label: import('react').ReactNode, value: import('react').ReactNode, caption?: import('react').ReactNode}} [props.highlight] el dato principal\n * @param {import('react').ReactNode} [props.trailing] la última columna del cuerpo, después de los grupos y del dato principal\n * (el estatus o unos botones, cuando el orden obligatorio los pone al final)\n * @param {string} [props.columns] en escritorio, el ancho de cada columna del cuerpo como en CSS ('1.2fr 1fr 1fr auto'); por\n * omisión, los grupos a partes iguales y el dato principal y trailing a su medida\n * @param {import('react').ReactNode} [props.footer] abajo, a todo lo ancho\n * @param {import('react').ReactNode} [props.details] lo que se despliega con «Ver detalle»\n * @param {string} [props.detailsLabel] ya traducido; por omisión «Ver detalle»\n * @param {boolean} [props.defaultDetailsOpen]\n * @param {(isOpen: boolean) => void} [props.onDetailsToggle]\n * @param {() => void} [props.onOpen] el botón para abrir el registro (su detalle)\n * @param {string} [props.openLabel] ya traducido: el nombre de ese botón («Abrir el pedido P-1203»)\n * @param {object} [props.sx]\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nexport default function RecordCard(props) {\n const {\n title, eyebrow, subtitle, avatar, status, actions, groups = [], highlight, trailing, columns, footer, details, detailsLabel, defaultDetailsOpen = false,\n onDetailsToggle, onOpen, openLabel, header, children, sx, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const titleId = useId();\n const detailsId = useId();\n const [isDetailsOpen, setIsDetailsOpen] = useState(defaultDetailsOpen);\n const toggleDetails = () => {\n setIsDetailsOpen((current) => !current);\n onDetailsToggle?.(!isDetailsOpen);\n };\n const hasBody = groups.length > 0 || highlight || trailing;\n // las columnas en escritorio: las que se pidan, o los grupos a partes iguales y lo demás a su medida\n const desktopColumns = columns ?? `${groups.length > 0 ? `repeat(${groups.length}, minmax(0, 1fr))` : ''}${highlight ? ' auto' : ''}${trailing ? ' auto' : ''}`.trim();\n\n return (\n <RecordCardRoot variant=\"outlined\" component=\"article\" aria-labelledby={titleId} ownSx={{p: {xs: 2, sm: 2.5}, minWidth: 0, ...sx}}>\n {/* en el teléfono el estatus baja abajo del título (si no, le quitaba medio ancho) y arriba quedan los botones */}\n {header ?? (\n <RecordCardHeader direction=\"row\" ownSx={{gap: 1.5, alignItems: 'flex-start', flexWrap: {xs: 'wrap', sm: 'nowrap'}}}>\n {avatar && (\n <RecordCardAvatar ownSx={{width: 44, height: 44, bgcolor: 'action.selected', color: 'text.primary', fontSize: 16, fontWeight: 600}}>\n {typeof avatar === 'string' ? initialsOf(avatar) : avatar}\n </RecordCardAvatar>\n )}\n <RecordCardTitles ownSx={{flex: 1, minWidth: 0, order: 1}}>\n {eyebrow && <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\" sx={{fontVariantNumeric: 'tabular-nums'}}>{eyebrow}</Typography>}\n <Typography id={titleId} variant=\"subtitle1\" component=\"h3\" sx={{fontWeight: 600, overflowWrap: 'anywhere'}}>{title}</Typography>\n {subtitle && <Typography variant=\"body2\" color=\"text.secondary\">{subtitle}</Typography>}\n </RecordCardTitles>\n {status && (\n <RecordCardStatus direction=\"row\" ownSx={{\n gap: 0.75, alignItems: 'center', flexWrap: 'wrap', order: {xs: 3, sm: 2},\n flexBasis: {xs: '100%', sm: 'auto'}, justifyContent: {xs: 'flex-start', sm: 'flex-end'}, maxWidth: {sm: '50%'},\n }}>\n {status}\n </RecordCardStatus>\n )}\n <Stack direction=\"row\" sx={{gap: 0.25, alignItems: 'center', order: {xs: 2, sm: 3}, flexShrink: 0}}>\n {onOpen && (\n <Tooltip title={openLabel ?? t('recordCard.open')}>\n <IconButton size=\"small\" aria-label={openLabel ?? t('recordCard.open')} onClick={onOpen}><OpenInNewRoundedIcon fontSize=\"small\" /></IconButton>\n </Tooltip>\n )}\n {actions?.length > 0 && <ActionsMenu label={t('recordCard.actions')} actions={actions} size=\"small\" />}\n </Stack>\n </RecordCardHeader>\n )}\n\n {hasBody && (\n <RecordCardBody ownSx={{\n mt: 2, display: 'grid', gap: {xs: 1.5, md: 3}, alignItems: 'start',\n // en escritorio los grupos lado a lado y el dato principal al final; en el teléfono, uno debajo de otro\n gridTemplateColumns: {xs: '1fr', md: desktopColumns},\n }}>\n {groups.map((group, groupIndex) => (\n <RecordCardGroup key={group.key ?? groupIndex} ownSx={{\n minWidth: 0, pt: {xs: groupIndex > 0 ? 1.5 : 0, md: 0}, borderTop: {xs: groupIndex > 0 ? 1 : 0, md: 0}, borderColor: 'divider',\n }}>\n {group.title && <Typography variant=\"overline\" color=\"text.secondary\" component=\"p\" sx={{lineHeight: 1.8}}>{group.title}</Typography>}\n {group.content ?? (\n <Box component=\"dl\" sx={{m: 0, display: 'grid', gridTemplateColumns: 'auto 1fr', columnGap: 1.5, rowGap: 0.5}}>\n {(group.facts ?? []).map((fact, factIndex) => (\n <RecordCardFact key={factIndex} ownSx={{display: 'contents'}}>\n <Typography component=\"dt\" variant=\"body2\" color=\"text.secondary\">{fact.label}</Typography>\n <Typography component=\"dd\" variant=\"body2\" sx={{m: 0, textAlign: 'right', fontVariantNumeric: 'tabular-nums', fontWeight: fact.emphasis ? 600 : 400, overflowWrap: 'anywhere'}}>\n {fact.value}\n </Typography>\n </RecordCardFact>\n ))}\n </Box>\n )}\n </RecordCardGroup>\n ))}\n {highlight && (\n <RecordCardHighlight ownSx={{\n textAlign: {xs: 'left', md: 'right'}, pl: {md: 3}, borderLeft: {md: 1}, borderTop: {xs: 1, md: 0}, pt: {xs: 1.5, md: 0}, borderColor: 'divider',\n }}>\n <Typography variant=\"overline\" color=\"text.secondary\" component=\"p\" sx={{lineHeight: 1.8}}>{highlight.label}</Typography>\n <Typography variant=\"h5\" component=\"p\" sx={{fontWeight: 700, fontVariantNumeric: 'tabular-nums', whiteSpace: 'nowrap'}}>{highlight.value}</Typography>\n {highlight.caption && <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">{highlight.caption}</Typography>}\n </RecordCardHighlight>\n )}\n {trailing && (\n <Box sx={{minWidth: 0, alignSelf: 'center', borderTop: {xs: 1, md: 0}, pt: {xs: 1.5, md: 0}, borderColor: 'divider'}}>{trailing}</Box>\n )}\n </RecordCardBody>\n )}\n\n {children}\n {(footer || details) && (\n <RecordCardFooter direction=\"row\" ownSx={{mt: 2, gap: 1, alignItems: 'center', flexWrap: 'wrap'}}>\n <Box sx={{flex: 1, minWidth: 0}}>{footer}</Box>\n {details && (\n <Button size=\"small\" onClick={toggleDetails} aria-expanded={isDetailsOpen} aria-controls={detailsId}\n endIcon={<ExpandMoreRoundedIcon sx={{transform: isDetailsOpen ? 'rotate(180deg)' : 'none', transition: 'transform 200ms'}} />}>\n {isDetailsOpen ? t('recordCard.hideDetails') : (detailsLabel ?? t('recordCard.showDetails'))}\n </Button>\n )}\n </RecordCardFooter>\n )}\n {details && (\n <Collapse in={isDetailsOpen} unmountOnExit>\n <RecordCardDetails id={detailsId} ownSx={{mt: 2, pt: 2, borderTop: 1, borderColor: 'divider'}}>{details}</RecordCardDetails>\n </Collapse>\n )}\n </RecordCardRoot>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RecordCard.js","sources":["../../../src/ui/cards/RecordCard.jsx"],"sourcesContent":["// La tarjeta de un registro (un pedido, un cliente, una solicitud) para listas donde una tabla se queda corta: cada registro\n// con su identidad arriba, sus datos agrupados en el cuerpo y lo que se puede hacer con él. Para una lista de tarjetas,\n// una debajo de otra; con RecordCardSkeleton mientras carga.\n//\n// encabezado avatar (iniciales o ícono), eyebrow (el folio), title, subtitle; a la derecha status (estatus e\n// insignias) y el menú «⋯» (actions)\n// cuerpo groups: grupos de datos {title?, facts: [{label, value}]} lado a lado en escritorio y uno debajo de otro en\n// el teléfono; highlight: el dato principal, grande (el total)\n// abajo footer (botones, una cuenta regresiva, un formulario corto) y details: lo que se despliega con «Ver\n// detalle» (una tabla, un historial), que avisa con onDetailsToggle\n//\n// El ORDEN es el que se da y nada se reacomoda solo: los grupos de izquierda a derecha (de arriba abajo en el teléfono) y\n// los datos de cada grupo en el orden de facts. Para un orden obligatorio (el de un sistema que ya existe, donde el estatus\n// va después de las fechas), trailing es la última columna del cuerpo y columns fija el ancho de cada una.\n//\n// La tarjeta NO se pica entera (la regla de la casa: una acción, un botón): para abrir el registro, onOpen pone su botón.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaRecordCard con defaultProps y\n// styleOverrides de sus partes: root, header, avatar, titles, status, body, group, fact, highlight, footer, details.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useId, useState} from 'react';\nimport Avatar from '@mui/material/Avatar';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Collapse from '@mui/material/Collapse';\nimport IconButton from '@mui/material/IconButton';\nimport Paper from '@mui/material/Paper';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport ExpandMoreRoundedIcon from '@mui/icons-material/ExpandMoreRounded';\nimport OpenInNewRoundedIcon from '@mui/icons-material/OpenInNewRounded';\n\nimport {initialsOf} from '@/appShell/menuItemText.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport ActionsMenu from '@/ui/actions/ActionsMenu.jsx';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaRecordCard)\nconst THEME_NAME = 'CalcitaRecordCard';\nconst RecordCardRoot = piecePart(THEME_NAME, 'Root', Paper);\nconst RecordCardHeader = piecePart(THEME_NAME, 'Header', Stack);\nconst RecordCardAvatar = piecePart(THEME_NAME, 'Avatar', Avatar);\nconst RecordCardTitles = piecePart(THEME_NAME, 'Titles', Box);\nconst RecordCardStatus = piecePart(THEME_NAME, 'Status', Stack);\nconst RecordCardBody = piecePart(THEME_NAME, 'Body', Box);\nconst RecordCardGroup = piecePart(THEME_NAME, 'Group', Box);\nconst RecordCardFact = piecePart(THEME_NAME, 'Fact', Box);\nconst RecordCardHighlight = piecePart(THEME_NAME, 'Highlight', Box);\nconst RecordCardFooter = piecePart(THEME_NAME, 'Footer', Stack);\nconst RecordCardDetails = piecePart(THEME_NAME, 'Details', Box);\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode} props.title el nombre del registro, ya traducido\n * @param {import('react').ReactNode} [props.eyebrow] arriba del título: el folio o el tipo\n * @param {import('react').ReactNode} [props.subtitle] abajo del título\n * @param {string|import('react').ReactNode} [props.avatar] un texto (de él salen las iniciales) o un ícono\n * @param {import('react').ReactNode} [props.status] a la derecha: StatusChip, IconBadge…\n * @param {Parameters<typeof import('@/ui/actions/ActionsMenu.jsx').default>[0]['actions']} [props.actions] el menú «⋯», con sus secciones,\n * separadores, ligas y submenús (los renglones de ActionsMenu)\n * @param {Array<{key?: string, title?: import('react').ReactNode, facts?: Array<{label: import('react').ReactNode, value: import('react').ReactNode, emphasis?: boolean}>, content?: import('react').ReactNode}>} [props.groups]\n * los datos, en grupos; emphasis los pone en negritas; content en lugar de facts para un grupo libre (una barra, unas\n * insignias, un enlace)\n * @param {import('react').ReactNode} [props.header] un encabezado propio en lugar del de la casa (avatar, títulos, estatus)\n * @param {import('react').ReactNode} [props.children] contenido libre entre el cuerpo y lo de abajo\n * @param {{label: import('react').ReactNode, value: import('react').ReactNode, caption?: import('react').ReactNode}} [props.highlight] el dato principal\n * @param {import('react').ReactNode} [props.trailing] la última columna del cuerpo, después de los grupos y del dato principal\n * (el estatus o unos botones, cuando el orden obligatorio los pone al final)\n * @param {string} [props.columns] en escritorio, el ancho de cada columna del cuerpo como en CSS ('1.2fr 1fr 1fr auto'); por\n * omisión, los grupos a partes iguales y el dato principal y trailing a su medida\n * @param {import('react').ReactNode} [props.footer] abajo, a todo lo ancho\n * @param {import('react').ReactNode} [props.details] lo que se despliega con «Ver detalle»\n * @param {string} [props.detailsLabel] ya traducido; por omisión «Ver detalle»\n * @param {boolean} [props.defaultDetailsOpen]\n * @param {(isOpen: boolean) => void} [props.onDetailsToggle]\n * @param {() => void} [props.onOpen] el botón para abrir el registro (su detalle)\n * @param {string} [props.openLabel] ya traducido: el nombre de ese botón («Abrir el pedido P-1203»)\n * @param {object} [props.sx]\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction RecordCardContent(props) {\n const {\n title, eyebrow, subtitle, avatar, status, actions, groups = [], highlight, trailing, columns, footer, details, detailsLabel, defaultDetailsOpen = false,\n onDetailsToggle, onOpen, openLabel, header, children, sx, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const titleId = useId();\n const detailsId = useId();\n const [isDetailsOpen, setIsDetailsOpen] = useState(defaultDetailsOpen);\n const toggleDetails = () => {\n setIsDetailsOpen((current) => !current);\n onDetailsToggle?.(!isDetailsOpen);\n };\n const hasBody = groups.length > 0 || highlight || trailing;\n // las columnas en escritorio: las que se pidan, o los grupos a partes iguales y lo demás a su medida\n const desktopColumns = columns ?? `${groups.length > 0 ? `repeat(${groups.length}, minmax(0, 1fr))` : ''}${highlight ? ' auto' : ''}${trailing ? ' auto' : ''}`.trim();\n\n return (\n <RecordCardRoot variant=\"outlined\" component=\"article\" aria-labelledby={titleId} ownSx={{p: {xs: 2, sm: 2.5}, minWidth: 0}} sx={sx}>\n {/* en el teléfono el estatus baja abajo del título (si no, le quitaba medio ancho) y arriba quedan los botones */}\n {header ?? (\n <RecordCardHeader direction=\"row\" ownSx={{gap: 1.5, alignItems: 'flex-start', flexWrap: {xs: 'wrap', sm: 'nowrap'}}}>\n {avatar && (\n <RecordCardAvatar ownSx={{width: 44, height: 44, bgcolor: 'action.selected', color: 'text.primary', fontSize: 16, fontWeight: 600}}>\n {typeof avatar === 'string' ? initialsOf(avatar) : avatar}\n </RecordCardAvatar>\n )}\n <RecordCardTitles ownSx={{flex: 1, minWidth: 0, order: 1}}>\n {eyebrow && <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\" sx={{fontVariantNumeric: 'tabular-nums'}}>{eyebrow}</Typography>}\n <Typography id={titleId} variant=\"subtitle1\" component=\"h3\" sx={{fontWeight: 600, overflowWrap: 'anywhere'}}>{title}</Typography>\n {subtitle && <Typography variant=\"body2\" color=\"text.secondary\">{subtitle}</Typography>}\n </RecordCardTitles>\n {status && (\n <RecordCardStatus direction=\"row\" ownSx={{\n gap: 0.75, alignItems: 'center', flexWrap: 'wrap', order: {xs: 3, sm: 2},\n flexBasis: {xs: '100%', sm: 'auto'}, justifyContent: {xs: 'flex-start', sm: 'flex-end'}, maxWidth: {sm: '50%'},\n }}>\n {status}\n </RecordCardStatus>\n )}\n <Stack direction=\"row\" sx={{gap: 0.25, alignItems: 'center', order: {xs: 2, sm: 3}, flexShrink: 0}}>\n {onOpen && (\n <Tooltip title={openLabel ?? t('recordCard.open')}>\n <IconButton size=\"small\" aria-label={openLabel ?? t('recordCard.open')} onClick={onOpen}><OpenInNewRoundedIcon fontSize=\"small\" /></IconButton>\n </Tooltip>\n )}\n {actions?.length > 0 && <ActionsMenu label={t('recordCard.actions')} actions={actions} size=\"small\" />}\n </Stack>\n </RecordCardHeader>\n )}\n\n {hasBody && (\n <RecordCardBody ownSx={{\n mt: 2, display: 'grid', gap: {xs: 1.5, md: 3}, alignItems: 'start',\n // en escritorio los grupos lado a lado y el dato principal al final; en el teléfono, uno debajo de otro\n gridTemplateColumns: {xs: '1fr', md: desktopColumns},\n }}>\n {groups.map((group, groupIndex) => (\n <RecordCardGroup key={group.key ?? groupIndex} ownSx={{\n minWidth: 0, pt: {xs: groupIndex > 0 ? 1.5 : 0, md: 0}, borderTop: {xs: groupIndex > 0 ? 1 : 0, md: 0}, borderColor: 'divider',\n }}>\n {group.title && <Typography variant=\"overline\" color=\"text.secondary\" component=\"p\" sx={{lineHeight: 1.8}}>{group.title}</Typography>}\n {group.content ?? (\n <Box component=\"dl\" sx={{m: 0, display: 'grid', gridTemplateColumns: 'auto 1fr', columnGap: 1.5, rowGap: 0.5}}>\n {(group.facts ?? []).map((fact, factIndex) => (\n <RecordCardFact key={factIndex} ownSx={{display: 'contents'}}>\n <Typography component=\"dt\" variant=\"body2\" color=\"text.secondary\">{fact.label}</Typography>\n <Typography component=\"dd\" variant=\"body2\" sx={{m: 0, textAlign: 'right', fontVariantNumeric: 'tabular-nums', fontWeight: fact.emphasis ? 600 : 400, overflowWrap: 'anywhere'}}>\n {fact.value}\n </Typography>\n </RecordCardFact>\n ))}\n </Box>\n )}\n </RecordCardGroup>\n ))}\n {highlight && (\n <RecordCardHighlight ownSx={{\n textAlign: {xs: 'left', md: 'right'}, pl: {md: 3}, borderLeft: {md: 1}, borderTop: {xs: 1, md: 0}, pt: {xs: 1.5, md: 0}, borderColor: 'divider',\n }}>\n <Typography variant=\"overline\" color=\"text.secondary\" component=\"p\" sx={{lineHeight: 1.8}}>{highlight.label}</Typography>\n <Typography variant=\"h5\" component=\"p\" sx={{fontWeight: 700, fontVariantNumeric: 'tabular-nums', whiteSpace: 'nowrap'}}>{highlight.value}</Typography>\n {highlight.caption && <Typography variant=\"caption\" color=\"text.secondary\" component=\"p\">{highlight.caption}</Typography>}\n </RecordCardHighlight>\n )}\n {trailing && (\n <Box sx={{minWidth: 0, alignSelf: 'center', borderTop: {xs: 1, md: 0}, pt: {xs: 1.5, md: 0}, borderColor: 'divider'}}>{trailing}</Box>\n )}\n </RecordCardBody>\n )}\n\n {children}\n {(footer || details) && (\n <RecordCardFooter direction=\"row\" ownSx={{mt: 2, gap: 1, alignItems: 'center', flexWrap: 'wrap'}}>\n <Box sx={{flex: 1, minWidth: 0}}>{footer}</Box>\n {details && (\n <Button size=\"small\" onClick={toggleDetails} aria-expanded={isDetailsOpen} aria-controls={detailsId}\n endIcon={<ExpandMoreRoundedIcon sx={{transform: isDetailsOpen ? 'rotate(180deg)' : 'none', transition: 'transform 200ms'}} />}>\n {isDetailsOpen ? t('recordCard.hideDetails') : (detailsLabel ?? t('recordCard.showDetails'))}\n </Button>\n )}\n </RecordCardFooter>\n )}\n {details && (\n <Collapse in={isDetailsOpen} unmountOnExit>\n <RecordCardDetails id={detailsId} ownSx={{mt: 2, pt: 2, borderTop: 1, borderColor: 'divider'}}>{details}</RecordCardDetails>\n </Collapse>\n )}\n </RecordCardRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst RecordCard = withPieceSlots(RecordCardContent, THEME_NAME);\nexport default RecordCard;\n"],"names":[],"mappings":"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"}
|
|
@@ -4,12 +4,16 @@ import Box from "@mui/material/Box";
|
|
|
4
4
|
import Paper from "@mui/material/Paper";
|
|
5
5
|
import Skeleton from "@mui/material/Skeleton";
|
|
6
6
|
import Stack from "@mui/material/Stack";
|
|
7
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
|
|
7
8
|
import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
|
|
8
9
|
import { warnUnknownProps } from "../../toolkit/unknownProps.js";
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
const THEME_NAME = "CalcitaRecordCardSkeleton";
|
|
11
|
+
const RecordCardSkeletonRoot = piecePart(THEME_NAME, "Root", Paper);
|
|
12
|
+
function RecordCardSkeletonContent(props) {
|
|
13
|
+
const { groups = 2, factsPerGroup = 3, withAvatar = true, withHighlight = true, sx, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
14
|
+
warnUnknownProps(THEME_NAME, unknownProps);
|
|
11
15
|
const { t } = useToolkitTranslation("common", texts);
|
|
12
|
-
return /* @__PURE__ */ jsxs(
|
|
16
|
+
return /* @__PURE__ */ jsxs(RecordCardSkeletonRoot, { variant: "outlined", role: "status", "aria-label": t("recordCard.loading"), ownSx: { p: { xs: 2, sm: 2.5 } }, sx, children: [
|
|
13
17
|
/* @__PURE__ */ jsxs(Stack, { direction: "row", sx: { gap: 1.5, alignItems: "center" }, children: [
|
|
14
18
|
withAvatar && /* @__PURE__ */ jsx(Skeleton, { variant: "circular", width: 44, height: 44 }),
|
|
15
19
|
/* @__PURE__ */ jsxs(Box, { sx: { flex: 1 }, children: [
|
|
@@ -27,6 +31,7 @@ function RecordCardSkeleton({ groups = 2, factsPerGroup = 3, withAvatar = true,
|
|
|
27
31
|
] })
|
|
28
32
|
] });
|
|
29
33
|
}
|
|
34
|
+
const RecordCardSkeleton = withPieceSlots(RecordCardSkeletonContent, THEME_NAME);
|
|
30
35
|
export {
|
|
31
36
|
RecordCardSkeleton as default
|
|
32
37
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecordCardSkeleton.js","sources":["../../../src/ui/cards/RecordCardSkeleton.jsx"],"sourcesContent":["// El esqueleto de RecordCard mientras llega la lista: la misma forma (avatar, títulos, grupos de datos y dato principal),\n// así la página no brinca cuando aparecen las tarjetas de verdad. Para un lector de pantalla dice «Cargando».\n//\n// Genérico del paquete: function (regla de la casa).\nimport Box from '@mui/material/Box';\nimport Paper from '@mui/material/Paper';\nimport Skeleton from '@mui/material/Skeleton';\nimport Stack from '@mui/material/Stack';\n\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n/**\n * @param {object} props\n * @param {number} [props.groups] cuántos grupos de datos (como los de la tarjeta)\n * @param {number} [props.factsPerGroup]\n * @param {boolean} [props.withAvatar]\n * @param {boolean} [props.withHighlight]\n * @param {object} [props.sx]\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\
|
|
1
|
+
{"version":3,"file":"RecordCardSkeleton.js","sources":["../../../src/ui/cards/RecordCardSkeleton.jsx"],"sourcesContent":["// El esqueleto de RecordCard mientras llega la lista: la misma forma (avatar, títulos, grupos de datos y dato principal),\n// así la página no brinca cuando aparecen las tarjetas de verdad. Para un lector de pantalla dice «Cargando».\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaRecordCardSkeleton con defaultProps (p. ej.\n// {groups: 3}), styleOverrides de su parte root y slots/slotProps.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Box from '@mui/material/Box';\nimport Paper from '@mui/material/Paper';\nimport Skeleton from '@mui/material/Skeleton';\nimport Stack from '@mui/material/Stack';\n\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y su parte (theme.components.CalcitaRecordCardSkeleton)\nconst THEME_NAME = 'CalcitaRecordCardSkeleton';\nconst RecordCardSkeletonRoot = piecePart(THEME_NAME, 'Root', Paper);\n\n/**\n * @param {object} props\n * @param {number} [props.groups] cuántos grupos de datos (como los de la tarjeta)\n * @param {number} [props.factsPerGroup]\n * @param {boolean} [props.withAvatar]\n * @param {boolean} [props.withHighlight]\n * @param {object} [props.sx]\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction RecordCardSkeletonContent(props) {\n const {groups = 2, factsPerGroup = 3, withAvatar = true, withHighlight = true, sx, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n return (\n <RecordCardSkeletonRoot variant=\"outlined\" role=\"status\" aria-label={t('recordCard.loading')} ownSx={{p: {xs: 2, sm: 2.5}}} sx={sx}>\n <Stack direction=\"row\" sx={{gap: 1.5, alignItems: 'center'}}>\n {withAvatar && <Skeleton variant=\"circular\" width={44} height={44} />}\n <Box sx={{flex: 1}}>\n <Skeleton width=\"20%\" />\n <Skeleton width=\"45%\" height={28} />\n </Box>\n <Skeleton variant=\"rounded\" width={88} height={24} />\n </Stack>\n <Box sx={{mt: 2, display: 'grid', gap: 3, gridTemplateColumns: {xs: '1fr', md: `repeat(${groups}, 1fr)${withHighlight ? ' 140px' : ''}`}}}>\n {Array.from({length: groups}, (unused, groupIndex) => (\n <Box key={groupIndex}>\n {Array.from({length: factsPerGroup}, (unusedFact, factIndex) => <Skeleton key={factIndex} />)}\n </Box>\n ))}\n {withHighlight && <Box><Skeleton width=\"60%\" /><Skeleton height={36} /></Box>}\n </Box>\n </RecordCardSkeletonRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst RecordCardSkeleton = withPieceSlots(RecordCardSkeletonContent, THEME_NAME);\nexport default RecordCardSkeleton;\n"],"names":[],"mappings":";;;;;;;;;AAiBA,MAAM,aAAa;AACnB,MAAM,yBAAyB,UAAU,YAAY,QAAQ,KAAK;AAWlE,SAAS,0BAA0B,OAAO;AACtC,QAAM,EAAC,SAAS,GAAG,gBAAgB,GAAG,aAAa,MAAM,gBAAgB,MAAM,IAAI,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AAC5I,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,SACI,qBAAC,0BAAuB,SAAQ,YAAW,MAAK,UAAS,cAAY,EAAE,oBAAoB,GAAG,OAAO,EAAC,GAAG,EAAC,IAAI,GAAG,IAAI,IAAA,EAAG,GAAI,IACxH,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAM,WAAU,OAAM,IAAI,EAAC,KAAK,KAAK,YAAY,SAAA,GAC7C,UAAA;AAAA,MAAA,kCAAe,UAAA,EAAS,SAAQ,YAAW,OAAO,IAAI,QAAQ,IAAI;AAAA,2BAClE,KAAA,EAAI,IAAI,EAAC,MAAM,KACZ,UAAA;AAAA,QAAA,oBAAC,UAAA,EAAS,OAAM,MAAA,CAAM;AAAA,QACtB,oBAAC,UAAA,EAAS,OAAM,OAAM,QAAQ,GAAA,CAAI;AAAA,MAAA,GACtC;AAAA,0BACC,UAAA,EAAS,SAAQ,WAAU,OAAO,IAAI,QAAQ,GAAA,CAAI;AAAA,IAAA,GACvD;AAAA,IACA,qBAAC,OAAI,IAAI,EAAC,IAAI,GAAG,SAAS,QAAQ,KAAK,GAAG,qBAAqB,EAAC,IAAI,OAAO,IAAI,UAAU,MAAM,SAAS,gBAAgB,WAAW,EAAE,GAAA,EAAE,GAClI,UAAA;AAAA,MAAA,MAAM,KAAK,EAAC,QAAQ,OAAA,GAAS,CAAC,QAAQ,eACnC,oBAAC,KAAA,EACI,UAAA,MAAM,KAAK,EAAC,QAAQ,cAAA,GAAgB,CAAC,YAAY,cAAc,oBAAC,UAAA,CAAA,GAAc,SAAW,CAAE,EAAA,GADtF,UAEV,CACH;AAAA,MACA,sCAAkB,KAAA,EAAI,UAAA;AAAA,QAAA,oBAAC,UAAA,EAAS,OAAM,MAAA,CAAM;AAAA,QAAE,oBAAC,UAAA,EAAS,QAAQ,GAAA,CAAI;AAAA,MAAA,EAAA,CAAE;AAAA,IAAA,EAAA,CAC3E;AAAA,EAAA,GACJ;AAER;AAGA,MAAM,qBAAqB,eAAe,2BAA2B,UAAU;"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import Typography from "@mui/material/Typography";
|
|
4
|
-
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
4
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
|
|
5
5
|
import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
|
|
6
6
|
import { warnUnknownProps } from "../../toolkit/unknownProps.js";
|
|
7
7
|
import { countdownClockOf } from "./countdownParts.js";
|
|
8
8
|
import { useCountdown } from "./useCountdown.js";
|
|
9
9
|
const THEME_NAME = "CalcitaCountdown";
|
|
10
10
|
const CountdownRoot = piecePart(THEME_NAME, "Root", Typography);
|
|
11
|
-
function
|
|
11
|
+
function CountdownContent(props) {
|
|
12
12
|
const {
|
|
13
13
|
until,
|
|
14
14
|
label,
|
|
@@ -32,6 +32,7 @@ function Countdown(props) {
|
|
|
32
32
|
}
|
|
33
33
|
return /* @__PURE__ */ jsx(CountdownRoot, { variant, role: "timer", "aria-label": label, ownSx: { fontVariantNumeric: "tabular-nums" }, sx, children: countdownClockOf(parts, { daysLabel: t("countdown.daysShort"), showSeconds }) });
|
|
34
34
|
}
|
|
35
|
+
const Countdown = withPieceSlots(CountdownContent, THEME_NAME);
|
|
35
36
|
export {
|
|
36
37
|
Countdown as default
|
|
37
38
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Countdown.js","sources":["../../../src/ui/countdown/Countdown.jsx"],"sourcesContent":["// La cuenta regresiva ya pintada: «02:14:30» hasta un momento (el cierre de unas inscripciones, el inicio de una cita, el fin de\n// una oferta), con días cuando faltan («3 d 02:14:30»), y lo que dice al llegar a cero («Ya terminó»). Avisa con onComplete\n// una sola vez.\n//\n// Para un lector de pantalla es un temporizador (role=\"timer\"): no anuncia cada segundo, sí el final (role=\"status\").\n// Con children como función se pinta a su manera: children(parts) recibe {days, hours, minutes, seconds, isOver}.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaCountdown con defaultProps y\n// styleOverrides de su parte root.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Typography from '@mui/material/Typography';\n\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {countdownClockOf} from '@/ui/countdown/countdownParts.js';\nimport {useCountdown} from '@/ui/countdown/useCountdown.js';\n\n// el nombre de la pieza en el tema y su parte (theme.components.CalcitaCountdown)\nconst THEME_NAME = 'CalcitaCountdown';\nconst CountdownRoot = piecePart(THEME_NAME, 'Root', Typography);\n\n/**\n * @param {object} props\n * @param {string|number|Date} props.until el momento: un instante en texto, un Date o milisegundos\n * @param {string} [props.label] ya traducido: qué se cuenta («Tiempo para que cierren las inscripciones»), para un lector de pantalla\n * @param {() => void} [props.onComplete] al llegar a cero (una vez)\n * @param {import('react').ReactNode} [props.completedText] lo que dice al terminar; por omisión «Ya terminó»\n * @param {boolean} [props.showSeconds] por omisión, sí\n * @param {(parts: {days: number, hours: number, minutes: number, seconds: number, totalSeconds: number, isOver: boolean}) => import('react').ReactNode} [props.children]\n * para pintarla a su manera\n * @param {import('@mui/material/Typography').TypographyProps['variant']} [props.variant] por omisión body1\n * @param {object} [props.sx]\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\
|
|
1
|
+
{"version":3,"file":"Countdown.js","sources":["../../../src/ui/countdown/Countdown.jsx"],"sourcesContent":["// La cuenta regresiva ya pintada: «02:14:30» hasta un momento (el cierre de unas inscripciones, el inicio de una cita, el fin de\n// una oferta), con días cuando faltan («3 d 02:14:30»), y lo que dice al llegar a cero («Ya terminó»). Avisa con onComplete\n// una sola vez.\n//\n// Para un lector de pantalla es un temporizador (role=\"timer\"): no anuncia cada segundo, sí el final (role=\"status\").\n// Con children como función se pinta a su manera: children(parts) recibe {days, hours, minutes, seconds, isOver}.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaCountdown con defaultProps y\n// styleOverrides de su parte root.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Typography from '@mui/material/Typography';\n\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {countdownClockOf} from '@/ui/countdown/countdownParts.js';\nimport {useCountdown} from '@/ui/countdown/useCountdown.js';\n\n// el nombre de la pieza en el tema y su parte (theme.components.CalcitaCountdown)\nconst THEME_NAME = 'CalcitaCountdown';\nconst CountdownRoot = piecePart(THEME_NAME, 'Root', Typography);\n\n/**\n * @param {object} props\n * @param {string|number|Date} props.until el momento: un instante en texto, un Date o milisegundos\n * @param {string} [props.label] ya traducido: qué se cuenta («Tiempo para que cierren las inscripciones»), para un lector de pantalla\n * @param {() => void} [props.onComplete] al llegar a cero (una vez)\n * @param {import('react').ReactNode} [props.completedText] lo que dice al terminar; por omisión «Ya terminó»\n * @param {boolean} [props.showSeconds] por omisión, sí\n * @param {(parts: {days: number, hours: number, minutes: number, seconds: number, totalSeconds: number, isOver: boolean}) => import('react').ReactNode} [props.children]\n * para pintarla a su manera\n * @param {import('@mui/material/Typography').TypographyProps['variant']} [props.variant] por omisión body1\n * @param {object} [props.sx]\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction CountdownContent(props) {\n const {\n until, label, onComplete, completedText, showSeconds = true, children, variant = 'body1', sx, texts,\n ...unknownProps\n } = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const {parts, isOver} = useCountdown(until, {onComplete});\n\n if (typeof children === 'function') {\n return children(parts);\n }\n if (isOver) {\n return (\n <CountdownRoot variant={variant} role=\"status\" ownSx={{fontVariantNumeric: 'tabular-nums'}} sx={sx}>\n {completedText ?? t('countdown.done')}\n </CountdownRoot>\n );\n }\n return (\n <CountdownRoot variant={variant} role=\"timer\" aria-label={label} ownSx={{fontVariantNumeric: 'tabular-nums'}} sx={sx}>\n {countdownClockOf(parts, {daysLabel: t('countdown.daysShort'), showSeconds})}\n </CountdownRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst Countdown = withPieceSlots(CountdownContent, THEME_NAME);\nexport default Countdown;\n"],"names":[],"mappings":";;;;;;;;AAoBA,MAAM,aAAa;AACnB,MAAM,gBAAgB,UAAU,YAAY,QAAQ,UAAU;AAe9D,SAAS,iBAAiB,OAAO;AAC7B,QAAM;AAAA,IACF;AAAA,IAAO;AAAA,IAAO;AAAA,IAAY;AAAA,IAAe,cAAc;AAAA,IAAM;AAAA,IAAU,UAAU;AAAA,IAAS;AAAA,IAAI;AAAA,IAC9F,GAAG;AAAA,EAAA,IACH,cAAc,OAAO,UAAU;AACnC,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,QAAM,EAAC,OAAO,OAAA,IAAU,aAAa,OAAO,EAAC,YAAW;AAExD,MAAI,OAAO,aAAa,YAAY;AAChC,WAAO,SAAS,KAAK;AAAA,EACzB;AACA,MAAI,QAAQ;AACR,WACI,oBAAC,eAAA,EAAc,SAAkB,MAAK,UAAS,OAAO,EAAC,oBAAoB,eAAA,GAAiB,IACvF,UAAA,iBAAiB,EAAE,gBAAgB,GACxC;AAAA,EAER;AACA,SACI,oBAAC,iBAAc,SAAkB,MAAK,SAAQ,cAAY,OAAO,OAAO,EAAC,oBAAoB,kBAAiB,IACzG,UAAA,iBAAiB,OAAO,EAAC,WAAW,EAAE,qBAAqB,GAAG,YAAA,CAAY,GAC/E;AAER;AAGA,MAAM,YAAY,eAAe,kBAAkB,UAAU;"}
|
|
@@ -6,7 +6,7 @@ import Stack from "@mui/material/Stack";
|
|
|
6
6
|
import Box from "@mui/material/Box";
|
|
7
7
|
import FileDownloadOutlinedIcon from "@mui/icons-material/FileDownloadOutlined";
|
|
8
8
|
import OpenInNewRoundedIcon from "@mui/icons-material/OpenInNewRounded";
|
|
9
|
-
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
9
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
|
|
10
10
|
import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
|
|
11
11
|
import { warnUnknownProps } from "../../toolkit/unknownProps.js";
|
|
12
12
|
import ContentDialog from "../layout/ContentDialog.js";
|
|
@@ -30,7 +30,7 @@ function usePdfUrl(src) {
|
|
|
30
30
|
}
|
|
31
31
|
return typeof src === "string" && src ? src : null;
|
|
32
32
|
}
|
|
33
|
-
function
|
|
33
|
+
function PdfViewerDialogContent(props) {
|
|
34
34
|
const { open, onClose, title, src, fileName, actions, onDownload, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
35
35
|
warnUnknownProps(THEME_NAME, unknownProps);
|
|
36
36
|
const { t } = useToolkitTranslation("common", texts);
|
|
@@ -75,6 +75,7 @@ function PdfViewerDialog(props) {
|
|
|
75
75
|
) : /* @__PURE__ */ jsx(Box, { sx: { height: { xs: "62vh", md: "72vh" }, borderRadius: 1, bgcolor: "action.hover" } })
|
|
76
76
|
] });
|
|
77
77
|
}
|
|
78
|
+
const PdfViewerDialog = withPieceSlots(PdfViewerDialogContent, THEME_NAME);
|
|
78
79
|
export {
|
|
79
80
|
PdfViewerDialog as default
|
|
80
81
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PdfViewerDialog.js","sources":["../../../src/ui/documents/PdfViewerDialog.jsx"],"sourcesContent":["// Un PDF en una ventana: el aviso de privacidad, un contrato, un estado de cuenta. Lo pinta el visor del navegador (sin\n// librerías: nada que descargar ni que actualizar) en la hoja de lectura de la casa (ContentDialog), con «Abrir en otra\n// pestaña» y «Descargar» arriba.\n//\n// OJO: en el iPhone el visor dentro de la página enseña solo la primera hoja y en algunos navegadores no se pinta; por eso\n// los dos botones siempre están a la vista: abrirlo aparte o bajarlo funciona en todos.\n//\n// src es la dirección del PDF o el archivo mismo (un Blob que mandó el API, un File elegido): del archivo se arma una\n// dirección en el navegador, sin subirlo, y se libera al cerrar.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaPdfViewerDialog con defaultProps y\n// styleOverrides de sus partes: actions, frame.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useState} from 'react';\nimport Button from '@mui/material/Button';\nimport Stack from '@mui/material/Stack';\nimport Box from '@mui/material/Box';\nimport FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';\nimport OpenInNewRoundedIcon from '@mui/icons-material/OpenInNewRounded';\n\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport ContentDialog from '@/ui/layout/ContentDialog.jsx';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaPdfViewerDialog)\nconst THEME_NAME = 'CalcitaPdfViewerDialog';\nconst ViewerActions = piecePart(THEME_NAME, 'Actions', Stack);\nconst ViewerFrame = piecePart(THEME_NAME, 'Frame', 'iframe');\n\n/**\n * La dirección del PDF: la que llega tal cual, o una del navegador para un archivo (se libera al cambiarlo o al cerrar).\n *\n * @param {string|Blob|null|undefined} src\n * @returns {string|null}\n */\nfunction usePdfUrl(src) {\n const [blobUrl, setBlobUrl] = useState(null);\n const isBlob = typeof Blob !== 'undefined' && src instanceof Blob;\n\n useEffect(() => {\n if (!isBlob) {\n setBlobUrl(null);\n return undefined;\n }\n const url = URL.createObjectURL(src);\n setBlobUrl(url);\n return () => URL.revokeObjectURL(url);\n }, [isBlob, src]);\n\n if (isBlob) {\n return blobUrl;\n }\n return typeof src === 'string' && src ? src : null;\n}\n\n/**\n * @param {object} props\n * @param {boolean} props.open\n * @param {() => void} props.onClose\n * @param {string} props.title ya traducido: qué documento es\n * @param {string|Blob|null} props.src la dirección del PDF o el archivo (Blob o File)\n * @param {string} [props.fileName] con qué nombre se descarga (por omisión, el título con .pdf)\n * @param {import('react').ReactNode} [props.actions] botones suyos junto a «Abrir en otra pestaña» y «Descargar»\n * @param {() => void} [props.onDownload] al descargar (para registrarlo, por ejemplo)\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\
|
|
1
|
+
{"version":3,"file":"PdfViewerDialog.js","sources":["../../../src/ui/documents/PdfViewerDialog.jsx"],"sourcesContent":["// Un PDF en una ventana: el aviso de privacidad, un contrato, un estado de cuenta. Lo pinta el visor del navegador (sin\n// librerías: nada que descargar ni que actualizar) en la hoja de lectura de la casa (ContentDialog), con «Abrir en otra\n// pestaña» y «Descargar» arriba.\n//\n// OJO: en el iPhone el visor dentro de la página enseña solo la primera hoja y en algunos navegadores no se pinta; por eso\n// los dos botones siempre están a la vista: abrirlo aparte o bajarlo funciona en todos.\n//\n// src es la dirección del PDF o el archivo mismo (un Blob que mandó el API, un File elegido): del archivo se arma una\n// dirección en el navegador, sin subirlo, y se libera al cerrar.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaPdfViewerDialog con defaultProps y\n// styleOverrides de sus partes: actions, frame.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useState} from 'react';\nimport Button from '@mui/material/Button';\nimport Stack from '@mui/material/Stack';\nimport Box from '@mui/material/Box';\nimport FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';\nimport OpenInNewRoundedIcon from '@mui/icons-material/OpenInNewRounded';\n\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport ContentDialog from '@/ui/layout/ContentDialog.jsx';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaPdfViewerDialog)\nconst THEME_NAME = 'CalcitaPdfViewerDialog';\nconst ViewerActions = piecePart(THEME_NAME, 'Actions', Stack);\nconst ViewerFrame = piecePart(THEME_NAME, 'Frame', 'iframe');\n\n/**\n * La dirección del PDF: la que llega tal cual, o una del navegador para un archivo (se libera al cambiarlo o al cerrar).\n *\n * @param {string|Blob|null|undefined} src\n * @returns {string|null}\n */\nfunction usePdfUrl(src) {\n const [blobUrl, setBlobUrl] = useState(null);\n const isBlob = typeof Blob !== 'undefined' && src instanceof Blob;\n\n useEffect(() => {\n if (!isBlob) {\n setBlobUrl(null);\n return undefined;\n }\n const url = URL.createObjectURL(src);\n setBlobUrl(url);\n return () => URL.revokeObjectURL(url);\n }, [isBlob, src]);\n\n if (isBlob) {\n return blobUrl;\n }\n return typeof src === 'string' && src ? src : null;\n}\n\n/**\n * @param {object} props\n * @param {boolean} props.open\n * @param {() => void} props.onClose\n * @param {string} props.title ya traducido: qué documento es\n * @param {string|Blob|null} props.src la dirección del PDF o el archivo (Blob o File)\n * @param {string} [props.fileName] con qué nombre se descarga (por omisión, el título con .pdf)\n * @param {import('react').ReactNode} [props.actions] botones suyos junto a «Abrir en otra pestaña» y «Descargar»\n * @param {() => void} [props.onDownload] al descargar (para registrarlo, por ejemplo)\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction PdfViewerDialogContent(props) {\n const {open, onClose, title, src, fileName, actions, onDownload, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const pdfUrl = usePdfUrl(open ? src : null);\n\n return (\n <ContentDialog open={open} onClose={onClose} title={title} texts={texts}>\n <ViewerActions direction=\"row\" ownSx={{gap: 1, flexWrap: 'wrap', mb: 2}}>\n <Button size=\"small\" variant=\"outlined\" startIcon={<OpenInNewRoundedIcon />} href={pdfUrl ?? undefined} target=\"_blank\"\n rel=\"noopener noreferrer\" disabled={!pdfUrl}>\n {t('pdfViewer.openInTab')}\n </Button>\n <Button size=\"small\" variant=\"outlined\" startIcon={<FileDownloadOutlinedIcon />} href={pdfUrl ?? undefined}\n download={fileName ?? `${title}.pdf`} disabled={!pdfUrl} onClick={onDownload}>\n {t('pdfViewer.download')}\n </Button>\n {actions}\n </ViewerActions>\n {pdfUrl ? (\n <ViewerFrame src={pdfUrl} title={title}\n ownSx={{display: 'block', width: '100%', height: {xs: '62vh', md: '72vh'}, border: 0, borderRadius: 1, bgcolor: 'action.hover'}} />\n ) : (\n <Box sx={{height: {xs: '62vh', md: '72vh'}, borderRadius: 1, bgcolor: 'action.hover'}} />\n )}\n </ContentDialog>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst PdfViewerDialog = withPieceSlots(PdfViewerDialogContent, THEME_NAME);\nexport default PdfViewerDialog;\n"],"names":[],"mappings":";;;;;;;;;;;;AA2BA,MAAM,aAAa;AACnB,MAAM,gBAAgB,UAAU,YAAY,WAAW,KAAK;AAC5D,MAAM,cAAc,UAAU,YAAY,SAAS,QAAQ;AAQ3D,SAAS,UAAU,KAAK;AACpB,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,SAAS,OAAO,SAAS,eAAe,eAAe;AAE7D,YAAU,MAAM;AACZ,QAAI,CAAC,QAAQ;AACT,iBAAW,IAAI;AACf,aAAO;AAAA,IACX;AACA,UAAM,MAAM,IAAI,gBAAgB,GAAG;AACnC,eAAW,GAAG;AACd,WAAO,MAAM,IAAI,gBAAgB,GAAG;AAAA,EACxC,GAAG,CAAC,QAAQ,GAAG,CAAC;AAEhB,MAAI,QAAQ;AACR,WAAO;AAAA,EACX;AACA,SAAO,OAAO,QAAQ,YAAY,MAAM,MAAM;AAClD;AAaA,SAAS,uBAAuB,OAAO;AACnC,QAAM,EAAC,MAAM,SAAS,OAAO,KAAK,UAAU,SAAS,YAAY,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AAC1H,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,QAAM,SAAS,UAAU,OAAO,MAAM,IAAI;AAE1C,SACI,qBAAC,eAAA,EAAc,MAAY,SAAkB,OAAc,OACvD,UAAA;AAAA,IAAA,qBAAC,eAAA,EAAc,WAAU,OAAM,OAAO,EAAC,KAAK,GAAG,UAAU,QAAQ,IAAI,EAAA,GACjE,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UAAO,MAAK;AAAA,UAAQ,SAAQ;AAAA,UAAW,+BAAY,sBAAA,EAAqB;AAAA,UAAI,MAAM,UAAU;AAAA,UAAW,QAAO;AAAA,UACvG,KAAI;AAAA,UAAsB,UAAU,CAAC;AAAA,UACxC,YAAE,qBAAqB;AAAA,QAAA;AAAA,MAAA;AAAA,MAE5B;AAAA,QAAC;AAAA,QAAA;AAAA,UAAO,MAAK;AAAA,UAAQ,SAAQ;AAAA,UAAW,+BAAY,0BAAA,EAAyB;AAAA,UAAI,MAAM,UAAU;AAAA,UACzF,UAAU,YAAY,GAAG,KAAK;AAAA,UAAQ,UAAU,CAAC;AAAA,UAAQ,SAAS;AAAA,UACrE,YAAE,oBAAoB;AAAA,QAAA;AAAA,MAAA;AAAA,MAE1B;AAAA,IAAA,GACL;AAAA,IACC,SACG;AAAA,MAAC;AAAA,MAAA;AAAA,QAAY,KAAK;AAAA,QAAQ;AAAA,QACb,OAAO,EAAC,SAAS,SAAS,OAAO,QAAQ,QAAQ,EAAC,IAAI,QAAQ,IAAI,UAAS,QAAQ,GAAG,cAAc,GAAG,SAAS,eAAA;AAAA,MAAc;AAAA,IAAA,IAE3I,oBAAC,KAAA,EAAI,IAAI,EAAC,QAAQ,EAAC,IAAI,QAAQ,IAAI,UAAS,cAAc,GAAG,SAAS,iBAAc,CAAG;AAAA,EAAA,GAE/F;AAER;AAGA,MAAM,kBAAkB,eAAe,wBAAwB,UAAU;"}
|
|
@@ -10,13 +10,13 @@ import TextField from "@mui/material/TextField";
|
|
|
10
10
|
import Typography from "@mui/material/Typography";
|
|
11
11
|
import DateRangeOutlinedIcon from "@mui/icons-material/DateRangeOutlined";
|
|
12
12
|
import { useFormatters } from "../../toolkit/useFormatters.js";
|
|
13
|
-
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
13
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
|
|
14
14
|
import { warnUnknownProps } from "../../toolkit/unknownProps.js";
|
|
15
15
|
const THEME_NAME = "CalcitaDateRangeFilter";
|
|
16
16
|
const RangeChip = piecePart(THEME_NAME, "Chip", Chip);
|
|
17
17
|
const RangePanel = piecePart(THEME_NAME, "Panel", Stack);
|
|
18
18
|
const RangeActions = piecePart(THEME_NAME, "Actions", Stack);
|
|
19
|
-
function
|
|
19
|
+
function DateRangeFilterContent(props) {
|
|
20
20
|
const { from = "", to = "", onChange, label, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
21
21
|
warnUnknownProps(THEME_NAME, unknownProps);
|
|
22
22
|
const { t } = useToolkitTranslation("table", texts);
|
|
@@ -89,6 +89,7 @@ function DateRangeFilter(props) {
|
|
|
89
89
|
] }) })
|
|
90
90
|
] });
|
|
91
91
|
}
|
|
92
|
+
const DateRangeFilter = withPieceSlots(DateRangeFilterContent, THEME_NAME);
|
|
92
93
|
export {
|
|
93
94
|
DateRangeFilter as default
|
|
94
95
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateRangeFilter.js","sources":["../../../src/ui/filters/DateRangeFilter.jsx"],"sourcesContent":["// Un rango de fechas personalizado, como chip al lado de los accesos rápidos.\n//\n// Viaja como AAAA-MM-DD (día, no instante). Convertirlo a \"inicio del día\" y \"fin del día\" lo hace el SERVIDOR con la\n// zona del negocio: si lo hiciera el navegador con la suya, alguien en otra zona pediría otro rango sin saberlo.\n//\n// El calendario es el <input type=\"date\"> del TextField de MUI y no el DatePicker de @mui/x-date-pickers con moment,\n// para no sumar dos dependencias (x-date-pickers y moment) que ninguna\n// pantalla del 22-sep necesita. Si el calendario nativo estorba (Safari de escritorio), se cambia SOLO este archivo.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaDateRangeFilter con defaultProps y\n// styleOverrides de sus partes: chip, panel, actions.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Button from '@mui/material/Button';\nimport Chip from '@mui/material/Chip';\nimport Popover from '@mui/material/Popover';\nimport Stack from '@mui/material/Stack';\nimport TextField from '@mui/material/TextField';\nimport Typography from '@mui/material/Typography';\nimport DateRangeOutlinedIcon from '@mui/icons-material/DateRangeOutlined';\n\nimport {useFormatters} from '@/toolkit/useFormatters.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.CalcitaDateRangeFilter)\nconst THEME_NAME = 'CalcitaDateRangeFilter';\nconst RangeChip = piecePart(THEME_NAME, 'Chip', Chip);\nconst RangePanel = piecePart(THEME_NAME, 'Panel', Stack);\nconst RangeActions = piecePart(THEME_NAME, 'Actions', Stack);\n\n/**\n * @param {object} props\n * @param {string} [props.from] AAAA-MM-DD o '' si no hay\n * @param {string} [props.to] AAAA-MM-DD o '' si no hay\n * @param {(range: {from: string, to: string}) => void} props.onChange '' para quitar\n * @param {string} [props.label] ya traducido; por defecto \"Personalizado\"\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\
|
|
1
|
+
{"version":3,"file":"DateRangeFilter.js","sources":["../../../src/ui/filters/DateRangeFilter.jsx"],"sourcesContent":["// Un rango de fechas personalizado, como chip al lado de los accesos rápidos.\n//\n// Viaja como AAAA-MM-DD (día, no instante). Convertirlo a \"inicio del día\" y \"fin del día\" lo hace el SERVIDOR con la\n// zona del negocio: si lo hiciera el navegador con la suya, alguien en otra zona pediría otro rango sin saberlo.\n//\n// El calendario es el <input type=\"date\"> del TextField de MUI y no el DatePicker de @mui/x-date-pickers con moment,\n// para no sumar dos dependencias (x-date-pickers y moment) que ninguna\n// pantalla del 22-sep necesita. Si el calendario nativo estorba (Safari de escritorio), se cambia SOLO este archivo.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaDateRangeFilter con defaultProps y\n// styleOverrides de sus partes: chip, panel, actions.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Button from '@mui/material/Button';\nimport Chip from '@mui/material/Chip';\nimport Popover from '@mui/material/Popover';\nimport Stack from '@mui/material/Stack';\nimport TextField from '@mui/material/TextField';\nimport Typography from '@mui/material/Typography';\nimport DateRangeOutlinedIcon from '@mui/icons-material/DateRangeOutlined';\n\nimport {useFormatters} from '@/toolkit/useFormatters.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.CalcitaDateRangeFilter)\nconst THEME_NAME = 'CalcitaDateRangeFilter';\nconst RangeChip = piecePart(THEME_NAME, 'Chip', Chip);\nconst RangePanel = piecePart(THEME_NAME, 'Panel', Stack);\nconst RangeActions = piecePart(THEME_NAME, 'Actions', Stack);\n\n/**\n * @param {object} props\n * @param {string} [props.from] AAAA-MM-DD o '' si no hay\n * @param {string} [props.to] AAAA-MM-DD o '' si no hay\n * @param {(range: {from: string, to: string}) => void} props.onChange '' para quitar\n * @param {string} [props.label] ya traducido; por defecto \"Personalizado\"\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\nfunction DateRangeFilterContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaDateRangeFilter.defaultProps) y encima lo que llega aquí\n const {from = '', to = '', onChange, label, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('table', texts);\n const {formatDate} = useFormatters();\n const [anchorElement, setAnchorElement] = useState(null);\n const [draft, setDraft] = useState({from, to});\n const isActive = Boolean(from || to);\n // AAAA-MM-DD se compara bien como texto\n const isInvalid = Boolean(draft.from && draft.to && draft.from > draft.to);\n\n const open = (event) => {\n setDraft({from, to});\n setAnchorElement(event.currentTarget);\n };\n const close = () => setAnchorElement(null);\n const apply = () => {\n onChange(draft);\n close();\n };\n const clear = () => {\n onChange({from: '', to: ''});\n close();\n };\n\n const summary = isActive\n ? t('dateRange.summary', {from: from ? formatDate(from) : '…', to: to ? formatDate(to) : t('dateRange.today')})\n : (label ?? t('dateRange.label'));\n\n return (\n <>\n <RangeChip icon={<DateRangeOutlinedIcon />} label={summary} clickable onClick={open}\n variant={isActive ? 'filled' : 'outlined'} color={isActive ? 'primary' : 'default'}\n onDelete={isActive ? clear : undefined} ownSx={{flex: '0 0 auto', height: 32}} />\n <Popover open={Boolean(anchorElement)} anchorEl={anchorElement} onClose={close} anchorOrigin={{vertical: 'bottom', horizontal: 'left'}}>\n <RangePanel spacing={2} ownSx={{p: 2, width: 280}}>\n <Typography variant=\"subtitle2\">{t('dateRange.title')}</Typography>\n <TextField type=\"date\" size=\"small\" fullWidth label={t('dateRange.from')} value={draft.from}\n helperText={t('dateRange.fromHelp')}\n onChange={(event) => setDraft((currentDraft) => ({...currentDraft, from: event.target.value}))}\n slotProps={{inputLabel: {shrink: true}, htmlInput: {max: draft.to || undefined}}} />\n <TextField type=\"date\" size=\"small\" fullWidth label={t('dateRange.to')} value={draft.to} error={isInvalid}\n helperText={isInvalid ? t('dateRange.invalid') : t('dateRange.toHelp')}\n onChange={(event) => setDraft((currentDraft) => ({...currentDraft, to: event.target.value}))}\n slotProps={{inputLabel: {shrink: true}, htmlInput: {min: draft.from || undefined}}} />\n <RangeActions direction=\"row\" spacing={1} ownSx={{justifyContent: 'flex-end'}}>\n {isActive && <Button onClick={clear}>{t('dateRange.clear')}</Button>}\n <Button variant=\"contained\" onClick={apply} disabled={isInvalid || !(draft.from || draft.to)}>\n {t('dateRange.apply')}\n </Button>\n </RangeActions>\n </RangePanel>\n </Popover>\n </>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst DateRangeFilter = withPieceSlots(DateRangeFilterContent, THEME_NAME);\nexport default DateRangeFilter;\n"],"names":[],"mappings":"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"}
|
|
@@ -14,7 +14,7 @@ import FieldFrame from "../../inputs/FieldFrame.js";
|
|
|
14
14
|
import NumberInput from "../../inputs/NumberInput.js";
|
|
15
15
|
import SelectInput from "../../inputs/SelectInput.js";
|
|
16
16
|
import TextInput from "../../inputs/TextInput.js";
|
|
17
|
-
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
17
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
|
|
18
18
|
import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
|
|
19
19
|
import { warnUnknownProps } from "../../toolkit/unknownProps.js";
|
|
20
20
|
import { drawerValuesOf, invalidRangesOf, emptyDrawerValuesOf, filterKeysOf, FILTER_FIELD_KIND, comparisonOf, COMPARISON_OPERATOR, comparisonTextOf } from "./filterDrawerFields.js";
|
|
@@ -132,7 +132,7 @@ function DrawerField({ field, values, setValue, invalidRanges, t }) {
|
|
|
132
132
|
return null;
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
|
-
function
|
|
135
|
+
function FilterDrawerContent(props) {
|
|
136
136
|
const {
|
|
137
137
|
open,
|
|
138
138
|
onClose,
|
|
@@ -204,6 +204,7 @@ function FilterDrawer(props) {
|
|
|
204
204
|
}
|
|
205
205
|
);
|
|
206
206
|
}
|
|
207
|
+
const FilterDrawer = withPieceSlots(FilterDrawerContent, THEME_NAME);
|
|
207
208
|
export {
|
|
208
209
|
FILTER_DRAWER_ANCHOR,
|
|
209
210
|
FilterDrawer as default
|