@stackcraftmx/calcita 0.27.0 → 0.30.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 +149 -0
- package/dist/DataTable/AuditTrailDialog.js +18 -14
- package/dist/DataTable/AuditTrailDialog.js.map +1 -1
- package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js +12 -6
- package/dist/DataTable/ColumnFilters/HeaderFilterPopover.js.map +1 -1
- package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js +8 -3
- package/dist/DataTable/ColumnFilters/MultiSelectColumnFilter.js.map +1 -1
- package/dist/DataTable/ColumnFilters/SortableFilterHeader.js +26 -18
- package/dist/DataTable/ColumnFilters/SortableFilterHeader.js.map +1 -1
- package/dist/DataTable/EmptyState.js +8 -3
- package/dist/DataTable/EmptyState.js.map +1 -1
- package/dist/DataTable/FilterChips.js +11 -5
- package/dist/DataTable/FilterChips.js.map +1 -1
- package/dist/DataTable/GoToPage.js +9 -4
- package/dist/DataTable/GoToPage.js.map +1 -1
- package/dist/DataTable/ServerTable.js +74 -61
- package/dist/DataTable/ServerTable.js.map +1 -1
- package/dist/DataTable/columns.js +1 -8
- package/dist/DataTable/columns.js.map +1 -1
- package/dist/access/PermissionMatrix.js +18 -9
- package/dist/access/PermissionMatrix.js.map +1 -1
- package/dist/account/AccountSecuritySection.js +8 -3
- package/dist/account/AccountSecuritySection.js.map +1 -1
- package/dist/account/DemoTotpCodeButton.js +8 -3
- package/dist/account/DemoTotpCodeButton.js.map +1 -1
- package/dist/account/ProfileScreen.js +19 -13
- package/dist/account/ProfileScreen.js.map +1 -1
- package/dist/account/SignInScreen.js +6 -2
- package/dist/account/SignInScreen.js.map +1 -1
- package/dist/appShell/AccountMenu.js +13 -5
- package/dist/appShell/AccountMenu.js.map +1 -1
- package/dist/appShell/AppLayout.js +100 -71
- package/dist/appShell/AppLayout.js.map +1 -1
- package/dist/appShell/AppearanceSettings.js +21 -13
- package/dist/appShell/AppearanceSettings.js.map +1 -1
- package/dist/appShell/AuthLayout.js +26 -13
- package/dist/appShell/AuthLayout.js.map +1 -1
- package/dist/appShell/BarActions.js +10 -5
- package/dist/appShell/BarActions.js.map +1 -1
- package/dist/appShell/BarCapsule.js +9 -4
- package/dist/appShell/BarCapsule.js.map +1 -1
- package/dist/appShell/BarSearch.js +7 -3
- package/dist/appShell/BarSearch.js.map +1 -1
- package/dist/appShell/HeaderTools.js +20 -15
- package/dist/appShell/HeaderTools.js.map +1 -1
- package/dist/appShell/MobileTabBar.js +25 -14
- package/dist/appShell/MobileTabBar.js.map +1 -1
- package/dist/appShell/SettingsMenu.js +7 -3
- package/dist/appShell/SettingsMenu.js.map +1 -1
- package/dist/appShell/SideMenu.js +53 -35
- package/dist/appShell/SideMenu.js.map +1 -1
- package/dist/appShell/SideMenuEntry.js +18 -9
- package/dist/appShell/SideMenuEntry.js.map +1 -1
- package/dist/appShell/SubmenuActionsMenu.js +6 -2
- package/dist/appShell/SubmenuActionsMenu.js.map +1 -1
- package/dist/appShell/TabBarEditor.js +16 -7
- package/dist/appShell/TabBarEditor.js.map +1 -1
- package/dist/appShell/TopMenu.js +12 -7
- package/dist/appShell/TopMenu.js.map +1 -1
- package/dist/appShell/Wordmark.js +6 -2
- package/dist/appShell/Wordmark.js.map +1 -1
- package/dist/auth/PasswordChecklist.js +14 -7
- package/dist/auth/PasswordChecklist.js.map +1 -1
- package/dist/calendar/EventCalendar.js +26 -19
- package/dist/calendar/EventCalendar.js.map +1 -1
- package/dist/calendar/EventDetails.js +28 -13
- package/dist/calendar/EventDetails.js.map +1 -1
- package/dist/downloads/DownloadManager.js +34 -18
- package/dist/downloads/DownloadManager.js.map +1 -1
- package/dist/feedback/ConfirmDialog.js +22 -17
- package/dist/feedback/ConfirmDialog.js.map +1 -1
- package/dist/feedback/ModalWaiting.js +12 -5
- package/dist/feedback/ModalWaiting.js.map +1 -1
- package/dist/feedback/NewBuildNotice.js +16 -8
- package/dist/feedback/NewBuildNotice.js.map +1 -1
- package/dist/filepond/FileDropzone.js +39 -31
- package/dist/filepond/FileDropzone.js.map +1 -1
- package/dist/forms/FormProblemAlert.js +4 -1
- package/dist/forms/FormProblemAlert.js.map +1 -1
- package/dist/forms/auth/SignInForm.js +6 -2
- package/dist/forms/auth/SignInForm.js.map +1 -1
- package/dist/forms/security/SecondStepForm.js +6 -2
- package/dist/forms/security/SecondStepForm.js.map +1 -1
- package/dist/forms/security/TwoStepVerificationCard.js +19 -9
- package/dist/forms/security/TwoStepVerificationCard.js.map +1 -1
- package/dist/hookForm/FormProblemAlert.js +4 -1
- package/dist/hookForm/FormProblemAlert.js.map +1 -1
- package/dist/inbox/InboxLayout.js +47 -29
- package/dist/inbox/InboxLayout.js.map +1 -1
- package/dist/inbox/MessageList.js +53 -32
- package/dist/inbox/MessageList.js.map +1 -1
- package/dist/inbox/MessageView.js +31 -15
- package/dist/inbox/MessageView.js.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/inputs/ColorInput.js +22 -17
- package/dist/inputs/ColorInput.js.map +1 -1
- package/dist/inputs/FormSection.js +66 -63
- package/dist/inputs/FormSection.js.map +1 -1
- package/dist/inputs/SelectInput.js +21 -16
- package/dist/inputs/SelectInput.js.map +1 -1
- package/dist/inputs/TextInput.js +25 -20
- package/dist/inputs/TextInput.js.map +1 -1
- package/dist/inputs/WizardLayout.js +21 -15
- package/dist/inputs/WizardLayout.js.map +1 -1
- package/dist/kanban/KanbanBoard.js +82 -50
- package/dist/kanban/KanbanBoard.js.map +1 -1
- package/dist/maps/MapView.js +19 -14
- package/dist/maps/MapView.js.map +1 -1
- package/dist/pwa/InstallAppSetting.js +4 -1
- package/dist/pwa/InstallAppSetting.js.map +1 -1
- package/dist/pwa/InstallInstructionsDialog.js +6 -2
- package/dist/pwa/InstallInstructionsDialog.js.map +1 -1
- package/dist/pwa/InstallPromptBanner.js +10 -5
- package/dist/pwa/InstallPromptBanner.js.map +1 -1
- package/dist/security/ActivityLog.js +6 -2
- package/dist/security/ActivityLog.js.map +1 -1
- package/dist/security/RecoveryCodesDialog.js +8 -3
- package/dist/security/RecoveryCodesDialog.js.map +1 -1
- package/dist/security/SessionsCard.js +12 -5
- package/dist/security/SessionsCard.js.map +1 -1
- package/dist/theme/components/glassComponents.js +19 -16
- package/dist/theme/components/glassComponents.js.map +1 -1
- package/dist/theme/components/minimalComponents.js +10 -6
- package/dist/theme/components/minimalComponents.js.map +1 -1
- package/dist/theme/createToolkitTheme.js +23 -6
- package/dist/theme/createToolkitTheme.js.map +1 -1
- package/dist/theme/cssTokens.js +23 -0
- package/dist/theme/cssTokens.js.map +1 -0
- package/dist/theme/glassSurface.js +64 -10
- package/dist/theme/glassSurface.js.map +1 -1
- package/dist/theme/glassToasterStyles.js +2 -3
- package/dist/theme/glassToasterStyles.js.map +1 -1
- package/dist/theme/themePieces.js +16 -0
- package/dist/theme/themePieces.js.map +1 -0
- package/dist/types/DataTable/AuditTrailDialog.d.ts +1 -1
- package/dist/types/DataTable/ColumnFilters/HeaderFilterPopover.d.ts +1 -1
- package/dist/types/DataTable/ColumnFilters/MultiSelectColumnFilter.d.ts +1 -1
- package/dist/types/DataTable/ColumnFilters/SortableFilterHeader.d.ts +1 -1
- package/dist/types/DataTable/EmptyState.d.ts +1 -1
- package/dist/types/DataTable/FilterChips.d.ts +1 -1
- package/dist/types/DataTable/GoToPage.d.ts +1 -1
- package/dist/types/DataTable/ServerTable.d.ts +1 -1
- package/dist/types/access/PermissionMatrix.d.ts +1 -1
- package/dist/types/account/AccountSecuritySection.d.ts +1 -1
- package/dist/types/account/DemoTotpCodeButton.d.ts +1 -1
- package/dist/types/account/ProfileScreen.d.ts +1 -1
- package/dist/types/account/SignInScreen.d.ts +1 -1
- package/dist/types/appShell/AccountMenu.d.ts +1 -1
- package/dist/types/appShell/AppLayout.d.ts +1 -1
- package/dist/types/appShell/AppearanceSettings.d.ts +1 -1
- package/dist/types/appShell/AuthLayout.d.ts +1 -1
- package/dist/types/appShell/BarActions.d.ts +1 -1
- package/dist/types/appShell/BarCapsule.d.ts +1 -1
- package/dist/types/appShell/BarSearch.d.ts +1 -1
- package/dist/types/appShell/HeaderTools.d.ts +1 -1
- package/dist/types/appShell/MobileTabBar.d.ts +1 -1
- package/dist/types/appShell/SettingsMenu.d.ts +1 -1
- package/dist/types/appShell/SideMenu.d.ts +1 -1
- package/dist/types/appShell/SideMenuEntry.d.ts +1 -1
- package/dist/types/appShell/SubmenuActionsMenu.d.ts +1 -1
- package/dist/types/appShell/TabBarEditor.d.ts +1 -1
- package/dist/types/appShell/TopMenu.d.ts +1 -1
- package/dist/types/appShell/Wordmark.d.ts +1 -1
- package/dist/types/auth/PasswordChecklist.d.ts +1 -1
- package/dist/types/calendar/EventCalendar.d.ts +1 -1
- package/dist/types/calendar/EventDetails.d.ts +1 -1
- package/dist/types/feedback/ConfirmDialog.d.ts +1 -1
- package/dist/types/feedback/ModalWaiting.d.ts +1 -1
- package/dist/types/feedback/NewBuildNotice.d.ts +1 -1
- package/dist/types/filepond/FileDropzone.d.ts +1 -1
- package/dist/types/forms/auth/SignInForm.d.ts +1 -1
- package/dist/types/forms/security/SecondStepForm.d.ts +1 -1
- package/dist/types/forms/security/TwoStepVerificationCard.d.ts +1 -1
- package/dist/types/inbox/InboxLayout.d.ts +1 -1
- package/dist/types/inbox/MessageList.d.ts +1 -1
- package/dist/types/inbox/MessageView.d.ts +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/inputs/ColorInput.d.ts +1 -1
- package/dist/types/inputs/FormSection.d.ts +2 -2
- package/dist/types/inputs/SelectInput.d.ts +1 -1
- package/dist/types/inputs/TextInput.d.ts +1 -1
- package/dist/types/inputs/WizardLayout.d.ts +1 -1
- package/dist/types/kanban/KanbanBoard.d.ts +1 -1
- package/dist/types/maps/MapView.d.ts +1 -1
- package/dist/types/pwa/InstallInstructionsDialog.d.ts +1 -1
- package/dist/types/pwa/InstallPromptBanner.d.ts +1 -1
- package/dist/types/security/ActivityLog.d.ts +1 -1
- package/dist/types/security/RecoveryCodesDialog.d.ts +1 -1
- package/dist/types/security/SessionsCard.d.ts +1 -1
- package/dist/types/theme/createToolkitTheme.d.ts +33 -1
- package/dist/types/theme/cssTokens.d.ts +46 -0
- package/dist/types/theme/glassSurface.d.ts +57 -1
- package/dist/types/theme/themePieces.d.ts +20 -0
- package/dist/types/ui/actions/ActionsMenu.d.ts +1 -1
- package/dist/types/ui/actions/DownloadMenu.d.ts +1 -1
- package/dist/types/ui/actions/SelectionActions.d.ts +1 -1
- package/dist/types/ui/filters/DateRangeFilter.d.ts +1 -1
- package/dist/types/ui/filters/PeriodRangeSelector.d.ts +1 -1
- package/dist/types/ui/filters/QuickFilters.d.ts +1 -1
- package/dist/types/ui/filters/SegmentedControl.d.ts +7 -2
- package/dist/types/ui/labels/StatusChip.d.ts +1 -1
- package/dist/types/ui/labels/Tag.d.ts +1 -1
- package/dist/types/ui/layout/CollapsibleSection.d.ts +1 -1
- package/dist/types/ui/layout/ContentDialog.d.ts +1 -1
- package/dist/types/ui/layout/DefinitionList.d.ts +1 -1
- package/dist/types/ui/layout/DetailHeader.d.ts +1 -1
- package/dist/types/ui/layout/ErrorPage.d.ts +1 -1
- package/dist/types/ui/layout/GlassPanel.d.ts +1 -1
- package/dist/types/ui/layout/PageHeader.d.ts +1 -1
- package/dist/types/ui/layout/PageHeading.d.ts +1 -1
- package/dist/types/ui/layout/ProfileHeader.d.ts +1 -1
- package/dist/types/ui/layout/ScrollableRow.d.ts +1 -1
- package/dist/types/ui/layout/SectionCard.d.ts +1 -1
- package/dist/types/ui/metrics/BarList.d.ts +1 -1
- package/dist/types/ui/metrics/CalendarHeatmap.d.ts +1 -1
- package/dist/types/ui/metrics/ChartTooltip.d.ts +1 -1
- package/dist/types/ui/metrics/ColumnChart.d.ts +1 -1
- package/dist/types/ui/metrics/LineChart.d.ts +1 -1
- package/dist/types/ui/metrics/MetricCard.d.ts +1 -1
- package/dist/types/ui/metrics/TableToggle.d.ts +1 -1
- package/dist/types/ui/navigation/ColorSchemeToggle.d.ts +1 -1
- package/dist/types/ui/navigation/FontSizeToggle.d.ts +1 -1
- package/dist/types/ui/navigation/LanguageToggle.d.ts +1 -1
- package/dist/types/ui/navigation/PageBreadcrumbs.d.ts +1 -1
- package/dist/types/ui/timeline/GroupedTimeline.d.ts +1 -1
- package/dist/types/upload/FileDropzone.d.ts +1 -1
- package/dist/ui/actions/ActionsMenu.js +9 -4
- package/dist/ui/actions/ActionsMenu.js.map +1 -1
- package/dist/ui/actions/DownloadMenu.js +21 -17
- package/dist/ui/actions/DownloadMenu.js.map +1 -1
- package/dist/ui/actions/SelectionActions.js +15 -7
- package/dist/ui/actions/SelectionActions.js.map +1 -1
- package/dist/ui/filters/DateRangeFilter.js +11 -5
- package/dist/ui/filters/DateRangeFilter.js.map +1 -1
- package/dist/ui/filters/PeriodRangeSelector.js +11 -5
- package/dist/ui/filters/PeriodRangeSelector.js.map +1 -1
- package/dist/ui/filters/QuickFilters.js +16 -8
- package/dist/ui/filters/QuickFilters.js.map +1 -1
- package/dist/ui/filters/SegmentedControl.js +12 -5
- package/dist/ui/filters/SegmentedControl.js.map +1 -1
- package/dist/ui/labels/StatusChip.js +35 -25
- package/dist/ui/labels/StatusChip.js.map +1 -1
- package/dist/ui/labels/Tag.js +8 -3
- package/dist/ui/labels/Tag.js.map +1 -1
- package/dist/ui/layout/CollapsibleSection.js +18 -8
- package/dist/ui/layout/CollapsibleSection.js.map +1 -1
- package/dist/ui/layout/ContentDialog.js +13 -6
- package/dist/ui/layout/ContentDialog.js.map +1 -1
- package/dist/ui/layout/DefinitionList.js +13 -6
- package/dist/ui/layout/DefinitionList.js.map +1 -1
- package/dist/ui/layout/DetailHeader.js +14 -6
- package/dist/ui/layout/DetailHeader.js.map +1 -1
- package/dist/ui/layout/ErrorPage.js +20 -15
- package/dist/ui/layout/ErrorPage.js.map +1 -1
- package/dist/ui/layout/FullPageLoader.js +4 -1
- package/dist/ui/layout/FullPageLoader.js.map +1 -1
- package/dist/ui/layout/GlassPanel.js +8 -4
- package/dist/ui/layout/GlassPanel.js.map +1 -1
- package/dist/ui/layout/PageHeader.js +10 -4
- package/dist/ui/layout/PageHeader.js.map +1 -1
- package/dist/ui/layout/PageHeading.js +17 -8
- package/dist/ui/layout/PageHeading.js.map +1 -1
- package/dist/ui/layout/ProfileHeader.js +21 -10
- package/dist/ui/layout/ProfileHeader.js.map +1 -1
- package/dist/ui/layout/ScrollableRow.js +19 -15
- package/dist/ui/layout/ScrollableRow.js.map +1 -1
- package/dist/ui/layout/SectionCard.js +10 -4
- package/dist/ui/layout/SectionCard.js.map +1 -1
- package/dist/ui/metrics/BarList.js +9 -4
- package/dist/ui/metrics/BarList.js.map +1 -1
- package/dist/ui/metrics/CalendarHeatmap.js +40 -21
- package/dist/ui/metrics/CalendarHeatmap.js.map +1 -1
- package/dist/ui/metrics/ChartTooltip.js +6 -2
- package/dist/ui/metrics/ChartTooltip.js.map +1 -1
- package/dist/ui/metrics/ColumnChart.js +22 -18
- package/dist/ui/metrics/ColumnChart.js.map +1 -1
- package/dist/ui/metrics/LineChart.js +20 -16
- package/dist/ui/metrics/LineChart.js.map +1 -1
- package/dist/ui/metrics/MetricCard.js +42 -24
- package/dist/ui/metrics/MetricCard.js.map +1 -1
- package/dist/ui/metrics/TableToggle.js +7 -2
- package/dist/ui/metrics/TableToggle.js.map +1 -1
- package/dist/ui/metrics/chartParts.js +14 -5
- package/dist/ui/metrics/chartParts.js.map +1 -1
- package/dist/ui/navigation/ColorSchemeToggle.js +8 -4
- package/dist/ui/navigation/ColorSchemeToggle.js.map +1 -1
- package/dist/ui/navigation/FontSizeToggle.js +6 -2
- package/dist/ui/navigation/FontSizeToggle.js.map +1 -1
- package/dist/ui/navigation/LanguageToggle.js +8 -4
- package/dist/ui/navigation/LanguageToggle.js.map +1 -1
- package/dist/ui/navigation/PageBreadcrumbs.js +12 -6
- package/dist/ui/navigation/PageBreadcrumbs.js.map +1 -1
- package/dist/ui/timeline/GroupedTimeline.js +26 -13
- package/dist/ui/timeline/GroupedTimeline.js.map +1 -1
- package/dist/upload/FileDropzone.js +35 -25
- package/dist/upload/FileDropzone.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -263,6 +263,16 @@ navegador: `isAndroidDevice({userAgent: headers.get('user-agent')})`. Sirve para
|
|
|
263
263
|
const theme = isAndroidDevice() ? createToolkitTheme({look: THEME_LOOK.minimal}) : createToolkitTheme({glass: true});
|
|
264
264
|
```
|
|
265
265
|
|
|
266
|
+
Los campos de captura (con vidrio, con el minimalista y dentro de `FormSection`) traen el gris de relleno de Apple. Para que
|
|
267
|
+
se vean como los de su sistema: `fields`, por modo, con el relleno (`fill`), el relleno con el cursor encima (`hoverFill`),
|
|
268
|
+
la orilla (`border`) y la orilla con el cursor encima (`hoverBorder`); y sus esquinas (`radius`). Lo que no se pase se queda
|
|
269
|
+
como lo trae el estilo (`FIELD_TONES`). Van en la paleta de cada modo (`palette.field`): cambian solos con el modo y también
|
|
270
|
+
se pueden escribir en `colorSchemes`.
|
|
271
|
+
|
|
272
|
+
```js
|
|
273
|
+
createToolkitTheme({glass: true, fields: {radius: 8, light: {fill: '#FFFFFF', hoverFill: '#FFFFFF', border: '#C4CDD5'}}});
|
|
274
|
+
```
|
|
275
|
+
|
|
266
276
|
El minimalista separa las superficies por su tono con los grises de Apple. Para pintarlo con los colores de la marca:
|
|
267
277
|
`minimalTones`, por modo, con el fondo de la página (`default`), las tarjetas (`paper`), el relleno de campos, grupos y
|
|
268
278
|
botones sin color (`fill`) y lo que flota, como la barra del teléfono (`floating`). Lo que no se pase se queda con el gris
|
|
@@ -280,6 +290,145 @@ Para lo que el proyecto quiera hacer flotar (los botones encima de un mapa, una
|
|
|
280
290
|
de vidrio si el tema lo trae y una tarjeta con sombra si no. Para algo propio: `sx={(theme) => glassStylesOf(theme)}` e
|
|
281
291
|
`isGlassTheme(theme)`. Cada ajuste vive en su archivo (`src/theme/components/MuiButton.js`…).
|
|
282
292
|
|
|
293
|
+
Todas las piezas de Calcita se cambian desde el tema del proyecto igual que las de MUI: con su nombre en `components`,
|
|
294
|
+
`styleOverrides` para cada parte y `defaultProps`. El orden, de abajo hacia arriba: el estilo de Calcita, encima el del
|
|
295
|
+
tema del proyecto y al final el `sx` que pase la pantalla. Los números se leen como en MUI (`borderRadius: 4` son 4 px).
|
|
296
|
+
Sirve con `createToolkitTheme` y con cualquier tema de MUI (el que ya tenía un sistema, tal cual): así un sistema puede
|
|
297
|
+
dejar Calcita con su propia cara, parte por parte.
|
|
298
|
+
|
|
299
|
+
<details>
|
|
300
|
+
<summary>Las piezas, con su nombre en el tema y sus partes</summary>
|
|
301
|
+
|
|
302
|
+
| Nombre en el tema | Partes |
|
|
303
|
+
| --- | --- |
|
|
304
|
+
| `CalcitaAccountMenu` | `button`, `avatar`, `header`, `name`, `settings` |
|
|
305
|
+
| `CalcitaAccountSecurity` | `title`, `form` |
|
|
306
|
+
| `CalcitaActionsMenu` | `item`, `itemIcon` |
|
|
307
|
+
| `CalcitaActivityLog` | `itemIcon` |
|
|
308
|
+
| `CalcitaAppearanceSettings` | `selectSection`, `section`, `sectionLabel`, `option`, `divider` |
|
|
309
|
+
| `CalcitaAppLayout` | `skipLink`, `brand`, `brandLogo`, `brandText`, `brandName`, `brandCaption`, `titleArea`, `phoneTitle`, `desktopTitle`, `railBrand`, `railLogo`, `collapseButton`, `root`, `scrollEdge`, `bar`, `toolbar`, `menuButton`, `spacer`, `tools`, `progress`, `body`, `drawer`, `main`, `phoneSlot`, `content`, `phoneDrawer` |
|
|
310
|
+
| `CalcitaAuditTrailDialog` | `description` |
|
|
311
|
+
| `CalcitaAuthLayout` | `root`, `tools`, `body`, `brand`, `logo`, `brandName`, `card`, `description`, `content`, `footer` |
|
|
312
|
+
| `CalcitaBarActions` | `group` |
|
|
313
|
+
| `CalcitaBarCapsule` | `root` |
|
|
314
|
+
| `CalcitaBarList` | `row`, `chart` |
|
|
315
|
+
| `CalcitaBarSearch` | `field` |
|
|
316
|
+
| `CalcitaCalendarHeatmap` | `header`, `toggle`, `tableArea`, `dateCell`, `valueCell`, `descriptionCell`, `gridArea`, `grid`, `monthLabel`, `week`, `dayLabel`, `cell`, `legend`, `legendLess`, `legendCell`, `legendMore` |
|
|
317
|
+
| `CalcitaChart` | `tableArea`, `legend`, `legendItem`, `legendLine`, `legendSwatch`, `reference`, `referenceLine` |
|
|
318
|
+
| `CalcitaChartTooltip` | `root` |
|
|
319
|
+
| `CalcitaCollapsibleSection` | `root`, `accordion`, `summary`, `titleArea`, `collapsedTitle`, `expandedTitle`, `details` |
|
|
320
|
+
| `CalcitaColorInput` | `swatch`, `nativeInput` |
|
|
321
|
+
| `CalcitaColorSchemeToggle` | `button` |
|
|
322
|
+
| `CalcitaColumnChart` | `chart` |
|
|
323
|
+
| `CalcitaConfirmDialog` | `problem`, `actions` |
|
|
324
|
+
| `CalcitaContentDialog` | `header`, `title`, `closeButton`, `body` |
|
|
325
|
+
| `CalcitaDateRangeFilter` | `chip`, `panel`, `actions` |
|
|
326
|
+
| `CalcitaDefinitionList` | `root`, `entry`, `label`, `value` |
|
|
327
|
+
| `CalcitaDemoTotpCode` | `root`, `code` |
|
|
328
|
+
| `CalcitaDetailHeader` | `root`, `titleArea`, `title`, `badges`, `actions` |
|
|
329
|
+
| `CalcitaDownloadManager` | `doneIcon`, `failedIcon`, `canceledIcon`, `cancelButton`, `progress`, `cancelIcon`, `item`, `itemText`, `itemStatus`, `itemActions`, `panel`, `header`, `title`, `list` |
|
|
330
|
+
| `CalcitaDownloadMenu` | `button` |
|
|
331
|
+
| `CalcitaEmptyState` | `root`, `icon` |
|
|
332
|
+
| `CalcitaErrorPage` | `root`, `actions` |
|
|
333
|
+
| `CalcitaEventCalendar` | `toolbar`, `navigation`, `title`, `calendar` |
|
|
334
|
+
| `CalcitaEventDetails` | `row`, `rowContent`, `titleRow`, `toneDot`, `linkRow`, `link`, `guestsTitle`, `guest`, `guestAvatar`, `guestName`, `notes`, `actions` |
|
|
335
|
+
| `CalcitaFileDropzone` | `root`, `fileArea`, `fileChip`, `hint`, `actions`, `limits`, `extra` |
|
|
336
|
+
| `CalcitaFilterChips` | `root`, `header`, `clearButton` |
|
|
337
|
+
| `CalcitaFontSizeToggle` | `button` |
|
|
338
|
+
| `CalcitaFormProblemAlert` | `root` |
|
|
339
|
+
| `CalcitaFormRow` | `root`, `label`, `control` |
|
|
340
|
+
| `CalcitaFormSection` | `root`, `title`, `card`, `footer` |
|
|
341
|
+
| `CalcitaFullPageLoader` | `root` |
|
|
342
|
+
| `CalcitaGlassPanel` | `root` |
|
|
343
|
+
| `CalcitaGoToPage` | `root`, `field` |
|
|
344
|
+
| `CalcitaGroupedTimeline` | `group`, `groupHeader`, `groupButton`, `groupTitle`, `expandIcon`, `timeline`, `opposite`, `connector`, `content`, `entryTitle` |
|
|
345
|
+
| `CalcitaHeaderFilter` | `button`, `badge`, `panel` |
|
|
346
|
+
| `CalcitaHeaderTools` | `divider`, `root` |
|
|
347
|
+
| `CalcitaInboxLayout` | `labelDot`, `folder`, `folderIcon`, `folderCount`, `root`, `folders`, `foldersHeader`, `labelsTitle`, `listPane`, `phoneTabs`, `phoneTabBadge`, `listHeader`, `list`, `detail`, `backButton` |
|
|
348
|
+
| `CalcitaInstallAppSetting` | `root` |
|
|
349
|
+
| `CalcitaInstallInstructions` | `steps` |
|
|
350
|
+
| `CalcitaInstallPromptBanner` | `root`, `alert` |
|
|
351
|
+
| `CalcitaKanbanBoard` | `completeButton`, `tags`, `titleRow`, `doneIcon`, `cardTitle`, `meta`, `due`, `dueIcon`, `dueText`, `checklist`, `checklistIcon`, `comments`, `commentsIcon`, `attachments`, `attachmentsIcon`, `assignees`, `root`, `collapsedColumn`, `collapsedTitle`, `hidden`, `column`, `columnHeader`, `columnTitle`, `quickAdd`, `dropZone`, `card`, `cardActions`, `cardContent`, `empty` |
|
|
352
|
+
| `CalcitaLanguageToggle` | `button` |
|
|
353
|
+
| `CalcitaLineChart` | `chart` |
|
|
354
|
+
| `CalcitaMapView` | `popupText`, `root` |
|
|
355
|
+
| `CalcitaMessageList` | `empty`, `selectedAvatar`, `item`, `actions`, `starButton`, `itemButton`, `avatarSlot`, `avatarButton`, `avatar`, `body`, `text`, `topRow`, `unreadDot`, `sender`, `threadCount`, `date`, `subject`, `labels` |
|
|
356
|
+
| `CalcitaMessageView` | `header`, `headerText`, `recipients`, `body`, `empty`, `labels`, `attachments`, `divider`, `collapsed`, `collapsedAvatar`, `collapsedText`, `collapsedSender`, `collapsedDate` |
|
|
357
|
+
| `CalcitaMetricCard` | `root`, `action`, `header`, `icon`, `label`, `value`, `caption`, `extra`, `trend` |
|
|
358
|
+
| `CalcitaMobileTabBar` | `tab`, `tabIconPlaceholder`, `tabLabel`, `root`, `bar`, `minimized`, `account`, `sheetHeader` |
|
|
359
|
+
| `CalcitaModalWaiting` | `root`, `title`, `body`, `text` |
|
|
360
|
+
| `CalcitaMultiSelectFilter` | `list`, `option` |
|
|
361
|
+
| `CalcitaNewBuildNotice` | `floating`, `icon`, `message`, `reloadButton`, `banner` |
|
|
362
|
+
| `CalcitaPageBreadcrumbs` | `root`, `link`, `current` |
|
|
363
|
+
| `CalcitaPageHeader` | `root`, `subtitle`, `action` |
|
|
364
|
+
| `CalcitaPageHeading` | `root`, `breadcrumbs`, `titleRow`, `title`, `actions`, `description` |
|
|
365
|
+
| `CalcitaPasswordChecklist` | `title`, `list`, `item`, `hidden` |
|
|
366
|
+
| `CalcitaPeriodRangeSelector` | `field`, `select`, `root` |
|
|
367
|
+
| `CalcitaPermissionMatrix` | `permission`, `checkbox`, `group`, `groupHeader`, `groupTitle`, `grid` |
|
|
368
|
+
| `CalcitaPondDropzone` | `root`, `summary`, `limits`, `actions`, `extra` |
|
|
369
|
+
| `CalcitaProfileHeader` | `root`, `cover`, `body`, `avatar`, `text`, `name`, `chips`, `actions` |
|
|
370
|
+
| `CalcitaProfileScreen` | `sectionTitle`, `form`, `preferences` |
|
|
371
|
+
| `CalcitaQuickFilters` | `root`, `caption`, `chip`, `chipLabel`, `chipCount` |
|
|
372
|
+
| `CalcitaRecoveryCodesDialog` | `codes`, `actions` |
|
|
373
|
+
| `CalcitaScrollableRow` | `root` |
|
|
374
|
+
| `CalcitaSecondStepForm` | `actions` |
|
|
375
|
+
| `CalcitaSectionCard` | `root`, `header`, `title` |
|
|
376
|
+
| `CalcitaSegmentedControl` | `root` |
|
|
377
|
+
| `CalcitaSelectInput` | `option`, `optionText` |
|
|
378
|
+
| `CalcitaSelectionActions` | `bar`, `count`, `clear`, `phoneCount`, `phoneActions` |
|
|
379
|
+
| `CalcitaServerTable` | `toolbar`, `summary`, `customHeader`, `count`, `countRow`, `selectionNotice`, `error`, `card`, `grid`, `pagination` |
|
|
380
|
+
| `CalcitaSessionsCard` | `item`, `itemIcon`, `itemHeader`, `actions` |
|
|
381
|
+
| `CalcitaSettingsMenu` | `divider` |
|
|
382
|
+
| `CalcitaSideMenu` | `scrollArrow`, `root`, `brand`, `brandLogo`, `brandText`, `brandName`, `brandCaption`, `railTop`, `listArea`, `list`, `section`, `sectionTitle`, `sectionTitleText`, `footer`, `railBottom` |
|
|
383
|
+
| `CalcitaSideMenuEntry` | `button`, `icon`, `iconPlaceholder`, `text`, `badge`, `expand` |
|
|
384
|
+
| `CalcitaSignInForm` | `footer` |
|
|
385
|
+
| `CalcitaSignInScreen` | `alert` |
|
|
386
|
+
| `CalcitaSortableFilterHeader` | `title`, `root`, `sortButton`, `sortIndicator`, `clearButton` |
|
|
387
|
+
| `CalcitaStatusChip` | `root`, `dot`, `label`, `chip` |
|
|
388
|
+
| `CalcitaSubmenuActionsMenu` | `badge` |
|
|
389
|
+
| `CalcitaTabBarEditor` | `root`, `header`, `title`, `list`, `itemIcon`, `footer` |
|
|
390
|
+
| `CalcitaTableToggle` | `root`, `button` |
|
|
391
|
+
| `CalcitaTag` | `root` |
|
|
392
|
+
| `CalcitaTextInput` | `field` |
|
|
393
|
+
| `CalcitaTopMenu` | `link`, `root` |
|
|
394
|
+
| `CalcitaTwoStepVerification` | `qr`, `secret`, `secretCode`, `header`, `headerTitle`, `headerText`, `menuIcon` |
|
|
395
|
+
| `CalcitaWizardLayout` | `stepper`, `phoneSteps`, `actions` |
|
|
396
|
+
| `CalcitaWordmark` | `root` |
|
|
397
|
+
|
|
398
|
+
</details>
|
|
399
|
+
|
|
400
|
+
Para cambiar de un jalón los valores globales, sin tocar pieza por pieza, Calcita los lee de variables CSS. Cada una trae su
|
|
401
|
+
valor de siempre de respaldo: sin ella se ve igual.
|
|
402
|
+
|
|
403
|
+
| Variable | Qué cambia | De fábrica |
|
|
404
|
+
| --- | --- | --- |
|
|
405
|
+
| `--calcita-panel-radius` | las esquinas de lo que flota grande y las tarjetas grandes (menú lateral, diálogos, la sección de un formulario) | 20px (16px en el minimalista) |
|
|
406
|
+
| `--calcita-menu-radius` | las esquinas de menús, listas desplegables, globos y avisos | 12px |
|
|
407
|
+
| `--calcita-field-radius` | las esquinas de los campos de captura | 12px (10px en el minimalista) |
|
|
408
|
+
| `--calcita-glass-blur` | el desenfoque del vidrio | 20px |
|
|
409
|
+
| `--calcita-glass-saturate` | cuánto aviva el vidrio los colores de atrás | 180% |
|
|
410
|
+
|
|
411
|
+
```css
|
|
412
|
+
:root { --calcita-panel-radius: 6px; --calcita-glass-blur: 12px; } /* también en la página de un sistema que ya existe */
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
```js
|
|
416
|
+
createToolkitTheme({cssTokens: {panelRadius: 6, glassBlur: 12}}); // las mismas, declaradas por el tema (un número va en px)
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
Los colores de los campos son variables de MUI (`--mui-palette-field-fill`, `--mui-palette-field-border`…; ver `fields`).
|
|
420
|
+
Lo que se pinta flotando al final de la página (menús, ventanas) toma las de `:root`, no las de un contenedor.
|
|
421
|
+
|
|
422
|
+
```js
|
|
423
|
+
createTheme({
|
|
424
|
+
components: {
|
|
425
|
+
CalcitaStatusChip: {defaultProps: {variant: 'chip'}},
|
|
426
|
+
CalcitaFormSection: {styleOverrides: {card: {borderRadius: 4}}},
|
|
427
|
+
CalcitaSegmentedControl: {styleOverrides: {root: {'& .MuiToggleButton-root': {textTransform: 'uppercase'}}}},
|
|
428
|
+
},
|
|
429
|
+
});
|
|
430
|
+
```
|
|
431
|
+
|
|
283
432
|
## El marco de la app, el menú y los permisos
|
|
284
433
|
|
|
285
434
|
`AppLayout` es el marco de las plantillas de MUI: la barra a todo lo ancho, con el logo y el nombre de la app; debajo,
|
|
@@ -3,21 +3,25 @@ import { jsxs, jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import Typography from "@mui/material/Typography";
|
|
4
4
|
import AuditTrailTable from "./AuditTrailTable.js";
|
|
5
5
|
import ContentDialog from "../ui/layout/ContentDialog.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
6
|
+
import { piecePart, usePieceProps } from "../theme/themePieces.js";
|
|
7
|
+
const THEME_NAME = "CalcitaAuditTrailDialog";
|
|
8
|
+
const AuditDescription = piecePart(THEME_NAME, "Description", Typography);
|
|
9
|
+
function AuditTrailDialog(props) {
|
|
10
|
+
const {
|
|
11
|
+
open,
|
|
12
|
+
onClose,
|
|
13
|
+
title,
|
|
14
|
+
subtitle,
|
|
15
|
+
subjectKey,
|
|
16
|
+
fetchPage,
|
|
17
|
+
eventDictionary,
|
|
18
|
+
resultDictionary,
|
|
19
|
+
extraColumns = [],
|
|
20
|
+
header = null,
|
|
21
|
+
eventSuffixOf = null
|
|
22
|
+
} = usePieceProps(props, THEME_NAME);
|
|
19
23
|
return /* @__PURE__ */ jsxs(ContentDialog, { open, onClose, title, children: [
|
|
20
|
-
subtitle && /* @__PURE__ */ jsx(
|
|
24
|
+
subtitle && /* @__PURE__ */ jsx(AuditDescription, { variant: "body2", color: "text.secondary", ownSx: { mb: 2 }, children: subtitle }),
|
|
21
25
|
header,
|
|
22
26
|
/* @__PURE__ */ jsx(
|
|
23
27
|
AuditTrailTable,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuditTrailDialog.js","sources":["../../src/DataTable/AuditTrailDialog.jsx"],"sourcesContent":["// Diálogo de auditoría de un renglón: su historia de eventos, paginada y filtrada EN EL SERVIDOR (AuditTrailTable).\n//\n// Sirve para el historial de cualquier registro (un pedido, una cuenta).\n// Solo abre una vista: no ejecuta nada y por eso no lleva confirmación.\n//\n// Se abre como diálogo de contenido (ContentDialog): sube desde abajo y ocupa la pantalla debajo de la barra superior. Una\n// tabla con su historia se lee mejor a todo lo ancho que en un recuadro al centro, también en el teléfono.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Typography from '@mui/material/Typography';\n\nimport AuditTrailTable from '@/DataTable/AuditTrailTable.jsx';\nimport ContentDialog from '@/ui/layout/ContentDialog.jsx';\n\n/**\n * @param {object} props\n * @param {boolean} props.open\n * @param {() => void} props.onClose\n * @param {string} props.title ya traducido («Historial de Q3 · ago 2026»)\n * @param {import('react').ReactNode} [props.subtitle]\n * @param {string} props.subjectKey\n * @param {(tableRequest: object, signal: AbortSignal) => Promise<{rows: Array, total: number, facets?: object}>} props.fetchPage\n * @param {Record<string, object>} props.eventDictionary\n * @param {Record<string, object>} [props.resultDictionary]\n * @param {Array<object>} [props.extraColumns]\n * @param {import('react').ReactNode} [props.header] va entre el subtítulo y la tabla (p. ej. pestañas que cambian lo que se\n * consulta)\n * @param {(row: any) => string|null} [props.eventSuffixOf] complemento del evento de un renglón (AuditTrailTable)\n */\nexport default function AuditTrailDialog({\n open, onClose, title, subtitle, subjectKey, fetchPage, eventDictionary, resultDictionary, extraColumns = [], header = null, eventSuffixOf = null,\n})
|
|
1
|
+
{"version":3,"file":"AuditTrailDialog.js","sources":["../../src/DataTable/AuditTrailDialog.jsx"],"sourcesContent":["// Diálogo de auditoría de un renglón: su historia de eventos, paginada y filtrada EN EL SERVIDOR (AuditTrailTable).\n//\n// Sirve para el historial de cualquier registro (un pedido, una cuenta).\n// Solo abre una vista: no ejecuta nada y por eso no lleva confirmación.\n//\n// Se abre como diálogo de contenido (ContentDialog): sube desde abajo y ocupa la pantalla debajo de la barra superior. Una\n// tabla con su historia se lee mejor a todo lo ancho que en un recuadro al centro, también en el teléfono.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaAuditTrailDialog con defaultProps y\n// styleOverrides de sus partes: description.\n//\n// Genérico del paquete: function (regla de la casa).\nimport Typography from '@mui/material/Typography';\n\nimport AuditTrailTable from '@/DataTable/AuditTrailTable.jsx';\nimport ContentDialog from '@/ui/layout/ContentDialog.jsx';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaAuditTrailDialog)\nconst THEME_NAME = 'CalcitaAuditTrailDialog';\nconst AuditDescription = piecePart(THEME_NAME, 'Description', Typography);\n\n/**\n * @param {object} props\n * @param {boolean} props.open\n * @param {() => void} props.onClose\n * @param {string} props.title ya traducido («Historial de Q3 · ago 2026»)\n * @param {import('react').ReactNode} [props.subtitle]\n * @param {string} props.subjectKey\n * @param {(tableRequest: object, signal: AbortSignal) => Promise<{rows: Array, total: number, facets?: object}>} props.fetchPage\n * @param {Record<string, object>} props.eventDictionary\n * @param {Record<string, object>} [props.resultDictionary]\n * @param {Array<object>} [props.extraColumns]\n * @param {import('react').ReactNode} [props.header] va entre el subtítulo y la tabla (p. ej. pestañas que cambian lo que se\n * consulta)\n * @param {(row: any) => string|null} [props.eventSuffixOf] complemento del evento de un renglón (AuditTrailTable)\n */\nexport default function AuditTrailDialog(props) {\n // lo que el proyecto puso en su tema (components.CalcitaAuditTrailDialog.defaultProps) y encima lo que llega aquí\n const {\n open, onClose, title, subtitle, subjectKey, fetchPage, eventDictionary, resultDictionary, extraColumns = [], header = null, eventSuffixOf = null,\n} = usePieceProps(props, THEME_NAME);\n return (\n <ContentDialog open={open} onClose={onClose} title={title}>\n {subtitle && (\n <AuditDescription variant=\"body2\" color=\"text.secondary\" ownSx={{mb: 2}}>{subtitle}</AuditDescription>\n )}\n {header}\n <AuditTrailTable\n subjectKey={open ? subjectKey : ''}\n fetchPage={fetchPage}\n eventDictionary={eventDictionary}\n resultDictionary={resultDictionary}\n extraColumns={extraColumns}\n eventSuffixOf={eventSuffixOf}\n ariaLabel={title}\n maxGridHeight={null}\n />\n </ContentDialog>\n );\n}\n"],"names":[],"mappings":";;;;;;AAmBA,MAAM,aAAa;AACnB,MAAM,mBAAmB,UAAU,YAAY,eAAe,UAAU;AAiBxE,SAAwB,iBAAiB,OAAO;AAE5C,QAAM;AAAA,IACN;AAAA,IAAM;AAAA,IAAS;AAAA,IAAO;AAAA,IAAU;AAAA,IAAY;AAAA,IAAW;AAAA,IAAiB;AAAA,IAAkB,eAAe,CAAA;AAAA,IAAI,SAAS;AAAA,IAAM,gBAAgB;AAAA,EAAA,IAC5I,cAAc,OAAO,UAAU;AAC/B,SACI,qBAAC,eAAA,EAAc,MAAY,SAAkB,OACxC,UAAA;AAAA,IAAA,YACG,oBAAC,kBAAA,EAAiB,SAAQ,SAAQ,OAAM,kBAAiB,OAAO,EAAC,IAAI,EAAA,GAAK,UAAA,SAAA,CAAS;AAAA,IAEtF;AAAA,IACD;AAAA,MAAC;AAAA,MAAA;AAAA,QACG,YAAY,OAAO,aAAa;AAAA,QAChC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QACX,eAAe;AAAA,MAAA;AAAA,IAAA;AAAA,EACnB,GACJ;AAER;"}
|
|
@@ -11,29 +11,35 @@ import Stack from "@mui/material/Stack";
|
|
|
11
11
|
import Tooltip from "@mui/material/Tooltip";
|
|
12
12
|
import FilterAltIcon from "@mui/icons-material/FilterAlt";
|
|
13
13
|
import FilterAltOutlinedIcon from "@mui/icons-material/FilterAltOutlined";
|
|
14
|
-
|
|
14
|
+
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
15
|
+
const THEME_NAME = "CalcitaHeaderFilter";
|
|
16
|
+
const FilterButton = piecePart(THEME_NAME, "Button", IconButton);
|
|
17
|
+
const FilterBadge = piecePart(THEME_NAME, "Badge", Badge);
|
|
18
|
+
const FilterPanel = piecePart(THEME_NAME, "Panel", Box);
|
|
19
|
+
function HeaderFilterPopover(props) {
|
|
20
|
+
const { activeCount = 0, onClear, children } = usePieceProps(props, THEME_NAME);
|
|
15
21
|
const { t } = useToolkitTranslation("table");
|
|
16
22
|
const [anchorElement, setAnchorElement] = useState(null);
|
|
17
23
|
const isActive = activeCount > 0;
|
|
18
24
|
const tooltip = isActive ? t("columnFilter.activeTooltip", { count: activeCount }) : t("columnFilter.tooltip");
|
|
19
25
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
20
26
|
/* @__PURE__ */ jsx(Tooltip, { title: tooltip, children: /* @__PURE__ */ jsx(
|
|
21
|
-
|
|
27
|
+
FilterButton,
|
|
22
28
|
{
|
|
23
29
|
size: "small",
|
|
24
30
|
"aria-label": tooltip,
|
|
25
|
-
|
|
31
|
+
ownSx: { color: isActive ? "primary.main" : "action.active", opacity: isActive ? 1 : 0.45, overflow: "visible" },
|
|
26
32
|
onClick: (event) => {
|
|
27
33
|
event.stopPropagation();
|
|
28
34
|
setAnchorElement(event.currentTarget);
|
|
29
35
|
},
|
|
30
36
|
children: isActive ? /* @__PURE__ */ jsx(
|
|
31
|
-
|
|
37
|
+
FilterBadge,
|
|
32
38
|
{
|
|
33
39
|
badgeContent: activeCount,
|
|
34
40
|
color: "primary",
|
|
35
41
|
overlap: "circular",
|
|
36
|
-
|
|
42
|
+
ownSx: { "& .MuiBadge-badge": { fontSize: 10, fontWeight: 700, minWidth: 16, height: 16 } },
|
|
37
43
|
children: /* @__PURE__ */ jsx(FilterAltIcon, { fontSize: "inherit" })
|
|
38
44
|
}
|
|
39
45
|
) : /* @__PURE__ */ jsx(FilterAltOutlinedIcon, { fontSize: "inherit" })
|
|
@@ -46,7 +52,7 @@ function HeaderFilterPopover({ activeCount = 0, onClear, children }) {
|
|
|
46
52
|
anchorEl: anchorElement,
|
|
47
53
|
onClose: () => setAnchorElement(null),
|
|
48
54
|
anchorOrigin: { vertical: "bottom", horizontal: "left" },
|
|
49
|
-
children: /* @__PURE__ */ jsx(
|
|
55
|
+
children: /* @__PURE__ */ jsx(FilterPanel, { ownSx: { p: 2, minWidth: 280 }, children: /* @__PURE__ */ jsxs(Stack, { spacing: 1, children: [
|
|
50
56
|
children,
|
|
51
57
|
/* @__PURE__ */ jsx(
|
|
52
58
|
Button,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeaderFilterPopover.js","sources":["../../../src/DataTable/ColumnFilters/HeaderFilterPopover.jsx"],"sourcesContent":["// El icono de filtro del encabezado, con su globo.\n//\n// El badge trae el NÚMERO de valores activos en esa columna, no un punto: así se sabe sin abrir nada si se filtró por\n// uno o por seis.\n//\n// OJO: stopPropagation en el clic no es adorno. El título del encabezado ordena, y sin eso abrir el filtro también\n// cambiaría el orden.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Badge from '@mui/material/Badge';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport IconButton from '@mui/material/IconButton';\nimport Popover from '@mui/material/Popover';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport FilterAltIcon from '@mui/icons-material/FilterAlt';\nimport FilterAltOutlinedIcon from '@mui/icons-material/FilterAltOutlined';\n\n/**\n * @param {{activeCount?: number, onClear: () => void, children: import('react').ReactNode}} props children = el filtro\n */\nexport default function HeaderFilterPopover({activeCount = 0, onClear, children})
|
|
1
|
+
{"version":3,"file":"HeaderFilterPopover.js","sources":["../../../src/DataTable/ColumnFilters/HeaderFilterPopover.jsx"],"sourcesContent":["// El icono de filtro del encabezado, con su globo.\n//\n// El badge trae el NÚMERO de valores activos en esa columna, no un punto: así se sabe sin abrir nada si se filtró por\n// uno o por seis.\n//\n// OJO: stopPropagation en el clic no es adorno. El título del encabezado ordena, y sin eso abrir el filtro también\n// cambiaría el orden.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaHeaderFilter con defaultProps y\n// styleOverrides de sus partes: button, badge, panel.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Badge from '@mui/material/Badge';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport IconButton from '@mui/material/IconButton';\nimport Popover from '@mui/material/Popover';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport FilterAltIcon from '@mui/icons-material/FilterAlt';\nimport FilterAltOutlinedIcon from '@mui/icons-material/FilterAltOutlined';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaHeaderFilter)\nconst THEME_NAME = 'CalcitaHeaderFilter';\nconst FilterButton = piecePart(THEME_NAME, 'Button', IconButton);\nconst FilterBadge = piecePart(THEME_NAME, 'Badge', Badge);\nconst FilterPanel = piecePart(THEME_NAME, 'Panel', Box);\n\n/**\n * @param {{activeCount?: number, onClear: () => void, children: import('react').ReactNode}} props children = el filtro\n */\nexport default function HeaderFilterPopover(props) {\n // lo que el proyecto puso en su tema (components.CalcitaHeaderFilter.defaultProps) y encima lo que llega aquí\n const {activeCount = 0, onClear, children} = usePieceProps(props, THEME_NAME);\n const {t} = useToolkitTranslation('table');\n const [anchorElement, setAnchorElement] = useState(null);\n const isActive = activeCount > 0;\n const tooltip = isActive ? t('columnFilter.activeTooltip', {count: activeCount}) : t('columnFilter.tooltip');\n\n return (\n <>\n <Tooltip title={tooltip}>\n <FilterButton size=\"small\" aria-label={tooltip}\n ownSx={{color: isActive ? 'primary.main' : 'action.active', opacity: isActive ? 1 : 0.45, overflow: 'visible'}}\n onClick={(event) => {\n event.stopPropagation();\n setAnchorElement(event.currentTarget);\n }}>\n {/* sin filtros NO se monta el Badge: MUI lo esconde con scale(0) y deja un artefacto en la esquina */}\n {isActive ? (\n <FilterBadge badgeContent={activeCount} color=\"primary\" overlap=\"circular\"\n ownSx={{'& .MuiBadge-badge': {fontSize: 10, fontWeight: 700, minWidth: 16, height: 16}}}>\n <FilterAltIcon fontSize=\"inherit\" />\n </FilterBadge>\n ) : <FilterAltOutlinedIcon fontSize=\"inherit\" />}\n </FilterButton>\n </Tooltip>\n\n <Popover open={Boolean(anchorElement)} anchorEl={anchorElement} onClose={() => setAnchorElement(null)}\n anchorOrigin={{vertical: 'bottom', horizontal: 'left'}}>\n <FilterPanel ownSx={{p: 2, minWidth: 280}}>\n <Stack spacing={1}>\n {children}\n <Button size=\"small\" disabled={!isActive}\n onClick={() => {\n onClear();\n setAnchorElement(null);\n }}>\n {t('columnFilter.clear')}\n </Button>\n </Stack>\n </FilterPanel>\n </Popover>\n </>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;AA0BA,MAAM,aAAa;AACnB,MAAM,eAAe,UAAU,YAAY,UAAU,UAAU;AAC/D,MAAM,cAAc,UAAU,YAAY,SAAS,KAAK;AACxD,MAAM,cAAc,UAAU,YAAY,SAAS,GAAG;AAKtD,SAAwB,oBAAoB,OAAO;AAE/C,QAAM,EAAC,cAAc,GAAG,SAAS,aAAY,cAAc,OAAO,UAAU;AAC5E,QAAM,EAAC,EAAA,IAAK,sBAAsB,OAAO;AACzC,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,IAAI;AACvD,QAAM,WAAW,cAAc;AAC/B,QAAM,UAAU,WAAW,EAAE,8BAA8B,EAAC,OAAO,YAAA,CAAY,IAAI,EAAE,sBAAsB;AAE3G,SACI,qBAAA,UAAA,EACI,UAAA;AAAA,IAAA,oBAAC,SAAA,EAAQ,OAAO,SACZ,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QAAa,MAAK;AAAA,QAAQ,cAAY;AAAA,QAC3B,OAAO,EAAC,OAAO,WAAW,iBAAiB,iBAAiB,SAAS,WAAW,IAAI,MAAM,UAAU,UAAA;AAAA,QACpG,SAAS,CAAC,UAAU;AAChB,gBAAM,gBAAA;AACN,2BAAiB,MAAM,aAAa;AAAA,QACxC;AAAA,QAEP,UAAA,WACG;AAAA,UAAC;AAAA,UAAA;AAAA,YAAY,cAAc;AAAA,YAAa,OAAM;AAAA,YAAU,SAAQ;AAAA,YACzD,OAAO,EAAC,qBAAqB,EAAC,UAAU,IAAI,YAAY,KAAK,UAAU,IAAI,QAAQ,GAAA,EAAE;AAAA,YACxF,UAAA,oBAAC,eAAA,EAAc,UAAS,UAAA,CAAU;AAAA,UAAA;AAAA,QAAA,IAEtC,oBAAC,uBAAA,EAAsB,UAAS,UAAA,CAAU;AAAA,MAAA;AAAA,IAAA,GAEtD;AAAA,IAEA;AAAA,MAAC;AAAA,MAAA;AAAA,QAAQ,MAAM,QAAQ,aAAa;AAAA,QAAG,UAAU;AAAA,QAAe,SAAS,MAAM,iBAAiB,IAAI;AAAA,QAC3F,cAAc,EAAC,UAAU,UAAU,YAAY,OAAA;AAAA,QACpD,UAAA,oBAAC,aAAA,EAAY,OAAO,EAAC,GAAG,GAAG,UAAU,IAAA,GACjC,UAAA,qBAAC,OAAA,EAAM,SAAS,GACX,UAAA;AAAA,UAAA;AAAA,UACD;AAAA,YAAC;AAAA,YAAA;AAAA,cAAO,MAAK;AAAA,cAAQ,UAAU,CAAC;AAAA,cACxB,SAAS,MAAM;AACX,wBAAA;AACA,iCAAiB,IAAI;AAAA,cACzB;AAAA,cACH,YAAE,oBAAoB;AAAA,YAAA;AAAA,UAAA;AAAA,QAC3B,EAAA,CACJ,EAAA,CACJ;AAAA,MAAA;AAAA,IAAA;AAAA,EACJ,GACJ;AAER;"}
|
|
@@ -8,8 +8,13 @@ import Stack from "@mui/material/Stack";
|
|
|
8
8
|
import TextField from "@mui/material/TextField";
|
|
9
9
|
import Typography from "@mui/material/Typography";
|
|
10
10
|
import { useFormatters } from "../../toolkit/useFormatters.js";
|
|
11
|
+
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
12
|
+
const THEME_NAME = "CalcitaMultiSelectFilter";
|
|
13
|
+
const MultiList = piecePart(THEME_NAME, "List", Stack);
|
|
14
|
+
const MultiOption = piecePart(THEME_NAME, "Option", Stack);
|
|
11
15
|
const SEARCHABLE_FROM_OPTIONS = 8;
|
|
12
|
-
function MultiSelectColumnFilter(
|
|
16
|
+
function MultiSelectColumnFilter(props) {
|
|
17
|
+
const { value = [], onChange, options = [], renderOption } = usePieceProps(props, THEME_NAME);
|
|
13
18
|
const { t } = useToolkitTranslation("table");
|
|
14
19
|
const { formatNumber } = useFormatters();
|
|
15
20
|
const [searchText, setSearchText] = useState("");
|
|
@@ -28,14 +33,14 @@ function MultiSelectColumnFilter({ value = [], onChange, options = [], renderOpt
|
|
|
28
33
|
onChange: (event) => setSearchText(event.target.value)
|
|
29
34
|
}
|
|
30
35
|
),
|
|
31
|
-
/* @__PURE__ */ jsxs(
|
|
36
|
+
/* @__PURE__ */ jsxs(MultiList, { ownSx: { maxHeight: 300, overflowY: "auto" }, children: [
|
|
32
37
|
options.length === 0 && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: t("options.empty") }),
|
|
33
38
|
options.length > 0 && visibleOptions.length === 0 && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: t("options.noMatch", { text: searchText }) }),
|
|
34
39
|
visibleOptions.map((option) => /* @__PURE__ */ jsx(
|
|
35
40
|
FormControlLabel,
|
|
36
41
|
{
|
|
37
42
|
control: /* @__PURE__ */ jsx(Checkbox, { size: "small", checked: value.includes(option.value), onChange: () => toggleOption(option.value) }),
|
|
38
|
-
label: /* @__PURE__ */ jsxs(
|
|
43
|
+
label: /* @__PURE__ */ jsxs(MultiOption, { direction: "row", spacing: 0.75, ownSx: { alignItems: "center" }, children: [
|
|
39
44
|
renderOption ? renderOption(option.value) : /* @__PURE__ */ jsx(Typography, { variant: "body2", children: option.value }),
|
|
40
45
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: formatNumber(option.total) })
|
|
41
46
|
] })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiSelectColumnFilter.js","sources":["../../../src/DataTable/ColumnFilters/MultiSelectColumnFilter.jsx"],"sourcesContent":["// Filtro de opciones de una columna.\n//\n// Dos cosas lo separan de un multi-select cualquiera:\n// - las opciones NO salen de las filas visibles: salen de las FACETAS que el servidor calcula sobre el resultado\n// COMPLETO (ofrecer solo lo que aparece en las primeras 25 filas convierte el filtro en adorno);\n// - cada opción trae su conteo, que es lo que deja decidir si vale la pena filtrar.\n//\n// Desde ocho opciones aparece una caja para buscar entre ellas.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Checkbox from '@mui/material/Checkbox';\nimport FormControlLabel from '@mui/material/FormControlLabel';\nimport Stack from '@mui/material/Stack';\nimport TextField from '@mui/material/TextField';\nimport Typography from '@mui/material/Typography';\n\nimport {useFormatters} from '@/toolkit/useFormatters.js';\n\nconst SEARCHABLE_FROM_OPTIONS = 8;\n\n/**\n * @param {object} props\n * @param {string[]} [props.value]\n * @param {(value: string[]) => void} props.onChange\n * @param {Array<{value: string, total: number}>} [props.options] faceta del servidor\n * @param {(value: string) => import('react').ReactNode} [props.renderOption] cómo se lee el valor (diccionario)\n */\nexport default function MultiSelectColumnFilter({value = [], onChange, options = [], renderOption})
|
|
1
|
+
{"version":3,"file":"MultiSelectColumnFilter.js","sources":["../../../src/DataTable/ColumnFilters/MultiSelectColumnFilter.jsx"],"sourcesContent":["// Filtro de opciones de una columna.\n//\n// Dos cosas lo separan de un multi-select cualquiera:\n// - las opciones NO salen de las filas visibles: salen de las FACETAS que el servidor calcula sobre el resultado\n// COMPLETO (ofrecer solo lo que aparece en las primeras 25 filas convierte el filtro en adorno);\n// - cada opción trae su conteo, que es lo que deja decidir si vale la pena filtrar.\n//\n// Desde ocho opciones aparece una caja para buscar entre ellas.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaMultiSelectFilter con defaultProps y\n// styleOverrides de sus partes: list, option.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Checkbox from '@mui/material/Checkbox';\nimport FormControlLabel from '@mui/material/FormControlLabel';\nimport Stack from '@mui/material/Stack';\nimport TextField from '@mui/material/TextField';\nimport Typography from '@mui/material/Typography';\n\nimport {useFormatters} from '@/toolkit/useFormatters.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaMultiSelectFilter)\nconst THEME_NAME = 'CalcitaMultiSelectFilter';\nconst MultiList = piecePart(THEME_NAME, 'List', Stack);\nconst MultiOption = piecePart(THEME_NAME, 'Option', Stack);\n\nconst SEARCHABLE_FROM_OPTIONS = 8;\n\n/**\n * @param {object} props\n * @param {string[]} [props.value]\n * @param {(value: string[]) => void} props.onChange\n * @param {Array<{value: string, total: number}>} [props.options] faceta del servidor\n * @param {(value: string) => import('react').ReactNode} [props.renderOption] cómo se lee el valor (diccionario)\n */\nexport default function MultiSelectColumnFilter(props) {\n // lo que el proyecto puso en su tema (components.CalcitaMultiSelectFilter.defaultProps) y encima lo que llega aquí\n const {value = [], onChange, options = [], renderOption} = usePieceProps(props, THEME_NAME);\n const {t} = useToolkitTranslation('table');\n const {formatNumber} = useFormatters();\n const [searchText, setSearchText] = useState('');\n\n const toggleOption = (optionValue) => onChange(value.includes(optionValue)\n ? value.filter((currentValue) => currentValue !== optionValue)\n : [...value, optionValue]);\n\n const isSearchable = options.length >= SEARCHABLE_FROM_OPTIONS;\n const visibleOptions = isSearchable && searchText\n ? options.filter((option) => String(option.value).toLowerCase().includes(searchText.toLowerCase()))\n : options;\n\n return (\n <Stack spacing={1}>\n {isSearchable && (\n <TextField size=\"small\" autoFocus fullWidth placeholder={t('options.searchPlaceholder')} value={searchText}\n onChange={(event) => setSearchText(event.target.value)} />\n )}\n <MultiList ownSx={{maxHeight: 300, overflowY: 'auto'}}>\n {options.length === 0 && (\n <Typography variant=\"caption\" color=\"text.secondary\">{t('options.empty')}</Typography>\n )}\n {options.length > 0 && visibleOptions.length === 0 && (\n <Typography variant=\"caption\" color=\"text.secondary\">{t('options.noMatch', {text: searchText})}</Typography>\n )}\n {visibleOptions.map((option) => (\n <FormControlLabel\n key={option.value}\n control={<Checkbox size=\"small\" checked={value.includes(option.value)} onChange={() => toggleOption(option.value)} />}\n label={(\n <MultiOption direction=\"row\" spacing={0.75} ownSx={{alignItems: 'center'}}>\n {renderOption ? renderOption(option.value) : <Typography variant=\"body2\">{option.value}</Typography>}\n <Typography variant=\"caption\" color=\"text.secondary\">{formatNumber(option.total)}</Typography>\n </MultiOption>\n )}\n />\n ))}\n </MultiList>\n </Stack>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;AAyBA,MAAM,aAAa;AACnB,MAAM,YAAY,UAAU,YAAY,QAAQ,KAAK;AACrD,MAAM,cAAc,UAAU,YAAY,UAAU,KAAK;AAEzD,MAAM,0BAA0B;AAShC,SAAwB,wBAAwB,OAAO;AAEnD,QAAM,EAAC,QAAQ,IAAI,UAAU,UAAU,IAAI,iBAAgB,cAAc,OAAO,UAAU;AAC1F,QAAM,EAAC,EAAA,IAAK,sBAAsB,OAAO;AACzC,QAAM,EAAC,aAAA,IAAgB,cAAA;AACvB,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,EAAE;AAE/C,QAAM,eAAe,CAAC,gBAAgB,SAAS,MAAM,SAAS,WAAW,IACnE,MAAM,OAAO,CAAC,iBAAiB,iBAAiB,WAAW,IAC3D,CAAC,GAAG,OAAO,WAAW,CAAC;AAE7B,QAAM,eAAe,QAAQ,UAAU;AACvC,QAAM,iBAAiB,gBAAgB,aACjC,QAAQ,OAAO,CAAC,WAAW,OAAO,OAAO,KAAK,EAAE,cAAc,SAAS,WAAW,YAAA,CAAa,CAAC,IAChG;AAEN,SACI,qBAAC,OAAA,EAAM,SAAS,GACX,UAAA;AAAA,IAAA,gBACG;AAAA,MAAC;AAAA,MAAA;AAAA,QAAU,MAAK;AAAA,QAAQ,WAAS;AAAA,QAAC,WAAS;AAAA,QAAC,aAAa,EAAE,2BAA2B;AAAA,QAAG,OAAO;AAAA,QACrF,UAAU,CAAC,UAAU,cAAc,MAAM,OAAO,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,IAEpE,qBAAC,aAAU,OAAO,EAAC,WAAW,KAAK,WAAW,UACzC,UAAA;AAAA,MAAA,QAAQ,WAAW,KAChB,oBAAC,YAAA,EAAW,SAAQ,WAAU,OAAM,kBAAkB,UAAA,EAAE,eAAe,EAAA,CAAE;AAAA,MAE5E,QAAQ,SAAS,KAAK,eAAe,WAAW,yBAC5C,YAAA,EAAW,SAAQ,WAAU,OAAM,kBAAkB,UAAA,EAAE,mBAAmB,EAAC,MAAM,WAAA,CAAW,GAAE;AAAA,MAElG,eAAe,IAAI,CAAC,WACjB;AAAA,QAAC;AAAA,QAAA;AAAA,UAEG,SAAS,oBAAC,UAAA,EAAS,MAAK,SAAQ,SAAS,MAAM,SAAS,OAAO,KAAK,GAAG,UAAU,MAAM,aAAa,OAAO,KAAK,GAAG;AAAA,UACnH,OACI,qBAAC,aAAA,EAAY,WAAU,OAAM,SAAS,MAAM,OAAO,EAAC,YAAY,SAAA,GAC3D,UAAA;AAAA,YAAA,eAAe,aAAa,OAAO,KAAK,wBAAK,YAAA,EAAW,SAAQ,SAAS,UAAA,OAAO,MAAA,CAAM;AAAA,YACvF,oBAAC,cAAW,SAAQ,WAAU,OAAM,kBAAkB,UAAA,aAAa,OAAO,KAAK,EAAA,CAAE;AAAA,UAAA,EAAA,CACrF;AAAA,QAAA;AAAA,QANC,OAAO;AAAA,MAAA,CASnB;AAAA,IAAA,EAAA,CACL;AAAA,EAAA,GACJ;AAER;"}
|
|
@@ -7,37 +7,45 @@ import Stack from "@mui/material/Stack";
|
|
|
7
7
|
import Tooltip from "@mui/material/Tooltip";
|
|
8
8
|
import Typography from "@mui/material/Typography";
|
|
9
9
|
import HeaderFilterPopover from "./HeaderFilterPopover.js";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
11
|
+
const THEME_NAME = "CalcitaSortableFilterHeader";
|
|
12
|
+
const SortableTitle = piecePart(THEME_NAME, "Title", Typography);
|
|
13
|
+
const SortableRoot = piecePart(THEME_NAME, "Root", Stack);
|
|
14
|
+
const SortableSortButton = piecePart(THEME_NAME, "SortButton", ButtonBase);
|
|
15
|
+
const SortableSortIndicator = piecePart(THEME_NAME, "SortIndicator", Box);
|
|
16
|
+
const SortableClearButton = piecePart(THEME_NAME, "ClearButton", ButtonBase);
|
|
17
|
+
function SortableFilterHeader(props) {
|
|
18
|
+
const {
|
|
19
|
+
label,
|
|
20
|
+
sortable = true,
|
|
21
|
+
sortEntry,
|
|
22
|
+
onSort,
|
|
23
|
+
onClearSort,
|
|
24
|
+
filterable = true,
|
|
25
|
+
activeCount,
|
|
26
|
+
onClear,
|
|
27
|
+
children
|
|
28
|
+
} = usePieceProps(props, THEME_NAME);
|
|
21
29
|
const { t } = useToolkitTranslation("table");
|
|
22
|
-
const title = /* @__PURE__ */ jsx(
|
|
23
|
-
return /* @__PURE__ */ jsxs(
|
|
24
|
-
sortable ? /* @__PURE__ */ jsx(Tooltip, { title: t("sort.tooltip"), children: /* @__PURE__ */ jsxs(
|
|
30
|
+
const title = /* @__PURE__ */ jsx(SortableTitle, { variant: "caption", ownSx: { fontWeight: 700, whiteSpace: "nowrap" }, children: label });
|
|
31
|
+
return /* @__PURE__ */ jsxs(SortableRoot, { direction: "row", spacing: 0.25, ownSx: { alignItems: "center" }, children: [
|
|
32
|
+
sortable ? /* @__PURE__ */ jsx(Tooltip, { title: t("sort.tooltip"), children: /* @__PURE__ */ jsxs(SortableSortButton, { onClick: onSort, ownSx: { gap: 0.25, borderRadius: 0.5 }, children: [
|
|
25
33
|
title,
|
|
26
34
|
sortEntry && /* @__PURE__ */ jsx(
|
|
27
|
-
|
|
35
|
+
SortableSortIndicator,
|
|
28
36
|
{
|
|
29
37
|
component: "span",
|
|
30
|
-
|
|
38
|
+
ownSx: { display: "inline-flex", alignItems: "center", color: "primary.main", fontWeight: 700 },
|
|
31
39
|
"aria-label": sortEntry.direction === "asc" ? t("sort.ascending") : t("sort.descending"),
|
|
32
40
|
children: sortEntry.direction === "asc" ? "↑" : "↓"
|
|
33
41
|
}
|
|
34
42
|
)
|
|
35
43
|
] }) }) : title,
|
|
36
44
|
sortEntry && onClearSort && /* @__PURE__ */ jsx(Tooltip, { title: t("sort.clear"), children: /* @__PURE__ */ jsx(
|
|
37
|
-
|
|
45
|
+
SortableClearButton,
|
|
38
46
|
{
|
|
39
47
|
"aria-label": t("sort.clear"),
|
|
40
|
-
|
|
48
|
+
ownSx: { fontSize: 12, lineHeight: 1, color: "primary.main", "&:hover": { color: "primary.dark" } },
|
|
41
49
|
onClick: (event) => {
|
|
42
50
|
event.stopPropagation();
|
|
43
51
|
onClearSort();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SortableFilterHeader.js","sources":["../../../src/DataTable/ColumnFilters/SortableFilterHeader.jsx"],"sourcesContent":["// Encabezado con orden y filtro.\n//\n// El que ordena es el TÍTULO, no un botón aparte: es el gesto que ya tiene aprendido quien usa tablas. La flecha solo\n// aparece cuando la columna está ordenando, y su × quita ese orden sin tener que ciclar hasta el tercer clic.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport ButtonBase from '@mui/material/ButtonBase';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\n\nimport HeaderFilterPopover from '@/DataTable/ColumnFilters/HeaderFilterPopover.jsx';\n\n/**\n * @param {object} props\n * @param {string} props.label\n * @param {boolean} [props.sortable]\n * @param {{column: string, direction: 'asc'|'desc'}} [props.sortEntry]\n * @param {() => void} [props.onSort]\n * @param {() => void} [props.onClearSort]\n * @param {boolean} [props.filterable]\n * @param {number} [props.activeCount]\n * @param {() => void} [props.onClear]\n * @param {import('react').ReactNode} [props.children] el filtro de la columna\n */\nexport default function SortableFilterHeader({\n label, sortable = true, sortEntry, onSort, onClearSort, filterable = true, activeCount, onClear, children,\n})
|
|
1
|
+
{"version":3,"file":"SortableFilterHeader.js","sources":["../../../src/DataTable/ColumnFilters/SortableFilterHeader.jsx"],"sourcesContent":["// Encabezado con orden y filtro.\n//\n// El que ordena es el TÍTULO, no un botón aparte: es el gesto que ya tiene aprendido quien usa tablas. La flecha solo\n// aparece cuando la columna está ordenando, y su × quita ese orden sin tener que ciclar hasta el tercer clic.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaSortableFilterHeader con defaultProps y\n// styleOverrides de sus partes: title, root, sortButton, sortIndicator, clearButton.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport ButtonBase from '@mui/material/ButtonBase';\nimport Stack from '@mui/material/Stack';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\n\nimport HeaderFilterPopover from '@/DataTable/ColumnFilters/HeaderFilterPopover.jsx';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaSortableFilterHeader)\nconst THEME_NAME = 'CalcitaSortableFilterHeader';\nconst SortableTitle = piecePart(THEME_NAME, 'Title', Typography);\nconst SortableRoot = piecePart(THEME_NAME, 'Root', Stack);\nconst SortableSortButton = piecePart(THEME_NAME, 'SortButton', ButtonBase);\nconst SortableSortIndicator = piecePart(THEME_NAME, 'SortIndicator', Box);\nconst SortableClearButton = piecePart(THEME_NAME, 'ClearButton', ButtonBase);\n\n/**\n * @param {object} props\n * @param {string} props.label\n * @param {boolean} [props.sortable]\n * @param {{column: string, direction: 'asc'|'desc'}} [props.sortEntry]\n * @param {() => void} [props.onSort]\n * @param {() => void} [props.onClearSort]\n * @param {boolean} [props.filterable]\n * @param {number} [props.activeCount]\n * @param {() => void} [props.onClear]\n * @param {import('react').ReactNode} [props.children] el filtro de la columna\n */\nexport default function SortableFilterHeader(props) {\n // lo que el proyecto puso en su tema (components.CalcitaSortableFilterHeader.defaultProps) y encima lo que llega aquí\n const {\n label, sortable = true, sortEntry, onSort, onClearSort, filterable = true, activeCount, onClear, children,\n} = usePieceProps(props, THEME_NAME);\n const {t} = useToolkitTranslation('table');\n const title = <SortableTitle variant=\"caption\" ownSx={{fontWeight: 700, whiteSpace: 'nowrap'}}>{label}</SortableTitle>;\n\n return (\n <SortableRoot direction=\"row\" spacing={0.25} ownSx={{alignItems: 'center'}}>\n {sortable ? (\n <Tooltip title={t('sort.tooltip')}>\n <SortableSortButton onClick={onSort} ownSx={{gap: 0.25, borderRadius: 0.5}}>\n {title}\n {sortEntry && (\n <SortableSortIndicator component=\"span\" ownSx={{display: 'inline-flex', alignItems: 'center', color: 'primary.main', fontWeight: 700}}\n aria-label={sortEntry.direction === 'asc' ? t('sort.ascending') : t('sort.descending')}>\n {sortEntry.direction === 'asc' ? '↑' : '↓'}\n </SortableSortIndicator>\n )}\n </SortableSortButton>\n </Tooltip>\n ) : title}\n\n {sortEntry && onClearSort && (\n <Tooltip title={t('sort.clear')}>\n <SortableClearButton aria-label={t('sort.clear')}\n // sin opacidad: la × es un control y al 70% daba 2.90:1 sobre el encabezado de la tabla\n ownSx={{fontSize: 12, lineHeight: 1, color: 'primary.main', '&:hover': {color: 'primary.dark'}}}\n onClick={(event) => {\n event.stopPropagation();\n onClearSort();\n }}>\n ×\n </SortableClearButton>\n </Tooltip>\n )}\n\n {filterable && (\n <HeaderFilterPopover activeCount={activeCount} onClear={onClear}>{children}</HeaderFilterPopover>\n )}\n </SortableRoot>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;AAoBA,MAAM,aAAa;AACnB,MAAM,gBAAgB,UAAU,YAAY,SAAS,UAAU;AAC/D,MAAM,eAAe,UAAU,YAAY,QAAQ,KAAK;AACxD,MAAM,qBAAqB,UAAU,YAAY,cAAc,UAAU;AACzE,MAAM,wBAAwB,UAAU,YAAY,iBAAiB,GAAG;AACxE,MAAM,sBAAsB,UAAU,YAAY,eAAe,UAAU;AAc3E,SAAwB,qBAAqB,OAAO;AAEhD,QAAM;AAAA,IACN;AAAA,IAAO,WAAW;AAAA,IAAM;AAAA,IAAW;AAAA,IAAQ;AAAA,IAAa,aAAa;AAAA,IAAM;AAAA,IAAa;AAAA,IAAS;AAAA,EAAA,IACjG,cAAc,OAAO,UAAU;AAC/B,QAAM,EAAC,EAAA,IAAK,sBAAsB,OAAO;AACzC,QAAM,QAAQ,oBAAC,eAAA,EAAc,SAAQ,WAAU,OAAO,EAAC,YAAY,KAAK,YAAY,SAAA,GAAY,UAAA,MAAA,CAAM;AAEtG,SACI,qBAAC,cAAA,EAAa,WAAU,OAAM,SAAS,MAAM,OAAO,EAAC,YAAY,SAAA,GAC5D,UAAA;AAAA,IAAA,+BACI,SAAA,EAAQ,OAAO,EAAE,cAAc,GAC5B,UAAA,qBAAC,oBAAA,EAAmB,SAAS,QAAQ,OAAO,EAAC,KAAK,MAAM,cAAc,OACjE,UAAA;AAAA,MAAA;AAAA,MACA,aACG;AAAA,QAAC;AAAA,QAAA;AAAA,UAAsB,WAAU;AAAA,UAAO,OAAO,EAAC,SAAS,eAAe,YAAY,UAAU,OAAO,gBAAgB,YAAY,IAAA;AAAA,UAC5H,cAAY,UAAU,cAAc,QAAQ,EAAE,gBAAgB,IAAI,EAAE,iBAAiB;AAAA,UACrF,UAAA,UAAU,cAAc,QAAQ,MAAM;AAAA,QAAA;AAAA,MAAA;AAAA,IAC3C,EAAA,CAER,GACJ,IACA;AAAA,IAEH,aAAa,eACV,oBAAC,WAAQ,OAAO,EAAE,YAAY,GAC1B,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QAAoB,cAAY,EAAE,YAAY;AAAA,QAEnC,OAAO,EAAC,UAAU,IAAI,YAAY,GAAG,OAAO,gBAAgB,WAAW,EAAC,OAAO,eAAA,EAAc;AAAA,QAC7F,SAAS,CAAC,UAAU;AAChB,gBAAM,gBAAA;AACN,sBAAA;AAAA,QACJ;AAAA,QAAG,UAAA;AAAA,MAAA;AAAA,IAAA,GAGnB;AAAA,IAGH,cACG,oBAAC,qBAAA,EAAoB,aAA0B,SAAmB,SAAA,CAAS;AAAA,EAAA,GAEnF;AAER;"}
|
|
@@ -7,11 +7,16 @@ import Stack from "@mui/material/Stack";
|
|
|
7
7
|
import Typography from "@mui/material/Typography";
|
|
8
8
|
import FilterListOffIcon from "@mui/icons-material/FilterListOff";
|
|
9
9
|
import InboxOutlinedIcon from "@mui/icons-material/InboxOutlined";
|
|
10
|
-
|
|
10
|
+
import { piecePart, usePieceProps } from "../theme/themePieces.js";
|
|
11
|
+
const THEME_NAME = "CalcitaEmptyState";
|
|
12
|
+
const EmptyRoot = piecePart(THEME_NAME, "Root", Stack);
|
|
13
|
+
const EmptyIcon = piecePart(THEME_NAME, "Icon", Box);
|
|
14
|
+
function EmptyState(props) {
|
|
15
|
+
const { filtered = false, label, onClearFilters, texts } = usePieceProps(props, THEME_NAME);
|
|
11
16
|
const { t } = useToolkitTranslation("table", texts);
|
|
12
17
|
const Icon = filtered ? FilterListOffIcon : InboxOutlinedIcon;
|
|
13
|
-
return /* @__PURE__ */ jsxs(
|
|
14
|
-
/* @__PURE__ */ jsx(
|
|
18
|
+
return /* @__PURE__ */ jsxs(EmptyRoot, { spacing: 1, ownSx: { height: "100%", px: 3, textAlign: "center", alignItems: "center", justifyContent: "center" }, children: [
|
|
19
|
+
/* @__PURE__ */ jsx(EmptyIcon, { ownSx: { color: "text.disabled", display: "flex" }, children: /* @__PURE__ */ jsx(Icon, { fontSize: "large" }) }),
|
|
15
20
|
/* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: filtered ? t("empty.filtered") : label ?? t("empty.default") }),
|
|
16
21
|
filtered && onClearFilters && /* @__PURE__ */ jsx(Button, { size: "small", onClick: onClearFilters, children: t("empty.clearFilters") })
|
|
17
22
|
] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmptyState.js","sources":["../../src/DataTable/EmptyState.jsx"],"sourcesContent":["// Qué decir cuando la tabla no tiene filas.\n//\n// Son dos situaciones distintas y confundirlas hace daño:\n// - sin filtros puestos, la lista vacía es el RESULTADO y se dice tal cual (label);\n// - con filtros puestos, la lista vacía NO dice nada del conjunto: dice que lo filtrado no existe dentro de él. Ahí\n// sí hay algo que hacer, y el botón lo hace.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport FilterListOffIcon from '@mui/icons-material/FilterListOff';\nimport InboxOutlinedIcon from '@mui/icons-material/InboxOutlined';\n\n/**\n * @param {object} [props]\n * @param {boolean} [props.filtered]\n * @param {string} [props.label] ya traducido\n * @param {() => void} [props.onClearFilters]\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\nexport default function EmptyState({filtered = false, label, onClearFilters, texts})
|
|
1
|
+
{"version":3,"file":"EmptyState.js","sources":["../../src/DataTable/EmptyState.jsx"],"sourcesContent":["// Qué decir cuando la tabla no tiene filas.\n//\n// Son dos situaciones distintas y confundirlas hace daño:\n// - sin filtros puestos, la lista vacía es el RESULTADO y se dice tal cual (label);\n// - con filtros puestos, la lista vacía NO dice nada del conjunto: dice que lo filtrado no existe dentro de él. Ahí\n// sí hay algo que hacer, y el botón lo hace.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaEmptyState con defaultProps y\n// styleOverrides de sus partes: root, icon.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport FilterListOffIcon from '@mui/icons-material/FilterListOff';\nimport InboxOutlinedIcon from '@mui/icons-material/InboxOutlined';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaEmptyState)\nconst THEME_NAME = 'CalcitaEmptyState';\nconst EmptyRoot = piecePart(THEME_NAME, 'Root', Stack);\nconst EmptyIcon = piecePart(THEME_NAME, 'Icon', Box);\n\n/**\n * @param {object} [props]\n * @param {boolean} [props.filtered]\n * @param {string} [props.label] ya traducido\n * @param {() => void} [props.onClearFilters]\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\nexport default function EmptyState(props) {\n // lo que el proyecto puso en su tema (components.CalcitaEmptyState.defaultProps) y encima lo que llega aquí\n const {filtered = false, label, onClearFilters, texts} = usePieceProps(props, THEME_NAME);\n const {t} = useToolkitTranslation('table', texts);\n const Icon = filtered ? FilterListOffIcon : InboxOutlinedIcon;\n\n return (\n <EmptyRoot spacing={1} ownSx={{height: '100%', px: 3, textAlign: 'center', alignItems: 'center', justifyContent: 'center'}}>\n <EmptyIcon ownSx={{color: 'text.disabled', display: 'flex'}}>\n <Icon fontSize=\"large\" />\n </EmptyIcon>\n <Typography variant=\"body2\" color=\"text.secondary\">\n {filtered ? t('empty.filtered') : (label ?? t('empty.default'))}\n </Typography>\n {filtered && onClearFilters && (\n <Button size=\"small\" onClick={onClearFilters}>{t('empty.clearFilters')}</Button>\n )}\n </EmptyRoot>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;AAqBA,MAAM,aAAa;AACnB,MAAM,YAAY,UAAU,YAAY,QAAQ,KAAK;AACrD,MAAM,YAAY,UAAU,YAAY,QAAQ,GAAG;AASnD,SAAwB,WAAW,OAAO;AAEtC,QAAM,EAAC,WAAW,OAAO,OAAO,gBAAgB,UAAS,cAAc,OAAO,UAAU;AACxF,QAAM,EAAC,EAAA,IAAK,sBAAsB,SAAS,KAAK;AAChD,QAAM,OAAO,WAAW,oBAAoB;AAE5C,8BACK,WAAA,EAAU,SAAS,GAAG,OAAO,EAAC,QAAQ,QAAQ,IAAI,GAAG,WAAW,UAAU,YAAY,UAAU,gBAAgB,YAC7G,UAAA;AAAA,IAAA,oBAAC,WAAA,EAAU,OAAO,EAAC,OAAO,iBAAiB,SAAS,OAAA,GAChD,UAAA,oBAAC,MAAA,EAAK,UAAS,QAAA,CAAQ,GAC3B;AAAA,IACA,oBAAC,YAAA,EAAW,SAAQ,SAAQ,OAAM,kBAC7B,UAAA,WAAW,EAAE,gBAAgB,IAAK,SAAS,EAAE,eAAe,GACjE;AAAA,IACC,YAAY,kBACT,oBAAC,QAAA,EAAO,MAAK,SAAQ,SAAS,gBAAiB,UAAA,EAAE,oBAAoB,EAAA,CAAE;AAAA,EAAA,GAE/E;AAER;"}
|
|
@@ -8,24 +8,30 @@ import Typography from "@mui/material/Typography";
|
|
|
8
8
|
import ClearAllIcon from "@mui/icons-material/ClearAll";
|
|
9
9
|
import ScrollableRow from "../ui/layout/ScrollableRow.js";
|
|
10
10
|
import Tag from "../ui/labels/Tag.js";
|
|
11
|
-
|
|
11
|
+
import { piecePart, usePieceProps } from "../theme/themePieces.js";
|
|
12
|
+
const THEME_NAME = "CalcitaFilterChips";
|
|
13
|
+
const ChipsRoot = piecePart(THEME_NAME, "Root", Box);
|
|
14
|
+
const ChipsHeader = piecePart(THEME_NAME, "Header", Stack);
|
|
15
|
+
const ChipsClearButton = piecePart(THEME_NAME, "ClearButton", Button);
|
|
16
|
+
function FilterChips(props) {
|
|
17
|
+
const { chipConfig, filters, onSetFilter, onClearAll, quickActiveCount = 0, texts } = usePieceProps(props, THEME_NAME);
|
|
12
18
|
const { t } = useToolkitTranslation("table", texts);
|
|
13
19
|
const chips = chipConfig.filter((chipDeclaration) => chipDeclaration.isActive(filters[chipDeclaration.key])).flatMap((chipDeclaration) => chipDeclaration.chipsFor(filters[chipDeclaration.key], onSetFilter));
|
|
14
20
|
const activeCount = chips.length + quickActiveCount;
|
|
15
21
|
if (activeCount === 0) {
|
|
16
22
|
return null;
|
|
17
23
|
}
|
|
18
|
-
return /* @__PURE__ */ jsxs(
|
|
19
|
-
/* @__PURE__ */ jsxs(
|
|
24
|
+
return /* @__PURE__ */ jsxs(ChipsRoot, { ownSx: { mb: 1.5, minWidth: 0 }, children: [
|
|
25
|
+
/* @__PURE__ */ jsxs(ChipsHeader, { direction: "row", spacing: 1, ownSx: { px: 0.25, alignItems: "center", justifyContent: "space-between" }, children: [
|
|
20
26
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", noWrap: true, children: t("chips.applied", { count: activeCount }) }),
|
|
21
27
|
/* @__PURE__ */ jsx(
|
|
22
|
-
|
|
28
|
+
ChipsClearButton,
|
|
23
29
|
{
|
|
24
30
|
size: "small",
|
|
25
31
|
color: "error",
|
|
26
32
|
startIcon: /* @__PURE__ */ jsx(ClearAllIcon, { fontSize: "small" }),
|
|
27
33
|
onClick: onClearAll,
|
|
28
|
-
|
|
34
|
+
ownSx: { flexShrink: 0 },
|
|
29
35
|
children: t("chips.clearAll")
|
|
30
36
|
}
|
|
31
37
|
)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterChips.js","sources":["../../src/DataTable/FilterChips.jsx"],"sourcesContent":["// Los filtros activos, a la vista y desarmables de a uno.\n//\n// Un filtro que solo se ve como un icono encendido en el encabezado se olvida: alguien filtra, se va al detalle,\n// regresa y lee el total como si fuera el de todo. Por eso los filtros puestos se dicen con todas sus letras arriba de\n// la tabla.\n//\n// Van en UNA tira que se desliza (ScrollableRow), no envolviéndose en renglones que empujan la tabla fuera de la\n// pantalla. La cuenta y \"Limpiar todo\" van en su propio renglón, arriba, para no tener que deslizar hasta encontrarlo.\n// Sin filtros activos no se pinta nada (ni el hueco).\n//\n// Los accesos rápidos cuentan aunque no tengan chip aquí: su propio chip encendido ya dice qué está elegido.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport ClearAllIcon from '@mui/icons-material/ClearAll';\n\nimport ScrollableRow from '@/ui/layout/ScrollableRow.jsx';\nimport Tag from '@/ui/labels/Tag.jsx';\n\n/**\n * @param {object} props\n * @param {Array<object>} props.chipConfig lo que arma buildChipConfig\n * @param {object} props.filters\n * @param {(field: string, value: unknown) => void} props.onSetFilter\n * @param {() => void} props.onClearAll\n * @param {number} [props.quickActiveCount] accesos rápidos puestos que no tienen chip aquí\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\nexport default function FilterChips({chipConfig, filters, onSetFilter, onClearAll, quickActiveCount = 0, texts})
|
|
1
|
+
{"version":3,"file":"FilterChips.js","sources":["../../src/DataTable/FilterChips.jsx"],"sourcesContent":["// Los filtros activos, a la vista y desarmables de a uno.\n//\n// Un filtro que solo se ve como un icono encendido en el encabezado se olvida: alguien filtra, se va al detalle,\n// regresa y lee el total como si fuera el de todo. Por eso los filtros puestos se dicen con todas sus letras arriba de\n// la tabla.\n//\n// Van en UNA tira que se desliza (ScrollableRow), no envolviéndose en renglones que empujan la tabla fuera de la\n// pantalla. La cuenta y \"Limpiar todo\" van en su propio renglón, arriba, para no tener que deslizar hasta encontrarlo.\n// Sin filtros activos no se pinta nada (ni el hueco).\n//\n// Los accesos rápidos cuentan aunque no tengan chip aquí: su propio chip encendido ya dice qué está elegido.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaFilterChips con defaultProps y\n// styleOverrides de sus partes: root, header, clearButton.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Box from '@mui/material/Box';\nimport Button from '@mui/material/Button';\nimport Stack from '@mui/material/Stack';\nimport Typography from '@mui/material/Typography';\nimport ClearAllIcon from '@mui/icons-material/ClearAll';\n\nimport ScrollableRow from '@/ui/layout/ScrollableRow.jsx';\nimport Tag from '@/ui/labels/Tag.jsx';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaFilterChips)\nconst THEME_NAME = 'CalcitaFilterChips';\nconst ChipsRoot = piecePart(THEME_NAME, 'Root', Box);\nconst ChipsHeader = piecePart(THEME_NAME, 'Header', Stack);\nconst ChipsClearButton = piecePart(THEME_NAME, 'ClearButton', Button);\n\n/**\n * @param {object} props\n * @param {Array<object>} props.chipConfig lo que arma buildChipConfig\n * @param {object} props.filters\n * @param {(field: string, value: unknown) => void} props.onSetFilter\n * @param {() => void} props.onClearAll\n * @param {number} [props.quickActiveCount] accesos rápidos puestos que no tienen chip aquí\n * @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete\n */\nexport default function FilterChips(props) {\n // lo que el proyecto puso en su tema (components.CalcitaFilterChips.defaultProps) y encima lo que llega aquí\n const {chipConfig, filters, onSetFilter, onClearAll, quickActiveCount = 0, texts} = usePieceProps(props, THEME_NAME);\n const {t} = useToolkitTranslation('table', texts);\n const chips = chipConfig\n .filter((chipDeclaration) => chipDeclaration.isActive(filters[chipDeclaration.key]))\n .flatMap((chipDeclaration) => chipDeclaration.chipsFor(filters[chipDeclaration.key], onSetFilter));\n\n const activeCount = chips.length + quickActiveCount;\n // guard clause: sin filtros no se pinta nada\n if (activeCount === 0) {\n return null;\n }\n\n return (\n <ChipsRoot ownSx={{mb: 1.5, minWidth: 0}}>\n <ChipsHeader direction=\"row\" spacing={1} ownSx={{px: 0.25, alignItems: 'center', justifyContent: 'space-between'}}>\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap>\n {t('chips.applied', {count: activeCount})}\n </Typography>\n <ChipsClearButton size=\"small\" color=\"error\" startIcon={<ClearAllIcon fontSize=\"small\" />} onClick={onClearAll}\n ownSx={{flexShrink: 0}}>\n {t('chips.clearAll')}\n </ChipsClearButton>\n </ChipsHeader>\n\n {chips.length > 0 && (\n <ScrollableRow>\n {chips.map(({id, label, onDelete}) => (\n <Tag key={id} label={label} color=\"primary\" onDelete={onDelete} sx={{flex: '0 0 auto'}} />\n ))}\n </ScrollableRow>\n )}\n </ChipsRoot>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;AA4BA,MAAM,aAAa;AACnB,MAAM,YAAY,UAAU,YAAY,QAAQ,GAAG;AACnD,MAAM,cAAc,UAAU,YAAY,UAAU,KAAK;AACzD,MAAM,mBAAmB,UAAU,YAAY,eAAe,MAAM;AAWpE,SAAwB,YAAY,OAAO;AAEvC,QAAM,EAAC,YAAY,SAAS,aAAa,YAAY,mBAAmB,GAAG,MAAA,IAAS,cAAc,OAAO,UAAU;AACnH,QAAM,EAAC,EAAA,IAAK,sBAAsB,SAAS,KAAK;AAChD,QAAM,QAAQ,WACT,OAAO,CAAC,oBAAoB,gBAAgB,SAAS,QAAQ,gBAAgB,GAAG,CAAC,CAAC,EAClF,QAAQ,CAAC,oBAAoB,gBAAgB,SAAS,QAAQ,gBAAgB,GAAG,GAAG,WAAW,CAAC;AAErG,QAAM,cAAc,MAAM,SAAS;AAEnC,MAAI,gBAAgB,GAAG;AACnB,WAAO;AAAA,EACX;AAEA,SACI,qBAAC,aAAU,OAAO,EAAC,IAAI,KAAK,UAAU,KAClC,UAAA;AAAA,IAAA,qBAAC,aAAA,EAAY,WAAU,OAAM,SAAS,GAAG,OAAO,EAAC,IAAI,MAAM,YAAY,UAAU,gBAAgB,mBAC7F,UAAA;AAAA,MAAA,oBAAC,YAAA,EAAW,SAAQ,WAAU,OAAM,kBAAiB,QAAM,MACtD,UAAA,EAAE,iBAAiB,EAAC,OAAO,YAAA,CAAY,GAC5C;AAAA,MACA;AAAA,QAAC;AAAA,QAAA;AAAA,UAAiB,MAAK;AAAA,UAAQ,OAAM;AAAA,UAAQ,WAAW,oBAAC,cAAA,EAAa,UAAS,QAAA,CAAQ;AAAA,UAAI,SAAS;AAAA,UAC5F,OAAO,EAAC,YAAY,EAAA;AAAA,UACvB,YAAE,gBAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IACvB,GACJ;AAAA,IAEC,MAAM,SAAS,KACZ,oBAAC,eAAA,EACI,UAAA,MAAM,IAAI,CAAC,EAAC,IAAI,OAAO,SAAA,0BACnB,KAAA,EAAa,OAAc,OAAM,WAAU,UAAoB,IAAI,EAAC,MAAM,WAAA,KAAjE,EAA8E,CAC3F,EAAA,CACL;AAAA,EAAA,GAER;AAER;"}
|