@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":"FilterDrawer.js","sources":["../../../src/ui/filters/FilterDrawer.jsx"],"sourcesContent":["// El cajón de búsqueda: un panel que sale de un lado con los campos que filtran una lista (las listas, un rango\n// «desde-hasta», unas fechas, un monto con su operador), para cuando los filtros ya no caben arriba de la tabla.\n//\n// Lo que se cambia adentro es un BORRADOR: la lista no se mueve hasta «Buscar» (no se consulta al servidor con cada tecla).\n// «Limpiar» vacía los campos del cajón; «Buscar» manda todos juntos (onApply) y cierra. Un rango al revés («hasta» menor que\n// «desde») se dice en su campo y no deja buscar.\n//\n// Los campos se declaran (filterDrawerFields.js dice cómo viaja cada uno); con kind 'custom' va uno propio (render). Para\n// conectarlo a ServerTable con su botón y sus chips: ServerTableFilterDrawer de /table.\n//\n// Configurable: de qué lado sale (anchor), su ancho, su título y los textos de sus botones. En el teléfono ocupa todo el\n// ancho.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaFilterDrawer con defaultProps y\n// styleOverrides de sus partes: paper, header, body, footer.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useId, useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Drawer from '@mui/material/Drawer';\nimport IconButton from '@mui/material/IconButton';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport CloseRoundedIcon from '@mui/icons-material/CloseRounded';\n\nimport CatalogInput from '@/inputs/CatalogInput.jsx';\nimport CheckboxGroupInput from '@/inputs/CheckboxGroupInput.jsx';\nimport FieldFrame from '@/inputs/FieldFrame.jsx';\nimport NumberInput from '@/inputs/NumberInput.jsx';\nimport SelectInput from '@/inputs/SelectInput.jsx';\nimport TextInput from '@/inputs/TextInput.jsx';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {\n COMPARISON_OPERATOR, FILTER_FIELD_KIND, comparisonOf, comparisonTextOf, drawerValuesOf, emptyDrawerValuesOf, filterKeysOf,\n invalidRangesOf,\n} from '@/ui/filters/filterDrawerFields.js';\n\n/** De qué lado sale el cajón. */\nexport const FILTER_DRAWER_ANCHOR = Object.freeze({left: 'left', right: 'right'});\nconst DEFAULT_WIDTH = 380;\n// «Cualquiera» de una lista de una sola opción: no es una opción y viaja como '' (sin filtro)\nconst ANY_OPTION = '__calcita_any__';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaFilterDrawer)\nconst THEME_NAME = 'CalcitaFilterDrawer';\nconst FilterDrawerHeader = piecePart(THEME_NAME, 'Header', Stack);\nconst FilterDrawerBody = piecePart(THEME_NAME, 'Body', Stack);\nconst FilterDrawerFooter = piecePart(THEME_NAME, 'Footer', Stack);\n\n/**\n * Dos campos lado a lado (desde y hasta, operador y número); en un cajón angosto se ven bien juntos.\n *\n * @param {{label: import('react').ReactNode, inputId: string, children: import('react').ReactNode, template?: string}} props\n */\nfunction PairedField({label, inputId, children, template = '1fr 1fr'}) {\n return (\n <FieldFrame inputId={inputId} label={label}>\n <Box sx={{display: 'grid', gridTemplateColumns: template, gap: 1.5, alignItems: 'start'}}>{children}</Box>\n </FieldFrame>\n );\n}\n\n/**\n * Un campo del cajón según su tipo, con las piezas de la casa.\n *\n * @param {object} props\n */\nfunction DrawerField({field, values, setValue, invalidRanges, t}) {\n const fieldId = useId();\n const [key] = filterKeysOf(field);\n switch (field.kind) {\n case FILTER_FIELD_KIND.text:\n return <TextInput label={field.label} value={values[key]} onChange={(text) => setValue(key, text)} placeholder={field.placeholder} />;\n case FILTER_FIELD_KIND.select:\n return (\n <SelectInput label={field.label} value={values[key] || ANY_OPTION} onChange={(chosen) => setValue(key, chosen === ANY_OPTION ? '' : chosen)}\n options={[{value: ANY_OPTION, label: t('filterDrawer.any')}, ...field.options]} />\n );\n case FILTER_FIELD_KIND.multiSelect:\n return <SelectInput label={field.label} value={values[key]} onChange={(chosen) => setValue(key, chosen)} options={field.options} multiple selectAll checkboxes />;\n case FILTER_FIELD_KIND.catalog:\n return (\n <CatalogInput label={field.label} value={values[key]} onChange={(chosen) => setValue(key, chosen)} options={field.options}\n multiple={field.multiple} selectAll={field.multiple} checkboxes={field.multiple} formatLabel={field.formatLabel}\n placeholder={field.placeholder} />\n );\n case FILTER_FIELD_KIND.checkboxes:\n return <CheckboxGroupInput label={field.label} value={values[key]} onChange={(chosen) => setValue(key, chosen)} options={field.options} selectAll={field.selectAll} />;\n case FILTER_FIELD_KIND.numberRange: {\n const [fromKey, toKey] = filterKeysOf(field);\n const numberProps = {decimals: field.decimals ?? 0, prefix: field.prefix, suffix: field.suffix, helperText: ''};\n return (\n <PairedField label={field.label} inputId={`${fieldId}-from`}>\n <NumberInput label={t('filterDrawer.from')} value={values[fromKey]} onChange={(number) => setValue(fromKey, number)} {...numberProps} />\n <NumberInput label={t('filterDrawer.to')} value={values[toKey]} onChange={(number) => setValue(toKey, number)} {...numberProps}\n error={invalidRanges[toKey] ? t('filterDrawer.rangeBackwards') : undefined} />\n </PairedField>\n );\n }\n case FILTER_FIELD_KIND.dateRange: {\n const [fromKey, toKey] = filterKeysOf(field);\n // el calendario del navegador (como DateRangeFilter): viaja AAAA-MM-DD, sin pedir MUI X\n return (\n <PairedField label={field.label} inputId={`${fieldId}-from`}>\n <TextInput type=\"date\" label={t('filterDrawer.from')} value={values[fromKey]} onChange={(date) => setValue(fromKey, date)} clearable={false} helperText=\"\" />\n <TextInput type=\"date\" label={t('filterDrawer.to')} value={values[toKey]} onChange={(date) => setValue(toKey, date)} clearable={false}\n error={invalidRanges[toKey] ? t('filterDrawer.rangeBackwards') : undefined} />\n </PairedField>\n );\n }\n case FILTER_FIELD_KIND.comparison: {\n const parts = comparisonOf(values[key]);\n const operators = field.operators ?? Object.values(COMPARISON_OPERATOR);\n const operator = parts?.operator ?? field.defaultOperator ?? operators[0];\n return (\n <PairedField label={field.label} inputId={`${fieldId}-value`} template=\"minmax(0, 1fr) minmax(0, 1.2fr)\">\n <SelectInput label={t('filterDrawer.operator')} value={operator} helperText=\"\"\n options={operators.map((option) => ({value: option, label: t(`filterDrawer.operators.${option}`)}))}\n onChange={(chosen) => setValue(key, comparisonTextOf(chosen, parts?.value ?? ''))} />\n <NumberInput label={t('filterDrawer.value')} value={parts?.value ?? ''} decimals={field.decimals ?? 2} prefix={field.prefix} suffix={field.suffix}\n helperText=\"\" onChange={(number) => setValue(key, comparisonTextOf(operator, number))} />\n </PairedField>\n );\n }\n case FILTER_FIELD_KIND.custom:\n return field.render({value: values[key], onChange: (next) => setValue(key, next), values, setValue});\n default:\n return null;\n }\n}\n\n/**\n * @param {object} props\n * @param {boolean} props.open\n * @param {() => void} props.onClose\n * @param {object[]} props.fields los campos (filterDrawerFields.js): {name, label, kind, options?, keys?, prefix?, suffix?, decimals?, operators?, render?…}\n * @param {Record<string, unknown>} props.values los filtros puestos hoy (de ahí sale el borrador al abrir)\n * @param {(values: Record<string, unknown>) => void} props.onApply todos los campos del cajón juntos, al picar «Buscar»\n * @param {'left'|'right'} [props.anchor] de qué lado sale (FILTER_DRAWER_ANCHOR); por omisión la derecha\n * @param {number} [props.width] su ancho en escritorio, en px\n * @param {string} [props.title] ya traducido; por omisión «Filtros»\n * @param {string} [props.applyLabel] ya traducido; por omisión «Buscar»\n * @param {boolean} [props.closeOnApply] por omisión sí\n * @param {import('react').ReactNode} [props.children] algo más abajo de los campos (una nota, un enlace)\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nexport default function FilterDrawer(props) {\n const {\n open, onClose, fields, values, onApply, anchor = FILTER_DRAWER_ANCHOR.right, width = DEFAULT_WIDTH, title, applyLabel,\n closeOnApply = true, children, 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 [draft, setDraft] = useState(() => drawerValuesOf(fields, values));\n // cada vez que se abre, el borrador empieza de lo que hay puesto (lo de la vez pasada sin buscar no se queda)\n useEffect(() => {\n if (open) {\n setDraft(drawerValuesOf(fields, values));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n const invalidRanges = invalidRangesOf(fields, draft);\n const hasInvalidRange = Object.keys(invalidRanges).length > 0;\n const setValue = (key, value) => setDraft((current) => ({...current, [key]: value}));\n const apply = () => {\n onApply(draft);\n if (closeOnApply) {\n onClose();\n }\n };\n\n return (\n <Drawer\n anchor={anchor}\n open={open}\n onClose={onClose}\n slotProps={{paper: {'aria-labelledby': titleId, className: `${THEME_NAME}-paper`, sx: {width: {xs: '100%', sm: width}, maxWidth: '100%'}}}}\n >\n <Box component=\"form\" noValidate sx={{display: 'flex', flexDirection: 'column', height: '100%'}}\n onSubmit={(event) => {\n event.preventDefault();\n if (!hasInvalidRange) {\n apply();\n }\n }}>\n <FilterDrawerHeader direction=\"row\" ownSx={{alignItems: 'center', gap: 1, px: 2, py: 1.5, borderBottom: 1, borderColor: 'divider'}}>\n <IconButton aria-label={t('filterDrawer.close')} onClick={onClose} edge=\"start\"><CloseRoundedIcon /></IconButton>\n <Typography id={titleId} variant=\"h6\" component=\"h2\" sx={{flexGrow: 1}}>{title ?? t('filterDrawer.title')}</Typography>\n </FilterDrawerHeader>\n <FilterDrawerBody spacing={1} ownSx={{flex: 1, overflowY: 'auto', px: 2.5, py: 2}}>\n {fields.map((field) => (\n <DrawerField key={field.name} field={field} values={draft} setValue={setValue} invalidRanges={invalidRanges} t={t} />\n ))}\n {children}\n </FilterDrawerBody>\n <FilterDrawerFooter direction=\"row\" ownSx={{gap: 1, justifyContent: 'flex-end', px: 2.5, py: 1.5, borderTop: 1, borderColor: 'divider'}}>\n <Button onClick={() => setDraft(emptyDrawerValuesOf(fields))}>{t('filterDrawer.clear')}</Button>\n <Button type=\"submit\" variant=\"contained\" disabled={hasInvalidRange}>{applyLabel ?? t('filterDrawer.apply')}</Button>\n </FilterDrawerFooter>\n </Box>\n </Drawer>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FilterDrawer.js","sources":["../../../src/ui/filters/FilterDrawer.jsx"],"sourcesContent":["// El cajón de búsqueda: un panel que sale de un lado con los campos que filtran una lista (las listas, un rango\n// «desde-hasta», unas fechas, un monto con su operador), para cuando los filtros ya no caben arriba de la tabla.\n//\n// Lo que se cambia adentro es un BORRADOR: la lista no se mueve hasta «Buscar» (no se consulta al servidor con cada tecla).\n// «Limpiar» vacía los campos del cajón; «Buscar» manda todos juntos (onApply) y cierra. Un rango al revés («hasta» menor que\n// «desde») se dice en su campo y no deja buscar.\n//\n// Los campos se declaran (filterDrawerFields.js dice cómo viaja cada uno); con kind 'custom' va uno propio (render). Para\n// conectarlo a ServerTable con su botón y sus chips: ServerTableFilterDrawer de /table.\n//\n// Configurable: de qué lado sale (anchor), su ancho, su título y los textos de sus botones. En el teléfono ocupa todo el\n// ancho.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaFilterDrawer con defaultProps y\n// styleOverrides de sus partes: paper, header, body, footer.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useId, useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Drawer from '@mui/material/Drawer';\nimport IconButton from '@mui/material/IconButton';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport CloseRoundedIcon from '@mui/icons-material/CloseRounded';\n\nimport CatalogInput from '@/inputs/CatalogInput.jsx';\nimport CheckboxGroupInput from '@/inputs/CheckboxGroupInput.jsx';\nimport FieldFrame from '@/inputs/FieldFrame.jsx';\nimport NumberInput from '@/inputs/NumberInput.jsx';\nimport SelectInput from '@/inputs/SelectInput.jsx';\nimport TextInput from '@/inputs/TextInput.jsx';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {\n COMPARISON_OPERATOR, FILTER_FIELD_KIND, comparisonOf, comparisonTextOf, drawerValuesOf, emptyDrawerValuesOf, filterKeysOf,\n invalidRangesOf,\n} from '@/ui/filters/filterDrawerFields.js';\n\n/** De qué lado sale el cajón. */\nexport const FILTER_DRAWER_ANCHOR = Object.freeze({left: 'left', right: 'right'});\nconst DEFAULT_WIDTH = 380;\n// «Cualquiera» de una lista de una sola opción: no es una opción y viaja como '' (sin filtro)\nconst ANY_OPTION = '__calcita_any__';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaFilterDrawer)\nconst THEME_NAME = 'CalcitaFilterDrawer';\nconst FilterDrawerHeader = piecePart(THEME_NAME, 'Header', Stack);\nconst FilterDrawerBody = piecePart(THEME_NAME, 'Body', Stack);\nconst FilterDrawerFooter = piecePart(THEME_NAME, 'Footer', Stack);\n\n/**\n * Dos campos lado a lado (desde y hasta, operador y número); en un cajón angosto se ven bien juntos.\n *\n * @param {{label: import('react').ReactNode, inputId: string, children: import('react').ReactNode, template?: string}} props\n */\nfunction PairedField({label, inputId, children, template = '1fr 1fr'}) {\n return (\n <FieldFrame inputId={inputId} label={label}>\n <Box sx={{display: 'grid', gridTemplateColumns: template, gap: 1.5, alignItems: 'start'}}>{children}</Box>\n </FieldFrame>\n );\n}\n\n/**\n * Un campo del cajón según su tipo, con las piezas de la casa.\n *\n * @param {object} props\n */\nfunction DrawerField({field, values, setValue, invalidRanges, t}) {\n const fieldId = useId();\n const [key] = filterKeysOf(field);\n switch (field.kind) {\n case FILTER_FIELD_KIND.text:\n return <TextInput label={field.label} value={values[key]} onChange={(text) => setValue(key, text)} placeholder={field.placeholder} />;\n case FILTER_FIELD_KIND.select:\n return (\n <SelectInput label={field.label} value={values[key] || ANY_OPTION} onChange={(chosen) => setValue(key, chosen === ANY_OPTION ? '' : chosen)}\n options={[{value: ANY_OPTION, label: t('filterDrawer.any')}, ...field.options]} />\n );\n case FILTER_FIELD_KIND.multiSelect:\n return <SelectInput label={field.label} value={values[key]} onChange={(chosen) => setValue(key, chosen)} options={field.options} multiple selectAll checkboxes />;\n case FILTER_FIELD_KIND.catalog:\n return (\n <CatalogInput label={field.label} value={values[key]} onChange={(chosen) => setValue(key, chosen)} options={field.options}\n multiple={field.multiple} selectAll={field.multiple} checkboxes={field.multiple} formatLabel={field.formatLabel}\n placeholder={field.placeholder} />\n );\n case FILTER_FIELD_KIND.checkboxes:\n return <CheckboxGroupInput label={field.label} value={values[key]} onChange={(chosen) => setValue(key, chosen)} options={field.options} selectAll={field.selectAll} />;\n case FILTER_FIELD_KIND.numberRange: {\n const [fromKey, toKey] = filterKeysOf(field);\n const numberProps = {decimals: field.decimals ?? 0, prefix: field.prefix, suffix: field.suffix, helperText: ''};\n return (\n <PairedField label={field.label} inputId={`${fieldId}-from`}>\n <NumberInput label={t('filterDrawer.from')} value={values[fromKey]} onChange={(number) => setValue(fromKey, number)} {...numberProps} />\n <NumberInput label={t('filterDrawer.to')} value={values[toKey]} onChange={(number) => setValue(toKey, number)} {...numberProps}\n error={invalidRanges[toKey] ? t('filterDrawer.rangeBackwards') : undefined} />\n </PairedField>\n );\n }\n case FILTER_FIELD_KIND.dateRange: {\n const [fromKey, toKey] = filterKeysOf(field);\n // el calendario del navegador (como DateRangeFilter): viaja AAAA-MM-DD, sin pedir MUI X\n return (\n <PairedField label={field.label} inputId={`${fieldId}-from`}>\n <TextInput type=\"date\" label={t('filterDrawer.from')} value={values[fromKey]} onChange={(date) => setValue(fromKey, date)} clearable={false} helperText=\"\" />\n <TextInput type=\"date\" label={t('filterDrawer.to')} value={values[toKey]} onChange={(date) => setValue(toKey, date)} clearable={false}\n error={invalidRanges[toKey] ? t('filterDrawer.rangeBackwards') : undefined} />\n </PairedField>\n );\n }\n case FILTER_FIELD_KIND.comparison: {\n const parts = comparisonOf(values[key]);\n const operators = field.operators ?? Object.values(COMPARISON_OPERATOR);\n const operator = parts?.operator ?? field.defaultOperator ?? operators[0];\n return (\n <PairedField label={field.label} inputId={`${fieldId}-value`} template=\"minmax(0, 1fr) minmax(0, 1.2fr)\">\n <SelectInput label={t('filterDrawer.operator')} value={operator} helperText=\"\"\n options={operators.map((option) => ({value: option, label: t(`filterDrawer.operators.${option}`)}))}\n onChange={(chosen) => setValue(key, comparisonTextOf(chosen, parts?.value ?? ''))} />\n <NumberInput label={t('filterDrawer.value')} value={parts?.value ?? ''} decimals={field.decimals ?? 2} prefix={field.prefix} suffix={field.suffix}\n helperText=\"\" onChange={(number) => setValue(key, comparisonTextOf(operator, number))} />\n </PairedField>\n );\n }\n case FILTER_FIELD_KIND.custom:\n return field.render({value: values[key], onChange: (next) => setValue(key, next), values, setValue});\n default:\n return null;\n }\n}\n\n/**\n * @param {object} props\n * @param {boolean} props.open\n * @param {() => void} props.onClose\n * @param {object[]} props.fields los campos (filterDrawerFields.js): {name, label, kind, options?, keys?, prefix?, suffix?, decimals?, operators?, render?…}\n * @param {Record<string, unknown>} props.values los filtros puestos hoy (de ahí sale el borrador al abrir)\n * @param {(values: Record<string, unknown>) => void} props.onApply todos los campos del cajón juntos, al picar «Buscar»\n * @param {'left'|'right'} [props.anchor] de qué lado sale (FILTER_DRAWER_ANCHOR); por omisión la derecha\n * @param {number} [props.width] su ancho en escritorio, en px\n * @param {string} [props.title] ya traducido; por omisión «Filtros»\n * @param {string} [props.applyLabel] ya traducido; por omisión «Buscar»\n * @param {boolean} [props.closeOnApply] por omisión sí\n * @param {import('react').ReactNode} [props.children] algo más abajo de los campos (una nota, un enlace)\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction FilterDrawerContent(props) {\n const {\n open, onClose, fields, values, onApply, anchor = FILTER_DRAWER_ANCHOR.right, width = DEFAULT_WIDTH, title, applyLabel,\n closeOnApply = true, children, 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 [draft, setDraft] = useState(() => drawerValuesOf(fields, values));\n // cada vez que se abre, el borrador empieza de lo que hay puesto (lo de la vez pasada sin buscar no se queda)\n useEffect(() => {\n if (open) {\n setDraft(drawerValuesOf(fields, values));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n const invalidRanges = invalidRangesOf(fields, draft);\n const hasInvalidRange = Object.keys(invalidRanges).length > 0;\n const setValue = (key, value) => setDraft((current) => ({...current, [key]: value}));\n const apply = () => {\n onApply(draft);\n if (closeOnApply) {\n onClose();\n }\n };\n\n return (\n <Drawer\n anchor={anchor}\n open={open}\n onClose={onClose}\n slotProps={{paper: {'aria-labelledby': titleId, className: `${THEME_NAME}-paper`, sx: {width: {xs: '100%', sm: width}, maxWidth: '100%'}}}}\n >\n <Box component=\"form\" noValidate sx={{display: 'flex', flexDirection: 'column', height: '100%'}}\n onSubmit={(event) => {\n event.preventDefault();\n if (!hasInvalidRange) {\n apply();\n }\n }}>\n <FilterDrawerHeader direction=\"row\" ownSx={{alignItems: 'center', gap: 1, px: 2, py: 1.5, borderBottom: 1, borderColor: 'divider'}}>\n <IconButton aria-label={t('filterDrawer.close')} onClick={onClose} edge=\"start\"><CloseRoundedIcon /></IconButton>\n <Typography id={titleId} variant=\"h6\" component=\"h2\" sx={{flexGrow: 1}}>{title ?? t('filterDrawer.title')}</Typography>\n </FilterDrawerHeader>\n <FilterDrawerBody spacing={1} ownSx={{flex: 1, overflowY: 'auto', px: 2.5, py: 2}}>\n {fields.map((field) => (\n <DrawerField key={field.name} field={field} values={draft} setValue={setValue} invalidRanges={invalidRanges} t={t} />\n ))}\n {children}\n </FilterDrawerBody>\n <FilterDrawerFooter direction=\"row\" ownSx={{gap: 1, justifyContent: 'flex-end', px: 2.5, py: 1.5, borderTop: 1, borderColor: 'divider'}}>\n <Button onClick={() => setDraft(emptyDrawerValuesOf(fields))}>{t('filterDrawer.clear')}</Button>\n <Button type=\"submit\" variant=\"contained\" disabled={hasInvalidRange}>{applyLabel ?? t('filterDrawer.apply')}</Button>\n </FilterDrawerFooter>\n </Box>\n </Drawer>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst FilterDrawer = withPieceSlots(FilterDrawerContent, THEME_NAME);\nexport default FilterDrawer;\n"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ import MenuItem from "@mui/material/MenuItem";
|
|
|
7
7
|
import Select from "@mui/material/Select";
|
|
8
8
|
import Stack from "@mui/material/Stack";
|
|
9
9
|
import { rangeEndOptionsOf, rangeEndAfterStartChange } from "../../periodRanges.js";
|
|
10
|
-
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
10
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
|
|
11
11
|
import { warnUnknownProps } from "../../toolkit/unknownProps.js";
|
|
12
12
|
const THEME_NAME = "CalcitaPeriodRangeSelector";
|
|
13
13
|
const PeriodField = piecePart(THEME_NAME, "Field", FormControl);
|
|
@@ -31,7 +31,7 @@ function PeriodSelect({ id, label, value, options, onChange }) {
|
|
|
31
31
|
)
|
|
32
32
|
] });
|
|
33
33
|
}
|
|
34
|
-
function
|
|
34
|
+
function PeriodRangeSelectorContent(props) {
|
|
35
35
|
const { id, options, from, to, fromLabel, toLabel, onChange, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
36
36
|
warnUnknownProps(THEME_NAME, unknownProps);
|
|
37
37
|
const endOptions = rangeEndOptionsOf(options, from);
|
|
@@ -58,6 +58,7 @@ function PeriodRangeSelector(props) {
|
|
|
58
58
|
)
|
|
59
59
|
] });
|
|
60
60
|
}
|
|
61
|
+
const PeriodRangeSelector = withPieceSlots(PeriodRangeSelectorContent, THEME_NAME);
|
|
61
62
|
export {
|
|
62
63
|
PeriodRangeSelector as default
|
|
63
64
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PeriodRangeSelector.js","sources":["../../../src/ui/filters/PeriodRangeSelector.jsx"],"sourcesContent":["// Un rango de periodos: «desde» y «hasta», cada uno una lista para elegir (de tal quincena a tal quincena, de tal mes a\n// tal mes). Se usa en lugar de un calendario porque los periodos no son días: solo se ofrecen los que existen, y los que no\n// se pueden elegir salen apagados con su razón.\n//\n// «Hasta» solo ofrece lo que hace un rango válido con «desde»: nada de antes y nada que salte un periodo apagado\n// (periodRanges.js). Al cambiar «desde», si el «hasta» que había ya no vale, se iguala a «desde».\n//\n// No sabe de quincenas ni de productos: recibe las opciones ya ordenadas y con sus textos traducidos.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaPeriodRangeSelector con defaultProps y\n// styleOverrides de sus partes: field, select, root.\n//\n// Genérico del paquete: function (regla de la casa).\nimport FormControl from '@mui/material/FormControl';\nimport InputLabel from '@mui/material/InputLabel';\nimport ListItemText from '@mui/material/ListItemText';\nimport MenuItem from '@mui/material/MenuItem';\nimport Select from '@mui/material/Select';\nimport Stack from '@mui/material/Stack';\n\nimport {rangeEndAfterStartChange, rangeEndOptionsOf} from '@/periodRanges.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.CalcitaPeriodRangeSelector)\nconst THEME_NAME = 'CalcitaPeriodRangeSelector';\nconst PeriodField = piecePart(THEME_NAME, 'Field', FormControl);\nconst PeriodSelectPart = piecePart(THEME_NAME, 'Select', Select);\nconst PeriodRoot = piecePart(THEME_NAME, 'Root', Stack);\n\n// ancho de cada lista: cabe «septiembre 2026 · Q2» sin cortarse\nconst SELECT_MINIMUM_WIDTH = 210;\n\n/**\n * Una lista del rango.\n *\n * @param {object} props\n * @param {string} props.id\n * @param {string} props.label\n * @param {string} props.value\n * @param {(value: string) => void} props.onChange\n * @param {Array<{value: string, label: string, disabled: boolean, hint?: string}>} props.options\n */\nfunction PeriodSelect({id, label, value, options, onChange}) {\n return (\n <PeriodField size=\"small\" ownSx={{minWidth: SELECT_MINIMUM_WIDTH, flex: '0 0 auto'}}>\n <InputLabel id={`${id}-label`}>{label}</InputLabel>\n <PeriodSelectPart labelId={`${id}-label`} label={label} value={value ?? ''} onChange={(event) => onChange(event.target.value)}\n ownSx={{bgcolor: 'background.paper'}}\n renderValue={(selectedValue) => options.find((option) => option.value === selectedValue)?.label ?? ''}>\n {options.map((option) => (\n <MenuItem key={option.value} value={option.value} disabled={option.disabled}>\n {/* la razón de una opción apagada va debajo de su nombre: «sin validar» se lee sin tooltip */}\n <ListItemText primary={option.label} secondary={option.disabled ? option.hint : undefined} />\n </MenuItem>\n ))}\n </PeriodSelectPart>\n </PeriodField>\n );\n}\n\n/**\n * @param {object} props\n * @param {string} props.id prefijo de los id de las dos listas (accesibilidad)\n * @param {Array<{value: string, label: string, disabled: boolean, hint?: string}>} props.options en orden; ya\n * traducidas\n * @param {string|null} props.from\n * @param {string|null} props.to\n * @param {string} props.fromLabel ya traducido\n * @param {string} props.toLabel ya traducido\n * @param {(range: {from: string, to: string}) => void} props.onChange\n */\
|
|
1
|
+
{"version":3,"file":"PeriodRangeSelector.js","sources":["../../../src/ui/filters/PeriodRangeSelector.jsx"],"sourcesContent":["// Un rango de periodos: «desde» y «hasta», cada uno una lista para elegir (de tal quincena a tal quincena, de tal mes a\n// tal mes). Se usa en lugar de un calendario porque los periodos no son días: solo se ofrecen los que existen, y los que no\n// se pueden elegir salen apagados con su razón.\n//\n// «Hasta» solo ofrece lo que hace un rango válido con «desde»: nada de antes y nada que salte un periodo apagado\n// (periodRanges.js). Al cambiar «desde», si el «hasta» que había ya no vale, se iguala a «desde».\n//\n// No sabe de quincenas ni de productos: recibe las opciones ya ordenadas y con sus textos traducidos.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaPeriodRangeSelector con defaultProps y\n// styleOverrides de sus partes: field, select, root.\n//\n// Genérico del paquete: function (regla de la casa).\nimport FormControl from '@mui/material/FormControl';\nimport InputLabel from '@mui/material/InputLabel';\nimport ListItemText from '@mui/material/ListItemText';\nimport MenuItem from '@mui/material/MenuItem';\nimport Select from '@mui/material/Select';\nimport Stack from '@mui/material/Stack';\n\nimport {rangeEndAfterStartChange, rangeEndOptionsOf} from '@/periodRanges.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.CalcitaPeriodRangeSelector)\nconst THEME_NAME = 'CalcitaPeriodRangeSelector';\nconst PeriodField = piecePart(THEME_NAME, 'Field', FormControl);\nconst PeriodSelectPart = piecePart(THEME_NAME, 'Select', Select);\nconst PeriodRoot = piecePart(THEME_NAME, 'Root', Stack);\n\n// ancho de cada lista: cabe «septiembre 2026 · Q2» sin cortarse\nconst SELECT_MINIMUM_WIDTH = 210;\n\n/**\n * Una lista del rango.\n *\n * @param {object} props\n * @param {string} props.id\n * @param {string} props.label\n * @param {string} props.value\n * @param {(value: string) => void} props.onChange\n * @param {Array<{value: string, label: string, disabled: boolean, hint?: string}>} props.options\n */\nfunction PeriodSelect({id, label, value, options, onChange}) {\n return (\n <PeriodField size=\"small\" ownSx={{minWidth: SELECT_MINIMUM_WIDTH, flex: '0 0 auto'}}>\n <InputLabel id={`${id}-label`}>{label}</InputLabel>\n <PeriodSelectPart labelId={`${id}-label`} label={label} value={value ?? ''} onChange={(event) => onChange(event.target.value)}\n ownSx={{bgcolor: 'background.paper'}}\n renderValue={(selectedValue) => options.find((option) => option.value === selectedValue)?.label ?? ''}>\n {options.map((option) => (\n <MenuItem key={option.value} value={option.value} disabled={option.disabled}>\n {/* la razón de una opción apagada va debajo de su nombre: «sin validar» se lee sin tooltip */}\n <ListItemText primary={option.label} secondary={option.disabled ? option.hint : undefined} />\n </MenuItem>\n ))}\n </PeriodSelectPart>\n </PeriodField>\n );\n}\n\n/**\n * @param {object} props\n * @param {string} props.id prefijo de los id de las dos listas (accesibilidad)\n * @param {Array<{value: string, label: string, disabled: boolean, hint?: string}>} props.options en orden; ya\n * traducidas\n * @param {string|null} props.from\n * @param {string|null} props.to\n * @param {string} props.fromLabel ya traducido\n * @param {string} props.toLabel ya traducido\n * @param {(range: {from: string, to: string}) => void} props.onChange\n */\nfunction PeriodRangeSelectorContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaPeriodRangeSelector.defaultProps) y encima lo que llega aquí\n const {id, options, from, to, fromLabel, toLabel, onChange, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const endOptions = rangeEndOptionsOf(options, from);\n\n return (\n <PeriodRoot direction=\"row\" spacing={1.5} useFlexGap ownSx={{alignItems: 'center', flexWrap: 'wrap'}}>\n <PeriodSelect id={`${id}-from`} label={fromLabel} value={from} options={options}\n onChange={(nextFrom) => onChange({from: nextFrom, to: rangeEndAfterStartChange(options, nextFrom, to)})} />\n <PeriodSelect id={`${id}-to`} label={toLabel} value={to} options={endOptions}\n onChange={(nextTo) => onChange({from, to: nextTo})} />\n </PeriodRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst PeriodRangeSelector = withPieceSlots(PeriodRangeSelectorContent, THEME_NAME);\nexport default PeriodRangeSelector;\n"],"names":[],"mappings":";;;;;;;;;;;AAyBA,MAAM,aAAa;AACnB,MAAM,cAAc,UAAU,YAAY,SAAS,WAAW;AAC9D,MAAM,mBAAmB,UAAU,YAAY,UAAU,MAAM;AAC/D,MAAM,aAAa,UAAU,YAAY,QAAQ,KAAK;AAGtD,MAAM,uBAAuB;AAY7B,SAAS,aAAa,EAAC,IAAI,OAAO,OAAO,SAAS,YAAW;AACzD,SACI,qBAAC,aAAA,EAAY,MAAK,SAAQ,OAAO,EAAC,UAAU,sBAAsB,MAAM,WAAA,GACpE,UAAA;AAAA,IAAA,oBAAC,YAAA,EAAW,IAAI,GAAG,EAAE,UAAW,UAAA,OAAM;AAAA,IACtC;AAAA,MAAC;AAAA,MAAA;AAAA,QAAiB,SAAS,GAAG,EAAE;AAAA,QAAU;AAAA,QAAc,OAAO,SAAS;AAAA,QAAI,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,KAAK;AAAA,QACpH,OAAO,EAAC,SAAS,mBAAA;AAAA,QACjB,aAAa,CAAC,kBAAkB,QAAQ,KAAK,CAAC,WAAW,OAAO,UAAU,aAAa,GAAG,SAAS;AAAA,QACtG,UAAA,QAAQ,IAAI,CAAC,WACV,oBAAC,UAAA,EAA4B,OAAO,OAAO,OAAO,UAAU,OAAO,UAE/D,UAAA,oBAAC,gBAAa,SAAS,OAAO,OAAO,WAAW,OAAO,WAAW,OAAO,OAAO,OAAA,CAAW,EAAA,GAFhF,OAAO,KAGtB,CACH;AAAA,MAAA;AAAA,IAAA;AAAA,EACL,GACJ;AAER;AAaA,SAAS,2BAA2B,OAAO;AAEvC,QAAM,EAAC,IAAI,SAAS,MAAM,IAAI,WAAW,SAAS,UAAU,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AAC9G,mBAAiB,YAAY,YAAY;AACzC,QAAM,aAAa,kBAAkB,SAAS,IAAI;AAElD,SACI,qBAAC,YAAA,EAAW,WAAU,OAAM,SAAS,KAAK,YAAU,MAAC,OAAO,EAAC,YAAY,UAAU,UAAU,UACzF,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QAAa,IAAI,GAAG,EAAE;AAAA,QAAS,OAAO;AAAA,QAAW,OAAO;AAAA,QAAM;AAAA,QACjD,UAAU,CAAC,aAAa,SAAS,EAAC,MAAM,UAAU,IAAI,yBAAyB,SAAS,UAAU,EAAE,GAAE;AAAA,MAAA;AAAA,IAAA;AAAA,IACpH;AAAA,MAAC;AAAA,MAAA;AAAA,QAAa,IAAI,GAAG,EAAE;AAAA,QAAO,OAAO;AAAA,QAAS,OAAO;AAAA,QAAI,SAAS;AAAA,QACpD,UAAU,CAAC,WAAW,SAAS,EAAC,MAAM,IAAI,QAAO;AAAA,MAAA;AAAA,IAAA;AAAA,EAAG,GACtE;AAER;AAGA,MAAM,sBAAsB,eAAe,4BAA4B,UAAU;"}
|
|
@@ -7,7 +7,7 @@ import { alpha } from "@mui/material/styles";
|
|
|
7
7
|
import Chip from "@mui/material/Chip";
|
|
8
8
|
import Typography from "@mui/material/Typography";
|
|
9
9
|
import ScrollableRow from "../layout/ScrollableRow.js";
|
|
10
|
-
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
10
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
|
|
11
11
|
import { warnUnknownProps } from "../../toolkit/unknownProps.js";
|
|
12
12
|
const THEME_NAME = "CalcitaQuickFilters";
|
|
13
13
|
const QuickRoot = piecePart(THEME_NAME, "Root", Box);
|
|
@@ -32,7 +32,7 @@ function compactCount(count) {
|
|
|
32
32
|
}
|
|
33
33
|
return String(count);
|
|
34
34
|
}
|
|
35
|
-
function
|
|
35
|
+
function QuickFiltersContent(props) {
|
|
36
36
|
const { value, onChange, options = [], caption, ariaLabel, extra, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
37
37
|
warnUnknownProps(THEME_NAME, unknownProps);
|
|
38
38
|
const { t } = useToolkitTranslation("table", texts);
|
|
@@ -95,6 +95,7 @@ function QuickFilters(props) {
|
|
|
95
95
|
] })
|
|
96
96
|
] });
|
|
97
97
|
}
|
|
98
|
+
const QuickFilters = withPieceSlots(QuickFiltersContent, THEME_NAME);
|
|
98
99
|
export {
|
|
99
100
|
QuickFilters as default
|
|
100
101
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuickFilters.js","sources":["../../../src/ui/filters/QuickFilters.jsx"],"sourcesContent":["// Accesos rápidos: una tira de chips donde se elige UNO (p. ej. el estatus de un pedido).\n//\n// Es el complemento de FilterChips, no lo mismo:\n// - FilterChips dice qué filtros están PUESTOS y sirve para quitarlos;\n// - esto dice qué opciones HAY y sirve para saltar entre ellas de un toque.\n//\n// El conteo de cada chip sale de las facetas del servidor, contadas sobre el conjunto COMPLETO y sin este filtro\n// puesto: al elegir una, las demás siguen diciendo cuántas tienen.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaQuickFilters con defaultProps y\n// styleOverrides de sus partes: root, caption, chip, chipLabel, chipCount.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useRef} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport {alpha} from '@mui/material/styles';\nimport Chip from '@mui/material/Chip';\nimport Typography from '@mui/material/Typography';\n\nimport ScrollableRow from '@/ui/layout/ScrollableRow.jsx';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaQuickFilters)\nconst THEME_NAME = 'CalcitaQuickFilters';\nconst QuickRoot = piecePart(THEME_NAME, 'Root', Box);\nconst QuickCaption = piecePart(THEME_NAME, 'Caption', Typography);\nconst QuickChip = piecePart(THEME_NAME, 'Chip', Chip);\nconst QuickChipLabel = piecePart(THEME_NAME, 'ChipLabel', Box);\nconst QuickChipCount = piecePart(THEME_NAME, 'ChipCount', Box);\n\n\n// qué tan marcado va el velo del contador del filtro elegido\nconst ACTIVE_COUNT_VEIL_OPACITY = 0.18;\n\n/**\n * El velo del contador del filtro elegido: el color del texto base (negro en claro, blanco en oscuro) casi transparente.\n * Un tema con variables CSS trae ese color en theme.vars; el tema por omisión de MUI, en su modo.\n *\n * @param {object} theme tema de MUI\n * @returns {string} color CSS\n */\nfunction activeCountVeilOf(theme) {\n if (theme.vars) {\n return `rgba(${theme.vars.palette.common.onBackgroundChannel} / ${ACTIVE_COUNT_VEIL_OPACITY})`;\n }\n const baseTextColor = theme.palette.mode === 'dark' ? theme.palette.common.white : theme.palette.common.black;\n\n return alpha(baseTextColor, ACTIVE_COUNT_VEIL_OPACITY);\n}\n\n/** \"99+\" arriba de 99 y \"1.2k\" arriba de 999: el chip no se estira. */\nfunction compactCount(count) {\n if (count > 999) {\n return `${(count / 1000).toFixed(1)}k`;\n }\n if (count > 99) {\n return '99+';\n }\n return String(count);\n}\n\n/**\n * @param {object} props\n * @param {string} props.value opción activa ('' = todas)\n * @param {(value: string) => void} props.onChange\n * @param {Array<{value: string, label: import('react').ReactNode, count?: number}>} [props.options]\n * @param {import('react').ReactNode} [props.caption]\n * @param {string} [props.ariaLabel]\n * @param {import('react').ReactNode} [props.extra] al final de la tira (p. ej. un rango de fechas)\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\
|
|
1
|
+
{"version":3,"file":"QuickFilters.js","sources":["../../../src/ui/filters/QuickFilters.jsx"],"sourcesContent":["// Accesos rápidos: una tira de chips donde se elige UNO (p. ej. el estatus de un pedido).\n//\n// Es el complemento de FilterChips, no lo mismo:\n// - FilterChips dice qué filtros están PUESTOS y sirve para quitarlos;\n// - esto dice qué opciones HAY y sirve para saltar entre ellas de un toque.\n//\n// El conteo de cada chip sale de las facetas del servidor, contadas sobre el conjunto COMPLETO y sin este filtro\n// puesto: al elegir una, las demás siguen diciendo cuántas tienen.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaQuickFilters con defaultProps y\n// styleOverrides de sus partes: root, caption, chip, chipLabel, chipCount.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useRef} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport {alpha} from '@mui/material/styles';\nimport Chip from '@mui/material/Chip';\nimport Typography from '@mui/material/Typography';\n\nimport ScrollableRow from '@/ui/layout/ScrollableRow.jsx';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaQuickFilters)\nconst THEME_NAME = 'CalcitaQuickFilters';\nconst QuickRoot = piecePart(THEME_NAME, 'Root', Box);\nconst QuickCaption = piecePart(THEME_NAME, 'Caption', Typography);\nconst QuickChip = piecePart(THEME_NAME, 'Chip', Chip);\nconst QuickChipLabel = piecePart(THEME_NAME, 'ChipLabel', Box);\nconst QuickChipCount = piecePart(THEME_NAME, 'ChipCount', Box);\n\n\n// qué tan marcado va el velo del contador del filtro elegido\nconst ACTIVE_COUNT_VEIL_OPACITY = 0.18;\n\n/**\n * El velo del contador del filtro elegido: el color del texto base (negro en claro, blanco en oscuro) casi transparente.\n * Un tema con variables CSS trae ese color en theme.vars; el tema por omisión de MUI, en su modo.\n *\n * @param {object} theme tema de MUI\n * @returns {string} color CSS\n */\nfunction activeCountVeilOf(theme) {\n if (theme.vars) {\n return `rgba(${theme.vars.palette.common.onBackgroundChannel} / ${ACTIVE_COUNT_VEIL_OPACITY})`;\n }\n const baseTextColor = theme.palette.mode === 'dark' ? theme.palette.common.white : theme.palette.common.black;\n\n return alpha(baseTextColor, ACTIVE_COUNT_VEIL_OPACITY);\n}\n\n/** \"99+\" arriba de 99 y \"1.2k\" arriba de 999: el chip no se estira. */\nfunction compactCount(count) {\n if (count > 999) {\n return `${(count / 1000).toFixed(1)}k`;\n }\n if (count > 99) {\n return '99+';\n }\n return String(count);\n}\n\n/**\n * @param {object} props\n * @param {string} props.value opción activa ('' = todas)\n * @param {(value: string) => void} props.onChange\n * @param {Array<{value: string, label: import('react').ReactNode, count?: number}>} [props.options]\n * @param {import('react').ReactNode} [props.caption]\n * @param {string} [props.ariaLabel]\n * @param {import('react').ReactNode} [props.extra] al final de la tira (p. ej. un rango de fechas)\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\nfunction QuickFiltersContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaQuickFilters.defaultProps) y encima lo que llega aquí\n const {value, onChange, options = [], caption, ariaLabel, extra, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('table', texts);\n const activeChip = useRef(null);\n const isFirstRender = useRef(true);\n\n // al cambiar la selección desde fuera (alguien limpió los filtros) el chip activo se trae a la vista; en el primer\n // render sin animación: una tira que se mueve sola al abrir la pantalla se siente rota\n useEffect(() => {\n if (!activeChip.current) {\n return;\n }\n const behavior = isFirstRender.current ? 'instant' : 'smooth';\n isFirstRender.current = false;\n activeChip.current.scrollIntoView({behavior, block: 'nearest', inline: 'center'});\n }, [value]);\n\n // guard clause: con una sola opción no hay entre qué saltar\n if (options.length <= 1) {\n return null;\n }\n\n return (\n <QuickRoot ownSx={{mb: 1}}>\n {caption && (\n <QuickCaption variant=\"caption\" color=\"text.secondary\" ownSx={{px: 0.25}}>{caption}</QuickCaption>\n )}\n <ScrollableRow role=\"tablist\" aria-label={ariaLabel}>\n {options.map((option) => {\n const isActive = option.value === value;\n return (\n <QuickChip\n key={option.value || '__all__'}\n ref={isActive ? activeChip : null}\n role=\"tab\"\n aria-selected={isActive}\n clickable\n onClick={() => onChange(isActive ? '' : option.value)}\n // el elegido trae su ×: \"volver a Todas\" no se descubre solo\n onDelete={isActive && option.value ? () => onChange('') : undefined}\n variant={isActive ? 'filled' : 'outlined'}\n color={isActive ? 'primary' : 'default'}\n label={(\n <QuickChipLabel component=\"span\" ownSx={{display: 'inline-flex', alignItems: 'center', gap: 0.75}}>\n <span>{option.label}</span>\n {option.count !== null && option.count !== undefined && (\n <QuickChipCount component=\"span\"\n aria-label={t('quickFilters.countAriaLabel', {count: option.count})}\n // velo del color del texto base (negro en claro, blanco en oscuro) y no rgba fijo\n ownSx={(theme) => ({\n px: 0.75, borderRadius: '6px', fontSize: 11, fontWeight: 700, minWidth: 18,\n textAlign: 'center', color: 'inherit',\n bgcolor: isActive ? activeCountVeilOf(theme) : 'action.selected',\n })}>\n {compactCount(option.count)}\n </QuickChipCount>\n )}\n </QuickChipLabel>\n )}\n ownSx={{flex: '0 0 auto', height: 32}}\n />\n );\n })}\n {extra}\n </ScrollableRow>\n </QuickRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst QuickFilters = withPieceSlots(QuickFiltersContent, THEME_NAME);\nexport default QuickFilters;\n"],"names":[],"mappings":"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"}
|
|
@@ -5,12 +5,17 @@ import Tooltip from "@mui/material/Tooltip";
|
|
|
5
5
|
import HelpOutlineRoundedIcon from "@mui/icons-material/HelpOutlineRounded";
|
|
6
6
|
import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
|
|
7
7
|
import { warnUnknownProps } from "../../toolkit/unknownProps.js";
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
|
|
9
|
+
const THEME_NAME = "CalcitaHelpButton";
|
|
10
|
+
const HelpButtonRoot = piecePart(THEME_NAME, "Root", IconButton);
|
|
11
|
+
function HelpButtonContent(props) {
|
|
12
|
+
const { onClick, label, size = "medium", sx, texts, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
13
|
+
warnUnknownProps(THEME_NAME, unknownProps);
|
|
10
14
|
const { t } = useToolkitTranslation("common", texts);
|
|
11
15
|
const text = label ?? t("help.button");
|
|
12
|
-
return /* @__PURE__ */ jsx(Tooltip, { title: text, children: /* @__PURE__ */ jsx(
|
|
16
|
+
return /* @__PURE__ */ jsx(Tooltip, { title: text, children: /* @__PURE__ */ jsx(HelpButtonRoot, { "aria-label": text, onClick, size, sx, children: /* @__PURE__ */ jsx(HelpOutlineRoundedIcon, { fontSize: size === "small" ? "small" : "medium" }) }) });
|
|
13
17
|
}
|
|
18
|
+
const HelpButton = withPieceSlots(HelpButtonContent, THEME_NAME);
|
|
14
19
|
export {
|
|
15
20
|
HelpButton as default
|
|
16
21
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HelpButton.js","sources":["../../../src/ui/help/HelpButton.jsx"],"sourcesContent":["// El botón «?» que vuelve a abrir la ayuda de una pantalla (la del carrusel o la que sea): un ícono con su nombre para el\n// lector de pantalla y su globo al pasar el cursor.\n//\n// Genérico del paquete: function (regla de la casa).\nimport IconButton from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded';\n\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n/**\n * @param {object} props\n * @param {() => void} props.onClick\n * @param {string} [props.label] ya traducido; por omisión «Ayuda de esta pantalla»\n * @param {'small'|'medium'|'large'} [props.size]\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":"HelpButton.js","sources":["../../../src/ui/help/HelpButton.jsx"],"sourcesContent":["// El botón «?» que vuelve a abrir la ayuda de una pantalla (la del carrusel o la que sea): un ícono con su nombre para el\n// lector de pantalla y su globo al pasar el cursor.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaHelpButton con defaultProps, styleOverrides de\n// sus partes (root) y slots/slotProps para cambiarlas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport IconButton from '@mui/material/IconButton';\nimport Tooltip from '@mui/material/Tooltip';\nimport HelpOutlineRoundedIcon from '@mui/icons-material/HelpOutlineRounded';\n\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaHelpButton)\nconst THEME_NAME = 'CalcitaHelpButton';\nconst HelpButtonRoot = piecePart(THEME_NAME, 'Root', IconButton);\n\n/**\n * @param {object} props\n * @param {() => void} props.onClick\n * @param {string} [props.label] ya traducido; por omisión «Ayuda de esta pantalla»\n * @param {'small'|'medium'|'large'} [props.size]\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 HelpButtonContent(props) {\n const {onClick, label, size = 'medium', sx, texts, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const {t} = useToolkitTranslation('common', texts);\n const text = label ?? t('help.button');\n return (\n <Tooltip title={text}>\n <HelpButtonRoot aria-label={text} onClick={onClick} size={size} sx={sx}>\n <HelpOutlineRoundedIcon fontSize={size === 'small' ? 'small' : 'medium'} />\n </HelpButtonRoot>\n </Tooltip>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst HelpButton = withPieceSlots(HelpButtonContent, THEME_NAME);\nexport default HelpButton;\n"],"names":[],"mappings":";;;;;;;;AAgBA,MAAM,aAAa;AACnB,MAAM,iBAAiB,UAAU,YAAY,QAAQ,UAAU;AAU/D,SAAS,kBAAkB,OAAO;AAC9B,QAAM,EAAC,SAAS,OAAO,OAAO,UAAU,IAAI,OAAO,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AACrG,mBAAiB,YAAY,YAAY;AACzC,QAAM,EAAC,EAAA,IAAK,sBAAsB,UAAU,KAAK;AACjD,QAAM,OAAO,SAAS,EAAE,aAAa;AACrC,6BACK,SAAA,EAAQ,OAAO,MACZ,UAAA,oBAAC,gBAAA,EAAe,cAAY,MAAM,SAAkB,MAAY,IAC5D,UAAA,oBAAC,0BAAuB,UAAU,SAAS,UAAU,UAAU,UAAU,GAC7E,EAAA,CACJ;AAER;AAGA,MAAM,aAAa,eAAe,mBAAmB,UAAU;"}
|
|
@@ -15,7 +15,7 @@ import Stack from "@mui/material/Stack";
|
|
|
15
15
|
import Typography from "@mui/material/Typography";
|
|
16
16
|
import useMediaQuery from "@mui/material/useMediaQuery";
|
|
17
17
|
import CloseRoundedIcon from "@mui/icons-material/CloseRounded";
|
|
18
|
-
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
18
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
|
|
19
19
|
import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
|
|
20
20
|
import { warnUnknownProps } from "../../toolkit/unknownProps.js";
|
|
21
21
|
const HELP_CLOSE_REASON = Object.freeze({ finished: "finished", closed: "closed" });
|
|
@@ -27,7 +27,7 @@ const HelpMedia = piecePart(THEME_NAME, "Media", Box);
|
|
|
27
27
|
const HelpContent = piecePart(THEME_NAME, "Content", DialogContent);
|
|
28
28
|
const HelpDots = piecePart(THEME_NAME, "Dots", Stack);
|
|
29
29
|
const HelpActions = piecePart(THEME_NAME, "Actions", DialogActions);
|
|
30
|
-
function
|
|
30
|
+
function HelpCarouselDialogContent(props) {
|
|
31
31
|
const {
|
|
32
32
|
open,
|
|
33
33
|
onClose,
|
|
@@ -147,6 +147,7 @@ function HelpCarouselDialog(props) {
|
|
|
147
147
|
}
|
|
148
148
|
);
|
|
149
149
|
}
|
|
150
|
+
const HelpCarouselDialog = withPieceSlots(HelpCarouselDialogContent, THEME_NAME);
|
|
150
151
|
export {
|
|
151
152
|
HELP_CLOSE_REASON,
|
|
152
153
|
HelpCarouselDialog as default
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HelpCarouselDialog.js","sources":["../../../src/ui/help/HelpCarouselDialog.jsx"],"sourcesContent":["// La ayuda en carrusel: unos cuantos pasos, cada uno con su imagen o ilustración, su título y su texto, para explicar una\n// pantalla la primera vez que se entra (o cuando cambia). Se avanza con «Siguiente», con los puntos de abajo, con las\n// flechas del teclado o deslizando con el dedo; el último paso dice «Listo». Con «reducir movimiento» del sistema no hay\n// animación.\n//\n// Cuándo sale y que se recuerde lo hace useHelpCarousel; esta ventana solo enseña y avisa:\n// onClose(reason, {dontShowAgain}) reason 'finished' (terminó) o 'closed' (la cerró antes); el proyecto puede guardarlo\n// también en su servidor\n// onStepChange(index) cada paso que se ve\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaHelpCarouselDialog con defaultProps y\n// styleOverrides de sus partes: media, content, dots, actions.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useId, useRef, useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport ButtonBase from '@mui/material/ButtonBase';\nimport Checkbox from '@mui/material/Checkbox';\nimport Dialog from '@mui/material/Dialog';\nimport DialogActions from '@mui/material/DialogActions';\nimport DialogContent from '@mui/material/DialogContent';\nimport Fade from '@mui/material/Fade';\nimport FormControlLabel from '@mui/material/FormControlLabel';\nimport IconButton from '@mui/material/IconButton';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport useMediaQuery from '@mui/material/useMediaQuery';\nimport CloseRoundedIcon from '@mui/icons-material/CloseRounded';\n\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n/** Por qué se cerró la ayuda. */\nexport const HELP_CLOSE_REASON = Object.freeze({finished: 'finished', closed: 'closed'});\n\n// lo que hay que deslizar con el dedo para cambiar de paso (px)\nconst SWIPE_DISTANCE = 50;\nconst FADE_MILLISECONDS = 220;\nconst MEDIA_HEIGHT = 200;\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaHelpCarouselDialog)\nconst THEME_NAME = 'CalcitaHelpCarouselDialog';\nconst HelpMedia = piecePart(THEME_NAME, 'Media', Box);\nconst HelpContent = piecePart(THEME_NAME, 'Content', DialogContent);\nconst HelpDots = piecePart(THEME_NAME, 'Dots', Stack);\nconst HelpActions = piecePart(THEME_NAME, 'Actions', DialogActions);\n\n/**\n * @param {object} props\n * @param {boolean} props.open\n * @param {(reason: string, details: {dontShowAgain: boolean}) => void} props.onClose HELP_CLOSE_REASON y si marcó «No volver a mostrar»\n * @param {Array<{title: string, content: import('react').ReactNode, image?: string, imageAlt?: string, media?: import('react').ReactNode}>} props.steps\n * title y content ya traducidos; image (una dirección) o media (una ilustración propia) arriba\n * @param {string} [props.title] ya traducido: de qué es la ayuda («Cómo usar el tablero»), arriba de los pasos\n * @param {boolean} [props.showDontShowAgain] la casilla «No volver a mostrar al entrar» (por omisión sí)\n * @param {(index: number) => void} [props.onStepChange]\n * @param {number} [props.initialStep]\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nexport default function HelpCarouselDialog(props) {\n const {\n open, onClose, steps, title, showDontShowAgain = true, onStepChange, initialStep = 0, 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 [stepIndex, setStepIndex] = useState(initialStep);\n const [dontShowAgain, setDontShowAgain] = useState(false);\n const reducesMotion = useMediaQuery('(prefers-reduced-motion: reduce)');\n const swipeStartRef = useRef(null);\n const lastIndex = steps.length - 1;\n const step = steps[Math.min(stepIndex, lastIndex)];\n\n // cada vez que se abre empieza en su primer paso\n useEffect(() => {\n if (open) {\n setStepIndex(initialStep);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n useEffect(() => {\n if (open) {\n onStepChange?.(stepIndex);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, stepIndex]);\n\n const goTo = (index) => setStepIndex(Math.max(0, Math.min(lastIndex, index)));\n const close = (reason) => onClose(reason, {dontShowAgain});\n const next = () => (stepIndex >= lastIndex ? close(HELP_CLOSE_REASON.finished) : goTo(stepIndex + 1));\n\n if (!step) {\n return null;\n }\n return (\n <Dialog\n open={open}\n onClose={() => close(HELP_CLOSE_REASON.closed)}\n maxWidth=\"sm\"\n fullWidth\n aria-labelledby={titleId}\n onKeyDown={(event) => {\n // las flechas cambian de paso (dentro de la casilla o de un botón también: no escriben nada)\n if (event.key === 'ArrowRight') {\n goTo(stepIndex + 1);\n } else if (event.key === 'ArrowLeft') {\n goTo(stepIndex - 1);\n }\n }}\n >\n <Box\n onPointerDown={(event) => {\n swipeStartRef.current = event.clientX;\n }}\n onPointerUp={(event) => {\n const distance = swipeStartRef.current === null ? 0 : event.clientX - swipeStartRef.current;\n swipeStartRef.current = null;\n if (Math.abs(distance) >= SWIPE_DISTANCE) {\n goTo(stepIndex + (distance < 0 ? 1 : -1));\n }\n }}\n sx={{position: 'relative', touchAction: 'pan-y'}}\n >\n <IconButton aria-label={t('help.close')} onClick={() => close(HELP_CLOSE_REASON.closed)}\n sx={{position: 'absolute', top: 8, right: 8, zIndex: 1}}>\n <CloseRoundedIcon />\n </IconButton>\n <Fade key={stepIndex} in appear={!reducesMotion} timeout={reducesMotion ? 0 : FADE_MILLISECONDS}>\n <div>\n {(step.image || step.media) && (\n <HelpMedia ownSx={{height: MEDIA_HEIGHT, display: 'grid', placeItems: 'center', overflow: 'hidden', bgcolor: 'action.hover'}}>\n {step.media ?? <Box component=\"img\" src={step.image} alt={step.imageAlt ?? ''} sx={{maxWidth: '100%', maxHeight: '100%', objectFit: 'contain'}} />}\n </HelpMedia>\n )}\n <HelpContent ownSx={{pt: 2.5}}>\n {title && <Typography variant=\"overline\" color=\"text.secondary\" component=\"p\">{title}</Typography>}\n <Typography id={titleId} variant=\"h6\" component=\"h2\" sx={{pr: 4}}>{step.title}</Typography>\n <Typography component=\"div\" color=\"text.secondary\" sx={{mt: 1}}>{step.content}</Typography>\n </HelpContent>\n </div>\n </Fade>\n </Box>\n {/* los puntos: dónde va y para saltar a un paso */}\n <HelpDots direction=\"row\" ownSx={{justifyContent: 'center', gap: 1, pb: 1}} role=\"group\" aria-label={t('help.stepOf', {current: stepIndex + 1, total: steps.length})}>\n {steps.map((unused, index) => (\n <ButtonBase key={index} onClick={() => goTo(index)} aria-label={t('help.goToStep', {number: index + 1})}\n aria-current={index === stepIndex ? 'step' : undefined}\n sx={{width: index === stepIndex ? 22 : 8, height: 8, borderRadius: 4, transition: reducesMotion ? 'none' : 'width 200ms',\n bgcolor: index === stepIndex ? 'primary.main' : 'action.disabled'}} />\n ))}\n </HelpDots>\n <HelpActions ownSx={{px: 3, pb: 2, gap: 1, flexWrap: 'wrap'}}>\n {showDontShowAgain && (\n <FormControlLabel sx={{mr: 'auto'}} label={t('help.dontShowAgain')}\n control={<Checkbox size=\"small\" checked={dontShowAgain} onChange={(event) => setDontShowAgain(event.target.checked)} />} />\n )}\n {stepIndex > 0 && <Button onClick={() => goTo(stepIndex - 1)}>{t('help.back')}</Button>}\n <Button variant=\"contained\" onClick={next} autoFocus>\n {stepIndex >= lastIndex ? t('help.done') : t('help.next')}\n </Button>\n </HelpActions>\n </Dialog>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"HelpCarouselDialog.js","sources":["../../../src/ui/help/HelpCarouselDialog.jsx"],"sourcesContent":["// La ayuda en carrusel: unos cuantos pasos, cada uno con su imagen o ilustración, su título y su texto, para explicar una\n// pantalla la primera vez que se entra (o cuando cambia). Se avanza con «Siguiente», con los puntos de abajo, con las\n// flechas del teclado o deslizando con el dedo; el último paso dice «Listo». Con «reducir movimiento» del sistema no hay\n// animación.\n//\n// Cuándo sale y que se recuerde lo hace useHelpCarousel; esta ventana solo enseña y avisa:\n// onClose(reason, {dontShowAgain}) reason 'finished' (terminó) o 'closed' (la cerró antes); el proyecto puede guardarlo\n// también en su servidor\n// onStepChange(index) cada paso que se ve\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaHelpCarouselDialog con defaultProps y\n// styleOverrides de sus partes: media, content, dots, actions.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useEffect, useId, useRef, useState} from 'react';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport ButtonBase from '@mui/material/ButtonBase';\nimport Checkbox from '@mui/material/Checkbox';\nimport Dialog from '@mui/material/Dialog';\nimport DialogActions from '@mui/material/DialogActions';\nimport DialogContent from '@mui/material/DialogContent';\nimport Fade from '@mui/material/Fade';\nimport FormControlLabel from '@mui/material/FormControlLabel';\nimport IconButton from '@mui/material/IconButton';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport useMediaQuery from '@mui/material/useMediaQuery';\nimport CloseRoundedIcon from '@mui/icons-material/CloseRounded';\n\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n/** Por qué se cerró la ayuda. */\nexport const HELP_CLOSE_REASON = Object.freeze({finished: 'finished', closed: 'closed'});\n\n// lo que hay que deslizar con el dedo para cambiar de paso (px)\nconst SWIPE_DISTANCE = 50;\nconst FADE_MILLISECONDS = 220;\nconst MEDIA_HEIGHT = 200;\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaHelpCarouselDialog)\nconst THEME_NAME = 'CalcitaHelpCarouselDialog';\nconst HelpMedia = piecePart(THEME_NAME, 'Media', Box);\nconst HelpContent = piecePart(THEME_NAME, 'Content', DialogContent);\nconst HelpDots = piecePart(THEME_NAME, 'Dots', Stack);\nconst HelpActions = piecePart(THEME_NAME, 'Actions', DialogActions);\n\n/**\n * @param {object} props\n * @param {boolean} props.open\n * @param {(reason: string, details: {dontShowAgain: boolean}) => void} props.onClose HELP_CLOSE_REASON y si marcó «No volver a mostrar»\n * @param {Array<{title: string, content: import('react').ReactNode, image?: string, imageAlt?: string, media?: import('react').ReactNode}>} props.steps\n * title y content ya traducidos; image (una dirección) o media (una ilustración propia) arriba\n * @param {string} [props.title] ya traducido: de qué es la ayuda («Cómo usar el tablero»), arriba de los pasos\n * @param {boolean} [props.showDontShowAgain] la casilla «No volver a mostrar al entrar» (por omisión sí)\n * @param {(index: number) => void} [props.onStepChange]\n * @param {number} [props.initialStep]\n * @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete\n */\nfunction HelpCarouselDialogContent(props) {\n const {\n open, onClose, steps, title, showDontShowAgain = true, onStepChange, initialStep = 0, 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 [stepIndex, setStepIndex] = useState(initialStep);\n const [dontShowAgain, setDontShowAgain] = useState(false);\n const reducesMotion = useMediaQuery('(prefers-reduced-motion: reduce)');\n const swipeStartRef = useRef(null);\n const lastIndex = steps.length - 1;\n const step = steps[Math.min(stepIndex, lastIndex)];\n\n // cada vez que se abre empieza en su primer paso\n useEffect(() => {\n if (open) {\n setStepIndex(initialStep);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n useEffect(() => {\n if (open) {\n onStepChange?.(stepIndex);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open, stepIndex]);\n\n const goTo = (index) => setStepIndex(Math.max(0, Math.min(lastIndex, index)));\n const close = (reason) => onClose(reason, {dontShowAgain});\n const next = () => (stepIndex >= lastIndex ? close(HELP_CLOSE_REASON.finished) : goTo(stepIndex + 1));\n\n if (!step) {\n return null;\n }\n return (\n <Dialog\n open={open}\n onClose={() => close(HELP_CLOSE_REASON.closed)}\n maxWidth=\"sm\"\n fullWidth\n aria-labelledby={titleId}\n onKeyDown={(event) => {\n // las flechas cambian de paso (dentro de la casilla o de un botón también: no escriben nada)\n if (event.key === 'ArrowRight') {\n goTo(stepIndex + 1);\n } else if (event.key === 'ArrowLeft') {\n goTo(stepIndex - 1);\n }\n }}\n >\n <Box\n onPointerDown={(event) => {\n swipeStartRef.current = event.clientX;\n }}\n onPointerUp={(event) => {\n const distance = swipeStartRef.current === null ? 0 : event.clientX - swipeStartRef.current;\n swipeStartRef.current = null;\n if (Math.abs(distance) >= SWIPE_DISTANCE) {\n goTo(stepIndex + (distance < 0 ? 1 : -1));\n }\n }}\n sx={{position: 'relative', touchAction: 'pan-y'}}\n >\n <IconButton aria-label={t('help.close')} onClick={() => close(HELP_CLOSE_REASON.closed)}\n sx={{position: 'absolute', top: 8, right: 8, zIndex: 1}}>\n <CloseRoundedIcon />\n </IconButton>\n <Fade key={stepIndex} in appear={!reducesMotion} timeout={reducesMotion ? 0 : FADE_MILLISECONDS}>\n <div>\n {(step.image || step.media) && (\n <HelpMedia ownSx={{height: MEDIA_HEIGHT, display: 'grid', placeItems: 'center', overflow: 'hidden', bgcolor: 'action.hover'}}>\n {step.media ?? <Box component=\"img\" src={step.image} alt={step.imageAlt ?? ''} sx={{maxWidth: '100%', maxHeight: '100%', objectFit: 'contain'}} />}\n </HelpMedia>\n )}\n <HelpContent ownSx={{pt: 2.5}}>\n {title && <Typography variant=\"overline\" color=\"text.secondary\" component=\"p\">{title}</Typography>}\n <Typography id={titleId} variant=\"h6\" component=\"h2\" sx={{pr: 4}}>{step.title}</Typography>\n <Typography component=\"div\" color=\"text.secondary\" sx={{mt: 1}}>{step.content}</Typography>\n </HelpContent>\n </div>\n </Fade>\n </Box>\n {/* los puntos: dónde va y para saltar a un paso */}\n <HelpDots direction=\"row\" ownSx={{justifyContent: 'center', gap: 1, pb: 1}} role=\"group\" aria-label={t('help.stepOf', {current: stepIndex + 1, total: steps.length})}>\n {steps.map((unused, index) => (\n <ButtonBase key={index} onClick={() => goTo(index)} aria-label={t('help.goToStep', {number: index + 1})}\n aria-current={index === stepIndex ? 'step' : undefined}\n sx={{width: index === stepIndex ? 22 : 8, height: 8, borderRadius: 4, transition: reducesMotion ? 'none' : 'width 200ms',\n bgcolor: index === stepIndex ? 'primary.main' : 'action.disabled'}} />\n ))}\n </HelpDots>\n <HelpActions ownSx={{px: 3, pb: 2, gap: 1, flexWrap: 'wrap'}}>\n {showDontShowAgain && (\n <FormControlLabel sx={{mr: 'auto'}} label={t('help.dontShowAgain')}\n control={<Checkbox size=\"small\" checked={dontShowAgain} onChange={(event) => setDontShowAgain(event.target.checked)} />} />\n )}\n {stepIndex > 0 && <Button onClick={() => goTo(stepIndex - 1)}>{t('help.back')}</Button>}\n <Button variant=\"contained\" onClick={next} autoFocus>\n {stepIndex >= lastIndex ? t('help.done') : t('help.next')}\n </Button>\n </HelpActions>\n </Dialog>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst HelpCarouselDialog = withPieceSlots(HelpCarouselDialogContent, THEME_NAME);\nexport default HelpCarouselDialog;\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { Fragment as Fragment$1, isValidElement, cloneElement, createElement } from "react";
|
|
4
|
+
import { parseMarkedText } from "./markedTextPieces.js";
|
|
5
|
+
import { warnUnknownProps } from "../../toolkit/unknownProps.js";
|
|
6
|
+
function renderPieces(pieces, marks, keyPrefix) {
|
|
7
|
+
return pieces.map((piece, index) => {
|
|
8
|
+
const key = `${keyPrefix}${index}`;
|
|
9
|
+
if (piece.type === "text") {
|
|
10
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: piece.value }, key);
|
|
11
|
+
}
|
|
12
|
+
const children = piece.children.length > 0 ? renderPieces(piece.children, marks, `${key}.`) : void 0;
|
|
13
|
+
const mark = marks[piece.name];
|
|
14
|
+
if (isValidElement(mark)) {
|
|
15
|
+
return cloneElement(mark, { key }, children);
|
|
16
|
+
}
|
|
17
|
+
if (typeof mark === "function") {
|
|
18
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: mark(children) }, key);
|
|
19
|
+
}
|
|
20
|
+
return createElement(mark, { key }, children);
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function MarkedText({ text, marks, ...unknownProps }) {
|
|
24
|
+
warnUnknownProps("MarkedText", unknownProps);
|
|
25
|
+
const pieces = parseMarkedText(text, Object.keys(marks ?? {}));
|
|
26
|
+
return /* @__PURE__ */ jsx(Fragment, { children: renderPieces(pieces, marks ?? {}, "") });
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
MarkedText as default
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=MarkedText.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkedText.js","sources":["../../../src/ui/labels/MarkedText.jsx"],"sourcesContent":["// Un texto traducido con una o varias palabras pintadas distinto: «Optimiza tu negocio con <highlight>financiamiento</highlight>\n// inteligente» en UNA llave, y la pantalla dice cómo se pinta cada marca. Lo mismo que <Trans> de react-i18next, sin\n// depender de i18next.\n//\n// <MarkedText text={t('home.headline')}\n// marks={{highlight: <Box component=\"strong\" sx={{color: 'primary.main'}} />, terms: <Link href=\"/terminos\" />}} />\n//\n// Cada marca puede ser:\n// un elemento <Box component=\"strong\" />, <Link href=\"/terminos\" />: se le pone lo de adentro como hijos\n// una etiqueta 'strong', 'em': se crea con lo de adentro como hijos\n// una función (children) => <Tooltip title=\"…\"><span>{children}</span></Tooltip>\n// OJO: un componente propio va como elemento (<Resaltado />), no suelto (Resaltado): una función suelta se toma como la de\n// arriba, que recibe lo de adentro.\n//\n// NO pinta HTML: solo las marcas que se nombran en `marks`; todo lo demás (también un «<b>» que venga en un dato) sale como\n// texto (markedTextPieces.js).\n//\n// Genérico del paquete: function (regla de la casa).\nimport {Fragment, cloneElement, createElement, isValidElement} from 'react';\n\nimport {parseMarkedText} from '@/ui/labels/markedTextPieces.js';\nimport {warnUnknownProps} from '@/toolkit/unknownProps.js';\n\n/**\n * Pinta los pedazos con la marca de cada uno.\n *\n * @param {Array<object>} pieces\n * @param {Record<string, any>} marks\n * @param {string} keyPrefix\n * @returns {import('react').ReactNode[]}\n */\nfunction renderPieces(pieces, marks, keyPrefix) {\n return pieces.map((piece, index) => {\n const key = `${keyPrefix}${index}`;\n if (piece.type === 'text') {\n return <Fragment key={key}>{piece.value}</Fragment>;\n }\n const children = piece.children.length > 0 ? renderPieces(piece.children, marks, `${key}.`) : undefined;\n const mark = marks[piece.name];\n if (isValidElement(mark)) {\n return cloneElement(mark, {key}, children);\n }\n if (typeof mark === 'function') {\n return <Fragment key={key}>{mark(children)}</Fragment>;\n }\n return createElement(mark, {key}, children);\n });\n}\n\n/**\n * @param {object} props\n * @param {string} props.text el texto ya traducido, con sus marcas\n * @param {Record<string, import('react').ReactElement|string|((children: import('react').ReactNode) => import('react').ReactNode)>} props.marks\n * cómo se pinta cada marca, por su nombre: un elemento, una etiqueta ('strong') o una función que recibe lo de adentro\n */\nexport default function MarkedText({text, marks, ...unknownProps}) {\n warnUnknownProps('MarkedText', unknownProps);\n const pieces = parseMarkedText(text, Object.keys(marks ?? {}));\n return <>{renderPieces(pieces, marks ?? {}, '')}</>;\n}\n"],"names":["Fragment"],"mappings":";;;;;AA+BA,SAAS,aAAa,QAAQ,OAAO,WAAW;AAC5C,SAAO,OAAO,IAAI,CAAC,OAAO,UAAU;AAChC,UAAM,MAAM,GAAG,SAAS,GAAG,KAAK;AAChC,QAAI,MAAM,SAAS,QAAQ;AACvB,aAAO,oBAACA,YAAA,EAAoB,UAAA,MAAM,SAAZ,GAAkB;AAAA,IAC5C;AACA,UAAM,WAAW,MAAM,SAAS,SAAS,IAAI,aAAa,MAAM,UAAU,OAAO,GAAG,GAAG,GAAG,IAAI;AAC9F,UAAM,OAAO,MAAM,MAAM,IAAI;AAC7B,QAAI,eAAe,IAAI,GAAG;AACtB,aAAO,aAAa,MAAM,EAAC,IAAA,GAAM,QAAQ;AAAA,IAC7C;AACA,QAAI,OAAO,SAAS,YAAY;AAC5B,iCAAQA,YAAA,EAAoB,UAAA,KAAK,QAAQ,KAAnB,GAAqB;AAAA,IAC/C;AACA,WAAO,cAAc,MAAM,EAAC,IAAA,GAAM,QAAQ;AAAA,EAC9C,CAAC;AACL;AAQA,SAAwB,WAAW,EAAC,MAAM,OAAO,GAAG,gBAAe;AAC/D,mBAAiB,cAAc,YAAY;AAC3C,QAAM,SAAS,gBAAgB,MAAM,OAAO,KAAK,SAAS,CAAA,CAAE,CAAC;AAC7D,yCAAU,UAAA,aAAa,QAAQ,SAAS,CAAA,GAAI,EAAE,GAAE;AACpD;"}
|
package/dist/ui/labels/Tag.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import Chip from "@mui/material/Chip";
|
|
4
4
|
import Tooltip from "@mui/material/Tooltip";
|
|
5
|
-
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
5
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
|
|
6
6
|
const THEME_NAME = "CalcitaTag";
|
|
7
7
|
const TagChip = piecePart(THEME_NAME, "Root", Chip);
|
|
8
|
-
function
|
|
8
|
+
function TagContent(props) {
|
|
9
9
|
const { label, tooltip, color = "default", variant = "outlined", size = "small", onDelete, sx, ...chipProps } = usePieceProps(props, THEME_NAME);
|
|
10
10
|
const chip = /* @__PURE__ */ jsx(
|
|
11
11
|
TagChip,
|
|
@@ -25,6 +25,7 @@ function Tag(props) {
|
|
|
25
25
|
}
|
|
26
26
|
return /* @__PURE__ */ jsx(Tooltip, { title: tooltip, children: chip });
|
|
27
27
|
}
|
|
28
|
+
const Tag = withPieceSlots(TagContent, THEME_NAME);
|
|
28
29
|
export {
|
|
29
30
|
Tag as default
|
|
30
31
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tag.js","sources":["../../../src/ui/labels/Tag.jsx"],"sourcesContent":["// El chip genérico: etiqueta + color + explicación, en un solo lugar.\n//\n// Para un valor que viene de un diccionario (estatus, formato, hallazgo) se usa StatusChip, que saca etiqueta, color y\n// tooltip del diccionario. Tag es para lo que no es un valor cerrado: un filtro puesto, \"total aproximado\", un conteo.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaTag con defaultProps y\n// styleOverrides.root (el sx de la pantalla sigue ganando a todo).\n//\n// Genérico del paquete: function (regla de la casa).\nimport Chip from '@mui/material/Chip';\nimport Tooltip from '@mui/material/Tooltip';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y su parte (theme.components.CalcitaTag)\nconst THEME_NAME = 'CalcitaTag';\nconst TagChip = piecePart(THEME_NAME, 'Root', Chip);\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode} props.label texto visible, ya traducido\n * @param {string} [props.tooltip] qué significa (aparece al pasar el cursor)\n * @param {string} [props.color] color del tema de MUI\n * @param {'filled'|'outlined'} [props.variant]\n * @param {'small'|'medium'} [props.size]\n * @param {() => void} [props.onDelete]\n * @param {object} [props.sx]\n */\
|
|
1
|
+
{"version":3,"file":"Tag.js","sources":["../../../src/ui/labels/Tag.jsx"],"sourcesContent":["// El chip genérico: etiqueta + color + explicación, en un solo lugar.\n//\n// Para un valor que viene de un diccionario (estatus, formato, hallazgo) se usa StatusChip, que saca etiqueta, color y\n// tooltip del diccionario. Tag es para lo que no es un valor cerrado: un filtro puesto, \"total aproximado\", un conteo.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaTag con defaultProps y\n// styleOverrides.root (el sx de la pantalla sigue ganando a todo).\n//\n// Genérico del paquete: function (regla de la casa).\nimport Chip from '@mui/material/Chip';\nimport Tooltip from '@mui/material/Tooltip';\nimport {piecePart, usePieceProps, withPieceSlots} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y su parte (theme.components.CalcitaTag)\nconst THEME_NAME = 'CalcitaTag';\nconst TagChip = piecePart(THEME_NAME, 'Root', Chip);\n\n/**\n * @param {object} props\n * @param {import('react').ReactNode} props.label texto visible, ya traducido\n * @param {string} [props.tooltip] qué significa (aparece al pasar el cursor)\n * @param {string} [props.color] color del tema de MUI\n * @param {'filled'|'outlined'} [props.variant]\n * @param {'small'|'medium'} [props.size]\n * @param {() => void} [props.onDelete]\n * @param {object} [props.sx]\n */\nfunction TagContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaTag.defaultProps) y encima lo que llega aquí\n const {label, tooltip, color = 'default', variant = 'outlined', size = 'small', onDelete, sx, ...chipProps} = usePieceProps(props, THEME_NAME);\n const chip = (\n <TagChip label={label} size={size} variant={variant} color={color} onDelete={onDelete}\n ownSx={{fontWeight: 500}} sx={sx} {...chipProps} />\n );\n\n // guard clause: sin tooltip no se envuelve (un Tooltip vacío se traga el cursor sin dar nada a cambio)\n if (!tooltip) {\n return chip;\n }\n return <Tooltip title={tooltip}>{chip}</Tooltip>;\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst Tag = withPieceSlots(TagContent, THEME_NAME);\nexport default Tag;\n"],"names":[],"mappings":";;;;;AAcA,MAAM,aAAa;AACnB,MAAM,UAAU,UAAU,YAAY,QAAQ,IAAI;AAYlD,SAAS,WAAW,OAAO;AAEvB,QAAM,EAAC,OAAO,SAAS,QAAQ,WAAW,UAAU,YAAY,OAAO,SAAS,UAAU,IAAI,GAAG,UAAA,IAAa,cAAc,OAAO,UAAU;AAC7I,QAAM,OACF;AAAA,IAAC;AAAA,IAAA;AAAA,MAAQ;AAAA,MAAc;AAAA,MAAY;AAAA,MAAkB;AAAA,MAAc;AAAA,MAC1D,OAAO,EAAC,YAAY,IAAA;AAAA,MAAM;AAAA,MAAS,GAAG;AAAA,IAAA;AAAA,EAAA;AAInD,MAAI,CAAC,SAAS;AACV,WAAO;AAAA,EACX;AACA,SAAO,oBAAC,SAAA,EAAQ,OAAO,SAAU,UAAA,MAAK;AAC1C;AAGA,MAAM,MAAM,eAAe,YAAY,UAAU;"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const MARK_PATTERN = /<(\/?)([A-Za-z][\w-]*)\s*(\/?)>/g;
|
|
2
|
+
function parseMarkedText(text, allowedNames) {
|
|
3
|
+
const allowed = new Set(allowedNames);
|
|
4
|
+
const root = { children: [] };
|
|
5
|
+
const open = [{ node: root, name: null, rawStart: 0, raw: "" }];
|
|
6
|
+
let lastIndex = 0;
|
|
7
|
+
const pushText = (parent, value) => {
|
|
8
|
+
if (!value) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const previous = parent.children.at(-1);
|
|
12
|
+
if (previous?.type === "text") {
|
|
13
|
+
previous.value += value;
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
parent.children.push({ type: "text", value });
|
|
17
|
+
};
|
|
18
|
+
for (const match of String(text ?? "").matchAll(MARK_PATTERN)) {
|
|
19
|
+
const [raw, closing, name, selfClosing] = match;
|
|
20
|
+
const current = open.at(-1);
|
|
21
|
+
pushText(current.node, text.slice(lastIndex, match.index));
|
|
22
|
+
lastIndex = match.index + raw.length;
|
|
23
|
+
if (!allowed.has(name)) {
|
|
24
|
+
pushText(current.node, raw);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (selfClosing && !closing) {
|
|
28
|
+
current.node.children.push({ type: "mark", name, children: [] });
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (!closing) {
|
|
32
|
+
const mark = { type: "mark", name, children: [] };
|
|
33
|
+
current.node.children.push(mark);
|
|
34
|
+
open.push({ node: mark, name, raw });
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (current.name === name) {
|
|
38
|
+
open.pop();
|
|
39
|
+
} else {
|
|
40
|
+
pushText(current.node, raw);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
pushText(open.at(-1).node, String(text ?? "").slice(lastIndex));
|
|
44
|
+
while (open.length > 1) {
|
|
45
|
+
const unclosed = open.pop();
|
|
46
|
+
const parent = open.at(-1).node;
|
|
47
|
+
const index = parent.children.indexOf(unclosed.node);
|
|
48
|
+
parent.children.splice(index, 1, { type: "text", value: unclosed.raw }, ...unclosed.node.children);
|
|
49
|
+
mergeAdjacentTexts(parent.children);
|
|
50
|
+
}
|
|
51
|
+
return root.children;
|
|
52
|
+
}
|
|
53
|
+
function mergeAdjacentTexts(pieces) {
|
|
54
|
+
for (let index = pieces.length - 1; index > 0; index -= 1) {
|
|
55
|
+
if (pieces[index].type === "text" && pieces[index - 1].type === "text") {
|
|
56
|
+
pieces[index - 1].value += pieces[index].value;
|
|
57
|
+
pieces.splice(index, 1);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
parseMarkedText
|
|
63
|
+
};
|
|
64
|
+
//# sourceMappingURL=markedTextPieces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markedTextPieces.js","sources":["../../../src/ui/labels/markedTextPieces.js"],"sourcesContent":["// Lee un texto traducido con marcas («Optimiza tu negocio con <highlight>financiamiento</highlight> inteligente») y lo\n// parte en pedazos: texto suelto y marcas con lo que llevan adentro. Quien traduce ve la frase completa en una sola llave\n// (antes había que partirla en tres: headlineBefore, headlineHighlight, headlineAfter).\n//\n// NO es HTML ni lo pinta como HTML: solo se reconocen las marcas que la pantalla nombra (`allowedNames`), cada una se cambia\n// por un componente de React y todo lo demás sale como texto. Un «<b>» que venga en un dato (el nombre de una persona) se\n// queda tal cual, letra por letra.\n//\n// <nombre>…</nombre> una marca con texto adentro (pueden ir unas dentro de otras)\n// <nombre/> una marca sola (un ícono, un salto de línea)\n//\n// Funciones puras, no renderizan: function (regla de la casa).\n\nconst MARK_PATTERN = /<(\\/?)([A-Za-z][\\w-]*)\\s*(\\/?)>/g;\n\n/**\n * @typedef {{type: 'text', value: string} | {type: 'mark', name: string, children: MarkedTextPiece[]}} MarkedTextPiece\n */\n\n/**\n * Los pedazos de un texto con marcas.\n *\n * Una marca que abre y no cierra (o cierra sin abrir) sale como texto: así un error de quien traduce se ve en pantalla en\n * lugar de comerse el resto de la frase.\n *\n * @param {string} text el texto ya traducido\n * @param {string[]} allowedNames las marcas que la pantalla sabe pintar\n * @returns {MarkedTextPiece[]}\n */\nexport function parseMarkedText(text, allowedNames) {\n const allowed = new Set(allowedNames);\n const root = {children: []};\n // las marcas abiertas, de afuera hacia adentro, con el lugar donde empezó cada una (para regresarla a texto si no cierra)\n const open = [{node: root, name: null, rawStart: 0, raw: ''}];\n let lastIndex = 0;\n\n const pushText = (parent, value) => {\n if (!value) {\n return;\n }\n const previous = parent.children.at(-1);\n if (previous?.type === 'text') {\n previous.value += value;\n return;\n }\n parent.children.push({type: 'text', value});\n };\n\n for (const match of String(text ?? '').matchAll(MARK_PATTERN)) {\n const [raw, closing, name, selfClosing] = match;\n const current = open.at(-1);\n pushText(current.node, text.slice(lastIndex, match.index));\n lastIndex = match.index + raw.length;\n\n if (!allowed.has(name)) {\n pushText(current.node, raw);\n continue;\n }\n if (selfClosing && !closing) {\n current.node.children.push({type: 'mark', name, children: []});\n continue;\n }\n if (!closing) {\n const mark = {type: 'mark', name, children: []};\n current.node.children.push(mark);\n open.push({node: mark, name, raw});\n continue;\n }\n // cierra: tiene que ser la última que se abrió; si no, sale como texto\n if (current.name === name) {\n open.pop();\n } else {\n pushText(current.node, raw);\n }\n }\n pushText(open.at(-1).node, String(text ?? '').slice(lastIndex));\n\n // las que quedaron abiertas se regresan a texto: su etiqueta de apertura y lo que llevaban adentro\n while (open.length > 1) {\n const unclosed = open.pop();\n const parent = open.at(-1).node;\n const index = parent.children.indexOf(unclosed.node);\n parent.children.splice(index, 1, {type: 'text', value: unclosed.raw}, ...unclosed.node.children);\n mergeAdjacentTexts(parent.children);\n }\n return root.children;\n}\n\n/** Junta textos seguidos (quedan así al regresar a texto una marca sin cerrar). */\nfunction mergeAdjacentTexts(pieces) {\n for (let index = pieces.length - 1; index > 0; index -= 1) {\n if (pieces[index].type === 'text' && pieces[index - 1].type === 'text') {\n pieces[index - 1].value += pieces[index].value;\n pieces.splice(index, 1);\n }\n }\n}\n"],"names":[],"mappings":"AAaA,MAAM,eAAe;AAgBd,SAAS,gBAAgB,MAAM,cAAc;AAChD,QAAM,UAAU,IAAI,IAAI,YAAY;AACpC,QAAM,OAAO,EAAC,UAAU,GAAE;AAE1B,QAAM,OAAO,CAAC,EAAC,MAAM,MAAM,MAAM,MAAM,UAAU,GAAG,KAAK,GAAE,CAAC;AAC5D,MAAI,YAAY;AAEhB,QAAM,WAAW,CAAC,QAAQ,UAAU;AAChC,QAAI,CAAC,OAAO;AACR;AAAA,IACJ;AACA,UAAM,WAAW,OAAO,SAAS,GAAG,EAAE;AACtC,QAAI,UAAU,SAAS,QAAQ;AAC3B,eAAS,SAAS;AAClB;AAAA,IACJ;AACA,WAAO,SAAS,KAAK,EAAC,MAAM,QAAQ,MAAK,CAAC;AAAA,EAC9C;AAEA,aAAW,SAAS,OAAO,QAAQ,EAAE,EAAE,SAAS,YAAY,GAAG;AAC3D,UAAM,CAAC,KAAK,SAAS,MAAM,WAAW,IAAI;AAC1C,UAAM,UAAU,KAAK,GAAG,EAAE;AAC1B,aAAS,QAAQ,MAAM,KAAK,MAAM,WAAW,MAAM,KAAK,CAAC;AACzD,gBAAY,MAAM,QAAQ,IAAI;AAE9B,QAAI,CAAC,QAAQ,IAAI,IAAI,GAAG;AACpB,eAAS,QAAQ,MAAM,GAAG;AAC1B;AAAA,IACJ;AACA,QAAI,eAAe,CAAC,SAAS;AACzB,cAAQ,KAAK,SAAS,KAAK,EAAC,MAAM,QAAQ,MAAM,UAAU,CAAA,EAAE,CAAC;AAC7D;AAAA,IACJ;AACA,QAAI,CAAC,SAAS;AACV,YAAM,OAAO,EAAC,MAAM,QAAQ,MAAM,UAAU,GAAE;AAC9C,cAAQ,KAAK,SAAS,KAAK,IAAI;AAC/B,WAAK,KAAK,EAAC,MAAM,MAAM,MAAM,IAAG,CAAC;AACjC;AAAA,IACJ;AAEA,QAAI,QAAQ,SAAS,MAAM;AACvB,WAAK,IAAG;AAAA,IACZ,OAAO;AACH,eAAS,QAAQ,MAAM,GAAG;AAAA,IAC9B;AAAA,EACJ;AACA,WAAS,KAAK,GAAG,EAAE,EAAE,MAAM,OAAO,QAAQ,EAAE,EAAE,MAAM,SAAS,CAAC;AAG9D,SAAO,KAAK,SAAS,GAAG;AACpB,UAAM,WAAW,KAAK,IAAG;AACzB,UAAM,SAAS,KAAK,GAAG,EAAE,EAAE;AAC3B,UAAM,QAAQ,OAAO,SAAS,QAAQ,SAAS,IAAI;AACnD,WAAO,SAAS,OAAO,OAAO,GAAG,EAAC,MAAM,QAAQ,OAAO,SAAS,IAAG,GAAG,GAAG,SAAS,KAAK,QAAQ;AAC/F,uBAAmB,OAAO,QAAQ;AAAA,EACtC;AACA,SAAO,KAAK;AAChB;AAGA,SAAS,mBAAmB,QAAQ;AAChC,WAAS,QAAQ,OAAO,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG;AACvD,QAAI,OAAO,KAAK,EAAE,SAAS,UAAU,OAAO,QAAQ,CAAC,EAAE,SAAS,QAAQ;AACpE,aAAO,QAAQ,CAAC,EAAE,SAAS,OAAO,KAAK,EAAE;AACzC,aAAO,OAAO,OAAO,CAAC;AAAA,IAC1B;AAAA,EACJ;AACJ;"}
|
|
@@ -7,7 +7,7 @@ import AccordionSummary from "@mui/material/AccordionSummary";
|
|
|
7
7
|
import Box from "@mui/material/Box";
|
|
8
8
|
import Typography from "@mui/material/Typography";
|
|
9
9
|
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
|
10
|
-
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
10
|
+
import { piecePart, withPieceSlots, usePieceProps } from "../../theme/themePieces.js";
|
|
11
11
|
import { warnUnknownProps } from "../../toolkit/unknownProps.js";
|
|
12
12
|
const THEME_NAME = "CalcitaCollapsibleSection";
|
|
13
13
|
const CollapsibleRoot = piecePart(THEME_NAME, "Root", Box);
|
|
@@ -31,7 +31,7 @@ const HEADER_SX = {
|
|
|
31
31
|
"&:hover": { bgcolor: "action.hover" },
|
|
32
32
|
"& .MuiAccordionSummary-content": { my: 0.75, minWidth: 0 }
|
|
33
33
|
};
|
|
34
|
-
function
|
|
34
|
+
function CollapsibleSectionContent(props) {
|
|
35
35
|
const { collapsedTitle, expandedTitle, hint = "", defaultExpanded = false, onExpandedChange, children, ...unknownProps } = usePieceProps(props, THEME_NAME);
|
|
36
36
|
warnUnknownProps(THEME_NAME, unknownProps);
|
|
37
37
|
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
|
|
@@ -58,6 +58,7 @@ function CollapsibleSection(props) {
|
|
|
58
58
|
}
|
|
59
59
|
) });
|
|
60
60
|
}
|
|
61
|
+
const CollapsibleSection = withPieceSlots(CollapsibleSectionContent, THEME_NAME);
|
|
61
62
|
export {
|
|
62
63
|
CollapsibleSection as default
|
|
63
64
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CollapsibleSection.js","sources":["../../../src/ui/layout/CollapsibleSection.jsx"],"sourcesContent":["// Sección que se pliega: un encabezado que se toca y, debajo, el contenido, que se abre y se cierra.\n//\n// Para qué: en una página de detalle las cifras quedan a la vista y lo demás se guarda aquí; quien quiere más, lo abre.\n//\n// El encabezado se ve como lo que es, un botón a todo lo ancho: recuadro, la flecha ADELANTE del texto y otro fondo al pasar\n// el cursor. Su texto dice lo que va a pasar al tocarlo («Ver el detalle…» plegada, «Ocultar el detalle…» abierta) y,\n// plegada, un renglón más chico dice qué hay adentro: así nadie tiene que abrirla para saber si ahí está lo que busca.\n// No dice «dé clic»: en el teléfono no hay clic, y un tooltip tampoco se ve ahí.\n//\n// El contenido va sin fondo ni borde propios: adentro van tarjetas (SectionCard) y un recuadro alrededor se vería como\n// tarjeta dentro de tarjeta.\n//\n// OJO: el acordeón de MUI se quita el margen de arriba cuando está abierto y es el primero de su tipo entre sus hermanos.\n// Dentro de un Stack, que separa a sus hijos con margen, eso hacía brincar el encabezado 16 px al abrir y al cerrar. Por eso\n// va envuelto en una caja: el margen del Stack cae en la caja y el encabezado se queda quieto.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaCollapsibleSection con defaultProps y\n// styleOverrides de sus partes: root, accordion, summary, titleArea, collapsedTitle, expandedTitle, details.\n//\n// Genérico del paquete: function (regla de la casa). No sabe de negocio: sus textos llegan ya traducidos.\nimport {useState} from 'react';\nimport Accordion from '@mui/material/Accordion';\nimport AccordionDetails from '@mui/material/AccordionDetails';\nimport AccordionSummary from '@mui/material/AccordionSummary';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\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.CalcitaCollapsibleSection)\nconst THEME_NAME = 'CalcitaCollapsibleSection';\nconst CollapsibleRoot = piecePart(THEME_NAME, 'Root', Box);\nconst CollapsibleAccordion = piecePart(THEME_NAME, 'Accordion', Accordion);\nconst CollapsibleSummary = piecePart(THEME_NAME, 'Summary', AccordionSummary);\nconst CollapsibleTitleArea = piecePart(THEME_NAME, 'TitleArea', Box);\nconst CollapsibleCollapsedTitle = piecePart(THEME_NAME, 'CollapsedTitle', Typography);\nconst CollapsibleExpandedTitle = piecePart(THEME_NAME, 'ExpandedTitle', Typography);\nconst CollapsibleDetails = piecePart(THEME_NAME, 'Details', AccordionDetails);\n\n// el mismo radio de las tarjetas (theme/components/surfaces.js): el encabezado se lee como una pieza más de la página\nconst CARD_BORDER_RADIUS_PIXELS = 10;\n\nconst HEADER_SX = {\n // la flecha adelante del texto: al final del renglón quedaba lejos de lo que se lee y pasaba inadvertida\n flexDirection: 'row-reverse', gap: 1, px: 1.5, minHeight: 44,\n border: 1, borderColor: 'divider', borderRadius: `${CARD_BORDER_RADIUS_PIXELS}px`, bgcolor: 'background.paper',\n '&:hover': {bgcolor: 'action.hover'},\n '& .MuiAccordionSummary-content': {my: 0.75, minWidth: 0},\n};\n\n/**\n * @param {object} props\n * @param {string} props.collapsedTitle lo que dice plegada, ya traducido («Ver el detalle de la validación»)\n * @param {string} props.expandedTitle lo que dice abierta («Ocultar el detalle de la validación»)\n * @param {string} [props.hint] plegada, qué hay adentro («Incluye resumen, motivos de rechazo y descargas.»)\n * @param {boolean} [props.defaultExpanded] si empieza abierta; por omisión empieza plegada\n * @param {(isExpanded: boolean) => void} [props.onExpandedChange] la persona la abrió o la plegó (por ejemplo, para pedir lo de\n * adentro hasta que se abre)\n * @param {import('react').ReactNode} props.children\n */\
|
|
1
|
+
{"version":3,"file":"CollapsibleSection.js","sources":["../../../src/ui/layout/CollapsibleSection.jsx"],"sourcesContent":["// Sección que se pliega: un encabezado que se toca y, debajo, el contenido, que se abre y se cierra.\n//\n// Para qué: en una página de detalle las cifras quedan a la vista y lo demás se guarda aquí; quien quiere más, lo abre.\n//\n// El encabezado se ve como lo que es, un botón a todo lo ancho: recuadro, la flecha ADELANTE del texto y otro fondo al pasar\n// el cursor. Su texto dice lo que va a pasar al tocarlo («Ver el detalle…» plegada, «Ocultar el detalle…» abierta) y,\n// plegada, un renglón más chico dice qué hay adentro: así nadie tiene que abrirla para saber si ahí está lo que busca.\n// No dice «dé clic»: en el teléfono no hay clic, y un tooltip tampoco se ve ahí.\n//\n// El contenido va sin fondo ni borde propios: adentro van tarjetas (SectionCard) y un recuadro alrededor se vería como\n// tarjeta dentro de tarjeta.\n//\n// OJO: el acordeón de MUI se quita el margen de arriba cuando está abierto y es el primero de su tipo entre sus hermanos.\n// Dentro de un Stack, que separa a sus hijos con margen, eso hacía brincar el encabezado 16 px al abrir y al cerrar. Por eso\n// va envuelto en una caja: el margen del Stack cae en la caja y el encabezado se queda quieto.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaCollapsibleSection con defaultProps y\n// styleOverrides de sus partes: root, accordion, summary, titleArea, collapsedTitle, expandedTitle, details.\n//\n// Genérico del paquete: function (regla de la casa). No sabe de negocio: sus textos llegan ya traducidos.\nimport {useState} from 'react';\nimport Accordion from '@mui/material/Accordion';\nimport AccordionDetails from '@mui/material/AccordionDetails';\nimport AccordionSummary from '@mui/material/AccordionSummary';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\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.CalcitaCollapsibleSection)\nconst THEME_NAME = 'CalcitaCollapsibleSection';\nconst CollapsibleRoot = piecePart(THEME_NAME, 'Root', Box);\nconst CollapsibleAccordion = piecePart(THEME_NAME, 'Accordion', Accordion);\nconst CollapsibleSummary = piecePart(THEME_NAME, 'Summary', AccordionSummary);\nconst CollapsibleTitleArea = piecePart(THEME_NAME, 'TitleArea', Box);\nconst CollapsibleCollapsedTitle = piecePart(THEME_NAME, 'CollapsedTitle', Typography);\nconst CollapsibleExpandedTitle = piecePart(THEME_NAME, 'ExpandedTitle', Typography);\nconst CollapsibleDetails = piecePart(THEME_NAME, 'Details', AccordionDetails);\n\n// el mismo radio de las tarjetas (theme/components/surfaces.js): el encabezado se lee como una pieza más de la página\nconst CARD_BORDER_RADIUS_PIXELS = 10;\n\nconst HEADER_SX = {\n // la flecha adelante del texto: al final del renglón quedaba lejos de lo que se lee y pasaba inadvertida\n flexDirection: 'row-reverse', gap: 1, px: 1.5, minHeight: 44,\n border: 1, borderColor: 'divider', borderRadius: `${CARD_BORDER_RADIUS_PIXELS}px`, bgcolor: 'background.paper',\n '&:hover': {bgcolor: 'action.hover'},\n '& .MuiAccordionSummary-content': {my: 0.75, minWidth: 0},\n};\n\n/**\n * @param {object} props\n * @param {string} props.collapsedTitle lo que dice plegada, ya traducido («Ver el detalle de la validación»)\n * @param {string} props.expandedTitle lo que dice abierta («Ocultar el detalle de la validación»)\n * @param {string} [props.hint] plegada, qué hay adentro («Incluye resumen, motivos de rechazo y descargas.»)\n * @param {boolean} [props.defaultExpanded] si empieza abierta; por omisión empieza plegada\n * @param {(isExpanded: boolean) => void} [props.onExpandedChange] la persona la abrió o la plegó (por ejemplo, para pedir lo de\n * adentro hasta que se abre)\n * @param {import('react').ReactNode} props.children\n */\nfunction CollapsibleSectionContent(props) {\n // lo que el proyecto puso en su tema (components.CalcitaCollapsibleSection.defaultProps) y encima lo que llega aquí\n const {collapsedTitle, expandedTitle, hint = '', defaultExpanded = false, onExpandedChange, children, ...unknownProps} = usePieceProps(props, THEME_NAME);\n warnUnknownProps(THEME_NAME, unknownProps);\n const [isExpanded, setIsExpanded] = useState(defaultExpanded);\n const changeExpanded = (nextIsExpanded) => {\n setIsExpanded(nextIsExpanded);\n onExpandedChange?.(nextIsExpanded);\n };\n\n return (\n <CollapsibleRoot ownSx={{minWidth: 0}}>\n <CollapsibleAccordion expanded={isExpanded} onChange={(changeEvent, nextIsExpanded) => changeExpanded(nextIsExpanded)}\n disableGutters elevation={0} square ownSx={{bgcolor: 'transparent', '&::before': {display: 'none'}}}>\n {/* NOTA: el acordeón ya envuelve este renglón en un encabezado (h3); los textos van como span para no anidar dos */}\n <CollapsibleSummary expandIcon={<ExpandMoreIcon color=\"primary\" />} ownSx={HEADER_SX}>\n <CollapsibleTitleArea ownSx={{minWidth: 0}}>\n <CollapsibleCollapsedTitle variant=\"subtitle2\" component=\"span\" color=\"primary\" ownSx={{display: 'block'}}>\n {isExpanded ? expandedTitle : collapsedTitle}\n </CollapsibleCollapsedTitle>\n {!isExpanded && hint && (\n <CollapsibleExpandedTitle variant=\"caption\" component=\"span\" color=\"text.secondary\" ownSx={{display: 'block'}}>{hint}</CollapsibleExpandedTitle>\n )}\n </CollapsibleTitleArea>\n </CollapsibleSummary>\n <CollapsibleDetails ownSx={{p: 0, pt: 2}}>{children}</CollapsibleDetails>\n </CollapsibleAccordion>\n </CollapsibleRoot>\n );\n}\n\n// lo que se exporta: la pieza con slots y slotProps para cambiar sus partes (themePieces.js)\nconst CollapsibleSection = withPieceSlots(CollapsibleSectionContent, THEME_NAME);\nexport default CollapsibleSection;\n"],"names":[],"mappings":";;;;;;;;;;;AA+BA,MAAM,aAAa;AACnB,MAAM,kBAAkB,UAAU,YAAY,QAAQ,GAAG;AACzD,MAAM,uBAAuB,UAAU,YAAY,aAAa,SAAS;AACzE,MAAM,qBAAqB,UAAU,YAAY,WAAW,gBAAgB;AAC5E,MAAM,uBAAuB,UAAU,YAAY,aAAa,GAAG;AACnE,MAAM,4BAA4B,UAAU,YAAY,kBAAkB,UAAU;AACpF,MAAM,2BAA2B,UAAU,YAAY,iBAAiB,UAAU;AAClF,MAAM,qBAAqB,UAAU,YAAY,WAAW,gBAAgB;AAG5E,MAAM,4BAA4B;AAElC,MAAM,YAAY;AAAA;AAAA,EAEd,eAAe;AAAA,EAAe,KAAK;AAAA,EAAG,IAAI;AAAA,EAAK,WAAW;AAAA,EAC1D,QAAQ;AAAA,EAAG,aAAa;AAAA,EAAW,cAAc,GAAG,yBAAyB;AAAA,EAAM,SAAS;AAAA,EAC5F,WAAW,EAAC,SAAS,eAAA;AAAA,EACrB,kCAAkC,EAAC,IAAI,MAAM,UAAU,EAAA;AAC3D;AAYA,SAAS,0BAA0B,OAAO;AAEtC,QAAM,EAAC,gBAAgB,eAAe,OAAO,IAAI,kBAAkB,OAAO,kBAAkB,UAAU,GAAG,aAAA,IAAgB,cAAc,OAAO,UAAU;AACxJ,mBAAiB,YAAY,YAAY;AACzC,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,eAAe;AAC5D,QAAM,iBAAiB,CAAC,mBAAmB;AACvC,kBAAc,cAAc;AAC5B,uBAAmB,cAAc;AAAA,EACrC;AAEA,6BACK,iBAAA,EAAgB,OAAO,EAAC,UAAU,KAC/B,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MAAqB,UAAU;AAAA,MAAY,UAAU,CAAC,aAAa,mBAAmB,eAAe,cAAc;AAAA,MACzG,gBAAc;AAAA,MAAC,WAAW;AAAA,MAAG,QAAM;AAAA,MAAC,OAAO,EAAC,SAAS,eAAe,aAAa,EAAC,SAAS,SAAM;AAAA,MAExG,UAAA;AAAA,QAAA,oBAAC,oBAAA,EAAmB,YAAY,oBAAC,gBAAA,EAAe,OAAM,UAAA,CAAU,GAAI,OAAO,WACvE,+BAAC,sBAAA,EAAqB,OAAO,EAAC,UAAU,KACpC,UAAA;AAAA,UAAA,oBAAC,2BAAA,EAA0B,SAAQ,aAAY,WAAU,QAAO,OAAM,WAAU,OAAO,EAAC,SAAS,QAAA,GAC5F,UAAA,aAAa,gBAAgB,gBAClC;AAAA,UACC,CAAC,cAAc,QACZ,oBAAC,0BAAA,EAAyB,SAAQ,WAAU,WAAU,QAAO,OAAM,kBAAiB,OAAO,EAAC,SAAS,QAAA,GAAW,UAAA,KAAA,CAAK;AAAA,QAAA,EAAA,CAE7H,EAAA,CACJ;AAAA,QACA,oBAAC,sBAAmB,OAAO,EAAC,GAAG,GAAG,IAAI,EAAA,GAAK,SAAA,CAAS;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA,GAE5D;AAER;AAGA,MAAM,qBAAqB,eAAe,2BAA2B,UAAU;"}
|