@stackcraftmx/calcita 0.28.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 +139 -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 +4 -0
- 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 +64 -64
- 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 +6 -2
- package/dist/theme/components/minimalComponents.js.map +1 -1
- package/dist/theme/createToolkitTheme.js +8 -1
- 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 +9 -3
- 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 +1 -0
- 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 +12 -1
- package/dist/types/theme/cssTokens.d.ts +46 -0
- package/dist/types/theme/glassSurface.d.ts +3 -0
- 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
|
@@ -22,7 +22,7 @@ export declare function selectionFloatsOnPhone(theme: object): boolean;
|
|
|
22
22
|
* @param {object} [props.texts] los textos que cambian, con la forma de `common`: {selection: {clear, actionsLabel, summaryLabel}}
|
|
23
23
|
* @param {object} [props.sx] estilos del renglón
|
|
24
24
|
*/
|
|
25
|
-
export default function SelectionActions(
|
|
25
|
+
export default function SelectionActions(props: {
|
|
26
26
|
countText: string;
|
|
27
27
|
actions?: Array<{
|
|
28
28
|
key: string;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @param {string} [props.label] ya traducido; por defecto "Personalizado"
|
|
7
7
|
* @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete
|
|
8
8
|
*/
|
|
9
|
-
export default function DateRangeFilter(
|
|
9
|
+
export default function DateRangeFilter(props: {
|
|
10
10
|
from?: string;
|
|
11
11
|
to?: string;
|
|
12
12
|
onChange: (range: {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @param {string} props.toLabel ya traducido
|
|
10
10
|
* @param {(range: {from: string, to: string}) => void} props.onChange
|
|
11
11
|
*/
|
|
12
|
-
export default function PeriodRangeSelector(
|
|
12
|
+
export default function PeriodRangeSelector(props: {
|
|
13
13
|
id: string;
|
|
14
14
|
options: Array<{
|
|
15
15
|
value: string;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @param {import('react').ReactNode} [props.extra] al final de la tira (p. ej. un rango de fechas)
|
|
9
9
|
* @param {object} [props.texts] los textos que cambian, con la forma de `table` en los textos del paquete
|
|
10
10
|
*/
|
|
11
|
-
export default function QuickFilters(
|
|
11
|
+
export default function QuickFilters(props: {
|
|
12
12
|
value: string;
|
|
13
13
|
onChange: (value: string) => void;
|
|
14
14
|
options?: Array<{
|
|
@@ -11,14 +11,19 @@ export declare const SEGMENTED_CONTROL_SX: {
|
|
|
11
11
|
letterSpacing: string;
|
|
12
12
|
border: number;
|
|
13
13
|
borderRadius: string;
|
|
14
|
+
m: number;
|
|
14
15
|
px: number;
|
|
15
16
|
py: number;
|
|
16
|
-
m: string;
|
|
17
17
|
fontWeight: number;
|
|
18
18
|
textTransform: string;
|
|
19
19
|
color: string;
|
|
20
20
|
whiteSpace: string;
|
|
21
21
|
};
|
|
22
|
+
'& .MuiToggleButton-root.MuiToggleButtonGroup-grouped': {
|
|
23
|
+
border: number;
|
|
24
|
+
borderRadius: string;
|
|
25
|
+
m: number;
|
|
26
|
+
};
|
|
22
27
|
'& .MuiToggleButton-root.Mui-selected, & .MuiToggleButton-root.Mui-selected:hover': {
|
|
23
28
|
bgcolor: string;
|
|
24
29
|
color: string;
|
|
@@ -32,7 +37,7 @@ export declare const SEGMENTED_CONTROL_SX: {
|
|
|
32
37
|
* @param {(value: string) => void} props.onChange
|
|
33
38
|
* @param {string} props.ariaLabel ya traducido
|
|
34
39
|
*/
|
|
35
|
-
export default function SegmentedControl(
|
|
40
|
+
export default function SegmentedControl(props: {
|
|
36
41
|
options: Array<{
|
|
37
42
|
value: string;
|
|
38
43
|
label: string;
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* que decir. OJO: no envuelvas este componente en otro Tooltip, porque el suyo sigue ahí y se ven los dos encimados
|
|
11
11
|
* @param {object} [props.sx] ajustes de estilo del Chip (solo variant="chip")
|
|
12
12
|
*/
|
|
13
|
-
export default function StatusChip(
|
|
13
|
+
export default function StatusChip(props: {
|
|
14
14
|
dictionary: Record<string, object>;
|
|
15
15
|
value: string | null | undefined;
|
|
16
16
|
variant?: 'dot' | 'chip';
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @param {() => void} [props.onDelete]
|
|
9
9
|
* @param {object} [props.sx]
|
|
10
10
|
*/
|
|
11
|
-
export default function Tag(
|
|
11
|
+
export default function Tag(props: {
|
|
12
12
|
label: import('react').ReactNode;
|
|
13
13
|
tooltip?: string;
|
|
14
14
|
color?: string;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* adentro hasta que se abre)
|
|
9
9
|
* @param {import('react').ReactNode} props.children
|
|
10
10
|
*/
|
|
11
|
-
export default function CollapsibleSection(
|
|
11
|
+
export default function CollapsibleSection(props: {
|
|
12
12
|
collapsedTitle: string;
|
|
13
13
|
expandedTitle: string;
|
|
14
14
|
hint?: string;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @param {import('react').ReactNode} props.children
|
|
7
7
|
* @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete
|
|
8
8
|
*/
|
|
9
|
-
export default function ContentDialog(
|
|
9
|
+
export default function ContentDialog(props: {
|
|
10
10
|
open: boolean;
|
|
11
11
|
onClose: () => void;
|
|
12
12
|
title: string;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @param {'columns'|'stacked'} [props.layout]
|
|
6
6
|
* @param {number} [props.labelWidth] ancho en px de la columna del dato (solo columns)
|
|
7
7
|
*/
|
|
8
|
-
export default function DefinitionList(
|
|
8
|
+
export default function DefinitionList(props: {
|
|
9
9
|
entries: Array<{
|
|
10
10
|
label: string;
|
|
11
11
|
value: import('react').ReactNode;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @param {import('react').ReactNode} [props.actions] botones a la derecha
|
|
7
7
|
* @param {string} [props.documentTitle] título de la pestaña si difiere del visible
|
|
8
8
|
*/
|
|
9
|
-
export default function DetailHeader(
|
|
9
|
+
export default function DetailHeader(props: {
|
|
10
10
|
title: string;
|
|
11
11
|
eyebrow?: string;
|
|
12
12
|
badges?: import('react').ReactNode;
|
|
@@ -20,7 +20,7 @@ export declare const ERROR_PAGE_KIND: Readonly<{
|
|
|
20
20
|
* @param {object} [props.texts] los textos que cambian, con la forma de `errorPage` en los textos del paquete:
|
|
21
21
|
* {goHome: 'Volver al tablero', notFound: {title: '…'}}
|
|
22
22
|
*/
|
|
23
|
-
export default function ErrorPage(
|
|
23
|
+
export default function ErrorPage(props: {
|
|
24
24
|
kind: string;
|
|
25
25
|
title?: string;
|
|
26
26
|
text?: import('react').ReactNode;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @param {object|Function|Array} [props.sx] estilos propios: se suman y ganan
|
|
5
5
|
* @param {import('react').ElementType} [props.component] por omisión 'div'
|
|
6
6
|
*/
|
|
7
|
-
export default function GlassPanel(
|
|
7
|
+
export default function GlassPanel(props: {
|
|
8
8
|
children: import('react').ReactNode;
|
|
9
9
|
sx?: object | Function | any[];
|
|
10
10
|
component?: import('react').ElementType;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @param {import('react').ReactNode} [props.action] normalmente un <Button variant="contained" shape="pill">
|
|
7
7
|
* @param {string} [props.documentTitle] título de la pestaña si difiere del visible
|
|
8
8
|
*/
|
|
9
|
-
export default function PageHeader(
|
|
9
|
+
export default function PageHeader(props: {
|
|
10
10
|
title: string;
|
|
11
11
|
eyebrow?: string;
|
|
12
12
|
subtitle?: import('react').ReactNode;
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @param {string} [props.documentTitle] título de la pestaña si difiere del visible
|
|
8
8
|
* @param {object} [props.texts] los textos que cambian, con la forma de `layout` en los textos del paquete
|
|
9
9
|
*/
|
|
10
|
-
export default function PageHeading(
|
|
10
|
+
export default function PageHeading(props: {
|
|
11
11
|
title: string;
|
|
12
12
|
description?: import('react').ReactNode;
|
|
13
13
|
breadcrumbs?: Array<{
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* @param {string[]} [props.chips] sus perfiles o etiquetas, ya traducidos
|
|
8
8
|
* @param {import('react').ReactNode} [props.actions] los botones de la derecha
|
|
9
9
|
*/
|
|
10
|
-
export default function ProfileHeader(
|
|
10
|
+
export default function ProfileHeader(props: {
|
|
11
11
|
name: string;
|
|
12
12
|
email?: string;
|
|
13
13
|
subtitle?: string;
|
|
@@ -21,7 +21,7 @@ export declare const scrollableRow: {
|
|
|
21
21
|
* @param {boolean} [props.fadeEdges]
|
|
22
22
|
* @param {import('react').Ref<HTMLElement>} [props.ref]
|
|
23
23
|
*/
|
|
24
|
-
export default function ScrollableRow(
|
|
24
|
+
export default function ScrollableRow(props: {
|
|
25
25
|
children: import('react').ReactNode;
|
|
26
26
|
gap?: number;
|
|
27
27
|
py?: number;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @param {import('react').ReactNode} [props.action] botón o liga a la derecha del título
|
|
5
5
|
* @param {import('react').ReactNode} props.children
|
|
6
6
|
*/
|
|
7
|
-
export default function SectionCard(
|
|
7
|
+
export default function SectionCard(props: {
|
|
8
8
|
title: string;
|
|
9
9
|
action?: import('react').ReactNode;
|
|
10
10
|
children: import('react').ReactNode;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* @param {(view: 'chart'|'table') => void} [props.onViewChange] la persona cambió a la tabla o a la gráfica
|
|
9
9
|
* @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete
|
|
10
10
|
*/
|
|
11
|
-
export default function BarList(
|
|
11
|
+
export default function BarList(props: {
|
|
12
12
|
items: Array<{
|
|
13
13
|
key: string;
|
|
14
14
|
label: string;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* @param {(view: 'chart'|'table') => void} [props.onViewChange] la persona cambió a la tabla o a la gráfica
|
|
15
15
|
* @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete
|
|
16
16
|
*/
|
|
17
|
-
export default function CalendarHeatmap(
|
|
17
|
+
export default function CalendarHeatmap(props: {
|
|
18
18
|
startsOn: string;
|
|
19
19
|
endsOn: string;
|
|
20
20
|
days: Array<{
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @param {{active?: boolean, payload?: Array<{payload: any}>, render: (item: any) => import('react').ReactNode}} props
|
|
3
3
|
* active y payload los pone recharts; render recibe el renglón de data del punto o la columna
|
|
4
4
|
*/
|
|
5
|
-
export default function ChartTooltip(
|
|
5
|
+
export default function ChartTooltip(props: {
|
|
6
6
|
active?: boolean;
|
|
7
7
|
payload?: Array<{
|
|
8
8
|
payload: any;
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* @param {(view: 'chart'|'table') => void} [props.onViewChange] la persona cambió a la tabla o a la gráfica
|
|
22
22
|
* @param {object} [props.texts] los textos que cambian, con la forma de `common`: {charts: {viewAsTable, viewAsChart, legend}}
|
|
23
23
|
*/
|
|
24
|
-
export default function ColumnChart(
|
|
24
|
+
export default function ColumnChart(props: {
|
|
25
25
|
data: Array<Record<string, any>>;
|
|
26
26
|
periodLabel: string;
|
|
27
27
|
valueLabel?: string;
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* @param {(view: 'chart'|'table') => void} [props.onViewChange] la persona cambió a la tabla o a la gráfica
|
|
17
17
|
* @param {object} [props.texts] los textos que cambian, con la forma de `common`: {charts: {viewAsTable, viewAsChart, legend}}
|
|
18
18
|
*/
|
|
19
|
-
export default function LineChart(
|
|
19
|
+
export default function LineChart(props: {
|
|
20
20
|
data: Array<Record<string, any>>;
|
|
21
21
|
series: Array<{
|
|
22
22
|
key: string;
|
|
@@ -19,7 +19,7 @@ export declare const TREND_DIRECTION: Readonly<{
|
|
|
19
19
|
* @param {() => void} [props.onClick] la tarjeta entera como botón, cuando no lleva a otra pantalla (to)
|
|
20
20
|
* @param {object} [props.texts] los textos que cambian, con la forma de `metricCard`: {trend: {up: 'subió'}}
|
|
21
21
|
*/
|
|
22
|
-
export default function MetricCard(
|
|
22
|
+
export default function MetricCard(props: {
|
|
23
23
|
label: string;
|
|
24
24
|
value: import('react').ReactNode;
|
|
25
25
|
caption?: import('react').ReactNode;
|
|
@@ -7,7 +7,7 @@ export declare const CHART_VIEW: Readonly<{
|
|
|
7
7
|
* @param {{asTable: boolean, onToggle: () => void, texts?: object}} props texts: los textos que cambian, con la forma de
|
|
8
8
|
* `common` ({charts: {viewAsTable, viewAsChart}})
|
|
9
9
|
*/
|
|
10
|
-
export default function TableToggle(
|
|
10
|
+
export default function TableToggle(props: {
|
|
11
11
|
asTable: boolean;
|
|
12
12
|
onToggle: () => void;
|
|
13
13
|
texts?: object;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* @param {(mode: 'light'|'dark'|'system') => void} [props.onChange] la persona cambió el modo (para guardarlo en su servidor)
|
|
6
6
|
* @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete
|
|
7
7
|
*/
|
|
8
|
-
export default function ColorSchemeToggle(
|
|
8
|
+
export default function ColorSchemeToggle(props?: {
|
|
9
9
|
size?: 'small' | 'medium';
|
|
10
10
|
inverted?: boolean;
|
|
11
11
|
onChange?: (mode: 'light' | 'dark' | 'system') => void;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @param {(level: string) => void} [props.onChange] la persona eligió otro tamaño (FONT_SIZE_LEVELS; para guardarlo en su servidor)
|
|
5
5
|
* @param {object} [props.texts] los textos que cambian, con la forma de `layout` en los textos del paquete
|
|
6
6
|
*/
|
|
7
|
-
export default function FontSizeToggle(
|
|
7
|
+
export default function FontSizeToggle(props?: {
|
|
8
8
|
size?: 'small' | 'medium';
|
|
9
9
|
onChange?: (level: string) => void;
|
|
10
10
|
texts?: object;
|
|
@@ -6,7 +6,7 @@ export declare const LANGUAGES: readonly ("en" | "es")[];
|
|
|
6
6
|
* @param {(language: string) => void} [props.onChange] además de avisar a ToolkitProvider, cada que se elige un idioma
|
|
7
7
|
* @param {object} [props.texts] los textos que cambian, con la forma de `common`: {language: {switchToNamed, choose}}
|
|
8
8
|
*/
|
|
9
|
-
export default function LanguageToggle(
|
|
9
|
+
export default function LanguageToggle(props?: {
|
|
10
10
|
inverted?: boolean;
|
|
11
11
|
onChange?: (language: string) => void;
|
|
12
12
|
texts?: object;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @param {Array<{label: string, to?: string}>} props.items textos ya traducidos
|
|
4
4
|
* @param {object} [props.texts] los textos que cambian, con la forma de `layout` en los textos del paquete
|
|
5
5
|
*/
|
|
6
|
-
export default function PageBreadcrumbs(
|
|
6
|
+
export default function PageBreadcrumbs(props: {
|
|
7
7
|
items: Array<{
|
|
8
8
|
label: string;
|
|
9
9
|
to?: string;
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* @param {(groupKey: string, isExpanded: boolean) => void} [props.onGroupToggle] la persona abrió o plegó un grupo (por ejemplo,
|
|
20
20
|
* para pedir sus eventos hasta que se abre)
|
|
21
21
|
*/
|
|
22
|
-
export default function GroupedTimeline(
|
|
22
|
+
export default function GroupedTimeline(props: {
|
|
23
23
|
groups: {
|
|
24
24
|
key: string;
|
|
25
25
|
title?: string;
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* @param {object} [props.sx] ajustes del recuadro
|
|
16
16
|
* @param {object} [props.texts] los textos que cambian, con la forma de `common` en los textos del paquete
|
|
17
17
|
*/
|
|
18
|
-
export default function FileDropzone(
|
|
18
|
+
export default function FileDropzone(props: {
|
|
19
19
|
value?: File | null;
|
|
20
20
|
onChange: (file: File | null) => void;
|
|
21
21
|
accept?: string | string[];
|
|
@@ -8,7 +8,12 @@ import Menu from "@mui/material/Menu";
|
|
|
8
8
|
import MenuItem from "@mui/material/MenuItem";
|
|
9
9
|
import Tooltip from "@mui/material/Tooltip";
|
|
10
10
|
import MoreHorizRoundedIcon from "@mui/icons-material/MoreHorizRounded";
|
|
11
|
-
|
|
11
|
+
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
12
|
+
const THEME_NAME = "CalcitaActionsMenu";
|
|
13
|
+
const ActionsItem = piecePart(THEME_NAME, "Item", MenuItem);
|
|
14
|
+
const ActionsItemIcon = piecePart(THEME_NAME, "ItemIcon", ListItemIcon);
|
|
15
|
+
function ActionsMenu(props) {
|
|
16
|
+
const { label, actions, icon, size = "small" } = usePieceProps(props, THEME_NAME);
|
|
12
17
|
const [anchor, setAnchor] = useState(null);
|
|
13
18
|
if (!actions?.length) {
|
|
14
19
|
return null;
|
|
@@ -28,16 +33,16 @@ function ActionsMenu({ label, actions, icon, size = "small" }) {
|
|
|
28
33
|
}
|
|
29
34
|
) }),
|
|
30
35
|
/* @__PURE__ */ jsx(Menu, { anchorEl: anchor, open: Boolean(anchor), onClose: () => setAnchor(null), onClick: (event) => event.stopPropagation(), children: actions.map((action) => /* @__PURE__ */ jsxs(
|
|
31
|
-
|
|
36
|
+
ActionsItem,
|
|
32
37
|
{
|
|
33
38
|
disabled: action.disabled,
|
|
34
39
|
onClick: () => {
|
|
35
40
|
setAnchor(null);
|
|
36
41
|
action.onClick();
|
|
37
42
|
},
|
|
38
|
-
|
|
43
|
+
ownSx: action.color ? { color: `${action.color}.main` } : void 0,
|
|
39
44
|
children: [
|
|
40
|
-
action.icon && /* @__PURE__ */ jsx(
|
|
45
|
+
action.icon && /* @__PURE__ */ jsx(ActionsItemIcon, { ownSx: action.color ? { color: "inherit" } : void 0, children: action.icon }),
|
|
41
46
|
/* @__PURE__ */ jsx(ListItemText, { children: action.label })
|
|
42
47
|
]
|
|
43
48
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionsMenu.js","sources":["../../../src/ui/actions/ActionsMenu.jsx"],"sourcesContent":["// Un botón «⋯» con un menú de acciones: el de cada tarjeta del tablero, el de cada columna, el de cada mensaje de la bandeja.\n// Las acciones las da la pantalla (label ya traducido, ícono, color, apagada); sin acciones no se pinta nada.\n//\n// <ActionsMenu label=\"Acciones de «Junta de cierre»\"\n// actions={[{key: 'delete', label: 'Borrar', icon: <DeleteOutlineIcon fontSize=\"small\" />, color: 'error', onClick: remove}]} />\n//\n// El clic no llega a lo de abajo: no levanta una tarjeta que se arrastra ni abre el renglón donde vive.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport IconButton from '@mui/material/IconButton';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport Menu from '@mui/material/Menu';\nimport MenuItem from '@mui/material/MenuItem';\nimport Tooltip from '@mui/material/Tooltip';\nimport MoreHorizRoundedIcon from '@mui/icons-material/MoreHorizRounded';\n\n/**\n * @param {object} props\n * @param {string} props.label el nombre del botón (lector de pantalla y su tooltip), ya traducido\n * @param {Array<{key: string, label: string, icon?: import('react').ReactNode, color?: string, disabled?: boolean, onClick: () => void}>} [props.actions]\n * @param {import('react').ReactNode} [props.icon] otro ícono para el botón (por omisión «⋯»)\n * @param {'small'|'medium'} [props.size]\n */\nexport default function ActionsMenu({label, actions, icon, size = 'small'})
|
|
1
|
+
{"version":3,"file":"ActionsMenu.js","sources":["../../../src/ui/actions/ActionsMenu.jsx"],"sourcesContent":["// Un botón «⋯» con un menú de acciones: el de cada tarjeta del tablero, el de cada columna, el de cada mensaje de la bandeja.\n// Las acciones las da la pantalla (label ya traducido, ícono, color, apagada); sin acciones no se pinta nada.\n//\n// <ActionsMenu label=\"Acciones de «Junta de cierre»\"\n// actions={[{key: 'delete', label: 'Borrar', icon: <DeleteOutlineIcon fontSize=\"small\" />, color: 'error', onClick: remove}]} />\n//\n// El clic no llega a lo de abajo: no levanta una tarjeta que se arrastra ni abre el renglón donde vive.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaActionsMenu con defaultProps y\n// styleOverrides de sus partes: item, itemIcon.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport IconButton from '@mui/material/IconButton';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport Menu from '@mui/material/Menu';\nimport MenuItem from '@mui/material/MenuItem';\nimport Tooltip from '@mui/material/Tooltip';\nimport MoreHorizRoundedIcon from '@mui/icons-material/MoreHorizRounded';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaActionsMenu)\nconst THEME_NAME = 'CalcitaActionsMenu';\nconst ActionsItem = piecePart(THEME_NAME, 'Item', MenuItem);\nconst ActionsItemIcon = piecePart(THEME_NAME, 'ItemIcon', ListItemIcon);\n\n/**\n * @param {object} props\n * @param {string} props.label el nombre del botón (lector de pantalla y su tooltip), ya traducido\n * @param {Array<{key: string, label: string, icon?: import('react').ReactNode, color?: string, disabled?: boolean, onClick: () => void}>} [props.actions]\n * @param {import('react').ReactNode} [props.icon] otro ícono para el botón (por omisión «⋯»)\n * @param {'small'|'medium'} [props.size]\n */\nexport default function ActionsMenu(props) {\n // lo que el proyecto puso en su tema (components.CalcitaActionsMenu.defaultProps) y encima lo que llega aquí\n const {label, actions, icon, size = 'small'} = usePieceProps(props, THEME_NAME);\n const [anchor, setAnchor] = useState(null);\n if (!actions?.length) {\n return null;\n }\n return (\n <>\n <Tooltip title={label}>\n <IconButton size={size} aria-label={label} aria-haspopup=\"menu\"\n onClick={(event) => {\n event.stopPropagation();\n setAnchor(event.currentTarget);\n }}>\n {icon ?? <MoreHorizRoundedIcon fontSize=\"small\" />}\n </IconButton>\n </Tooltip>\n <Menu anchorEl={anchor} open={Boolean(anchor)} onClose={() => setAnchor(null)} onClick={(event) => event.stopPropagation()}>\n {actions.map((action) => (\n <ActionsItem key={action.key} disabled={action.disabled}\n onClick={() => {\n setAnchor(null);\n action.onClick();\n }}\n ownSx={action.color ? {color: `${action.color}.main`} : undefined}>\n {action.icon && <ActionsItemIcon ownSx={action.color ? {color: 'inherit'} : undefined}>{action.icon}</ActionsItemIcon>}\n <ListItemText>{action.label}</ListItemText>\n </ActionsItem>\n ))}\n </Menu>\n </>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;AAuBA,MAAM,aAAa;AACnB,MAAM,cAAc,UAAU,YAAY,QAAQ,QAAQ;AAC1D,MAAM,kBAAkB,UAAU,YAAY,YAAY,YAAY;AAStE,SAAwB,YAAY,OAAO;AAEvC,QAAM,EAAC,OAAO,SAAS,MAAM,OAAO,YAAW,cAAc,OAAO,UAAU;AAC9E,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,IAAI;AACzC,MAAI,CAAC,SAAS,QAAQ;AAClB,WAAO;AAAA,EACX;AACA,SACI,qBAAA,UAAA,EACI,UAAA;AAAA,IAAA,oBAAC,SAAA,EAAQ,OAAO,OACZ,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QAAW;AAAA,QAAY,cAAY;AAAA,QAAO,iBAAc;AAAA,QAC7C,SAAS,CAAC,UAAU;AAChB,gBAAM,gBAAA;AACN,oBAAU,MAAM,aAAa;AAAA,QACjC;AAAA,QACP,UAAA,QAAQ,oBAAC,sBAAA,EAAqB,UAAS,QAAA,CAAQ;AAAA,MAAA;AAAA,IAAA,GAExD;AAAA,IACA,oBAAC,QAAK,UAAU,QAAQ,MAAM,QAAQ,MAAM,GAAG,SAAS,MAAM,UAAU,IAAI,GAAG,SAAS,CAAC,UAAU,MAAM,mBACpG,UAAA,QAAQ,IAAI,CAAC,WACV;AAAA,MAAC;AAAA,MAAA;AAAA,QAA6B,UAAU,OAAO;AAAA,QACrC,SAAS,MAAM;AACX,oBAAU,IAAI;AACd,iBAAO,QAAA;AAAA,QACX;AAAA,QACA,OAAO,OAAO,QAAQ,EAAC,OAAO,GAAG,OAAO,KAAK,QAAA,IAAW;AAAA,QAC7D,UAAA;AAAA,UAAA,OAAO,QAAQ,oBAAC,iBAAA,EAAgB,OAAO,OAAO,QAAQ,EAAC,OAAO,UAAA,IAAa,QAAY,UAAA,OAAO,MAAK;AAAA,UACpG,oBAAC,cAAA,EAAc,UAAA,OAAO,MAAA,CAAM;AAAA,QAAA;AAAA,MAAA;AAAA,MAPd,OAAO;AAAA,IAAA,CAS5B,EAAA,CACL;AAAA,EAAA,GACJ;AAER;"}
|
|
@@ -16,21 +16,25 @@ import { startDownload } from "../../downloads/downloadQueue.js";
|
|
|
16
16
|
import { useFileTypes } from "../../downloads/fileTypes.js";
|
|
17
17
|
import ConfirmDialog from "../../feedback/ConfirmDialog.js";
|
|
18
18
|
import { useConfirmAction } from "../../feedback/useConfirmAction.js";
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
19
|
+
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
20
|
+
const THEME_NAME = "CalcitaDownloadMenu";
|
|
21
|
+
const DownloadButton = piecePart(THEME_NAME, "Button", Button);
|
|
22
|
+
function DownloadMenu(props) {
|
|
23
|
+
const {
|
|
24
|
+
formats,
|
|
25
|
+
download,
|
|
26
|
+
label,
|
|
27
|
+
downloadLabel,
|
|
28
|
+
disabled = false,
|
|
29
|
+
confirmation,
|
|
30
|
+
onDownloaded,
|
|
31
|
+
onFailed,
|
|
32
|
+
onCanceled,
|
|
33
|
+
variant = "button",
|
|
34
|
+
ariaLabel,
|
|
35
|
+
onChooseFormat,
|
|
36
|
+
icon: ButtonIcon = FileDownloadOutlinedIcon
|
|
37
|
+
} = usePieceProps(props, THEME_NAME);
|
|
34
38
|
const { t } = useToolkitTranslation("common");
|
|
35
39
|
const fileTypes = useFileTypes();
|
|
36
40
|
const [anchorElement, setAnchorElement] = useState(null);
|
|
@@ -106,12 +110,12 @@ function DownloadMenu({
|
|
|
106
110
|
}
|
|
107
111
|
) }) })
|
|
108
112
|
) : /* @__PURE__ */ jsx(
|
|
109
|
-
|
|
113
|
+
DownloadButton,
|
|
110
114
|
{
|
|
111
115
|
variant: "outlined",
|
|
112
116
|
startIcon: /* @__PURE__ */ jsx(ButtonIcon, {}),
|
|
113
117
|
endIcon: /* @__PURE__ */ jsx(ArrowDropDownIcon, {}),
|
|
114
|
-
|
|
118
|
+
ownSx: { flexShrink: 0 },
|
|
115
119
|
disabled,
|
|
116
120
|
"aria-haspopup": "menu",
|
|
117
121
|
onClick: openMenu,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DownloadMenu.js","sources":["../../../src/ui/actions/DownloadMenu.jsx"],"sourcesContent":["// \"Descargar ▾\" con los formatos de un reporte: PDF para leer o archivar, Excel o CSV para trabajar.\n//\n// Un solo botón y no tres: en la barra de una pantalla tres botones de descarga compiten con la acción principal.\n// Se acomoda a donde quedó, como BarActionButton: en una cápsula de la barra (las `actions` de PageHeading con cápsulas)\n// es solo el ícono con su nombre en el tooltip, como las demás acciones; antes salía la píldora «Descargar ▾» dentro de\n// la cápsula y se veía una cápsula dentro de otra. En el «⋯» del teléfono es un renglón que abre los formatos.\n// Quien llama pasa QUÉ descargar por formato (download(format, transferOptions) → {blob, fileName}, la forma de\n// un cliente HTTP que descarga). La descarga va al panel de descargas (startDownload, downloads): el diálogo se cierra al\n// confirmar y el avance, el aviso de \"descargado\" y el error se ven allá, mientras la persona sigue trabajando.\n//\n// Regla de tablas: una descarga pasa por un diálogo de confirmación que dice qué se va a bajar (p. ej. que la base\n// completa de clientes tarda unos minutos). Con `confirmation` el formato elegido NO se descarga de inmediato: abre\n// ConfirmDialog (máquina confirmActionMachine) y solo al confirmar se pide el archivo, una sola vez aunque haya doble clic.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Button from '@mui/material/Button';\nimport IconButton from '@mui/material/IconButton';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport Menu from '@mui/material/Menu';\nimport MenuItem from '@mui/material/MenuItem';\nimport Tooltip from '@mui/material/Tooltip';\nimport ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';\nimport FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';\n\nimport {BAR_ACTIONS_PLACEMENT, useBarActionsPlacement, useCloseBarActionsMenu} from '@/appShell/barActionsSlot.js';\nimport {startDownload} from '@/downloads/downloadQueue.js';\nimport {useFileTypes} from '@/downloads/fileTypes.js';\nimport ConfirmDialog from '@/feedback/ConfirmDialog.jsx';\nimport {useConfirmAction} from '@/feedback/useConfirmAction.js';\n\n\n/**\n * @param {object} props\n * @param {string[]} props.formats los tipos de archivo, en orden: los de la casa (xlsx, csv, pdf) y los que el proyecto declare\n * en ToolkitProvider fileTypes (zip, xml…)\n * @param {(format: string, transferOptions: {signal: AbortSignal, onDownloadProgress: (progress: {loaded: number, total?: number|null}) => void}) => Promise<{blob: Blob, fileName: string}>} props.download\n * @param {string} [props.label] ya traducido; por defecto \"Descargar\"\n * @param {string} [props.downloadLabel] ya traducido; lo que se ve en el panel de descargas antes de saber el nombre\n * del archivo\n * @param {boolean} [props.disabled]\n * @param {(format: string) => {title: string, description: import('react').ReactNode, confirmLabel?: string}} [props.confirmation]\n * @param {(format: string) => void} [props.onDownloaded] p. ej. volver a pedir la tabla (si la descarga cambia algo en\n * el servidor)\n * @param {(format: string, error: unknown) => void} [props.onFailed] cuando la descarga no se pudo (el panel ya lo dice)\n * @param {(format: string) => void} [props.onCanceled] cuando la persona la canceló desde el panel\n * @param {'button'|'icon'} [props.variant] icon = solo el icono (columna de acciones de una tabla)\n * @param {string} [props.ariaLabel] ya traducido; obligatorio en la variante icon\n * @param {(format: string) => void} [props.onChooseFormat] quien llama se encarga de confirmar y descargar\n * @param {import('react').ElementType} [props.icon] ícono del botón; por defecto el de descarga. Distingue dos descargas en la\n * misma fila\n *\n * IMPORTANTE: hay que pasar `confirmation` u `onChooseFormat`. Sin ninguno de los dos el menú no descarga nada (regla de\n * tablas: toda descarga pasa por confirmación).\n *\n * OJO onChooseFormat: dentro de una celda del DataGrid el diálogo de confirmación NO puede vivir en la celda (el grid\n * virtualiza y vuelve a pintar sus celdas; el diálogo se perdía al elegir el formato). Ahí el menú solo avisa qué formato\n * se eligió y la pantalla abre SU confirmación (useConfirmAction) fuera de la tabla.\n */\nexport default function DownloadMenu({\n formats, download, label, downloadLabel, disabled = false, confirmation, onDownloaded, onFailed, onCanceled, variant = 'button', ariaLabel,\n onChooseFormat, icon: ButtonIcon = FileDownloadOutlinedIcon,\n}) {\n const {t} = useToolkitTranslation('common');\n const fileTypes = useFileTypes();\n // de dónde sale el menú de formatos: del botón, o (desde el «⋯» del teléfono, que se cierra) de donde estaba el renglón\n const [anchorElement, setAnchorElement] = useState(null);\n const [anchorPosition, setAnchorPosition] = useState(null);\n const placement = useBarActionsPlacement();\n const closeMoreMenu = useCloseBarActionsMenu();\n const closeFormats = () => {\n setAnchorElement(null);\n setAnchorPosition(null);\n };\n\n // no se espera a que termine: la descarga sigue en el panel y el diálogo de confirmación se cierra de inmediato\n const runDownload = (format) => {\n startDownload({\n label: downloadLabel ?? label ?? ariaLabel ?? t('actions.download'),\n format,\n request: (transferOptions) => download(format, transferOptions),\n onCompleted: () => onDownloaded?.(format),\n onFailed: (error) => onFailed?.(format, error),\n onCanceled: () => onCanceled?.(format),\n });\n };\n\n const confirmedDownload = useConfirmAction({run: ({subject}) => runDownload(subject.format)});\n\n const chooseFormat = (format) => {\n closeFormats();\n if (onChooseFormat) {\n onChooseFormat(format);\n return;\n }\n if (confirmation) {\n confirmedDownload.open({format});\n return;\n }\n // Regla de tablas: nada se descarga con un solo clic. Sin confirmation ni onChooseFormat es un error de quien\n // llama, no un camino válido: lo decimos en la consola y no descargamos\n console.error('DownloadMenu: falta confirmation u onChooseFormat; toda descarga pasa por un diálogo de confirmación');\n };\n\n const buttonLabel = label ?? t('actions.download');\n const openMenu = (event) => setAnchorElement(event.currentTarget);\n // desde el «⋯»: se cierra ese menú y los formatos salen donde estaba el renglón\n const openFromMoreMenu = (event) => {\n const {bottom, right} = event.currentTarget.getBoundingClientRect();\n closeMoreMenu();\n setAnchorPosition({top: bottom, left: right});\n };\n const isFormatsOpen = Boolean(anchorElement || anchorPosition);\n const confirmationTexts = confirmedDownload.subject ? confirmation?.(confirmedDownload.subject.format) : null;\n\n return (\n <>\n {placement === BAR_ACTIONS_PLACEMENT.menu && (\n <MenuItem disabled={disabled} aria-haspopup=\"menu\" onClick={openFromMoreMenu}>\n <ListItemIcon><ButtonIcon /></ListItemIcon>\n <ListItemText>{buttonLabel}</ListItemText>\n </MenuItem>\n )}\n {placement === BAR_ACTIONS_PLACEMENT.capsule && (\n // en la cápsula, del tamaño y color de las demás acciones (BarActionButton)\n <Tooltip title={buttonLabel} describeChild>\n <span>\n <IconButton color=\"primary\" aria-label={buttonLabel} aria-haspopup=\"menu\" aria-expanded={isFormatsOpen}\n disabled={disabled} onClick={openMenu}>\n <ButtonIcon />\n </IconButton>\n </span>\n </Tooltip>\n )}\n {placement === BAR_ACTIONS_PLACEMENT.inline && (variant === 'icon' ? (\n // describeChild: el nombre accesible ya lo trae el botón; sin esto el Tooltip le pone el mismo aria-label al\n // span y un lector de pantalla (o una prueba) encuentra dos \"botones\" con el mismo nombre\n <Tooltip title={ariaLabel ?? buttonLabel} describeChild>\n {/* el span deja que el tooltip funcione con el botón inhabilitado */}\n <span>\n <IconButton size=\"small\" aria-label={ariaLabel ?? buttonLabel} aria-haspopup=\"menu\"\n disabled={disabled} onClick={openMenu}>\n <ButtonIcon fontSize=\"small\" />\n </IconButton>\n </span>\n </Tooltip>\n ) : (\n <Button variant=\"outlined\" startIcon={<ButtonIcon />} endIcon={<ArrowDropDownIcon />}\n sx={{flexShrink: 0}} disabled={disabled} aria-haspopup=\"menu\" onClick={openMenu}>\n {buttonLabel}\n </Button>\n ))}\n <Menu open={isFormatsOpen} onClose={closeFormats}\n anchorReference={anchorPosition ? 'anchorPosition' : 'anchorEl'} anchorEl={anchorElement} anchorPosition={anchorPosition ?? undefined}\n anchorOrigin={{vertical: 'bottom', horizontal: 'right'}} transformOrigin={{vertical: 'top', horizontal: 'right'}}>\n {formats.map((format) => {\n const fileType = fileTypes[format];\n const Icon = fileType?.Icon ?? FileDownloadOutlinedIcon;\n return (\n <MenuItem key={format} onClick={() => chooseFormat(format)}>\n <ListItemIcon><Icon fontSize=\"small\" /></ListItemIcon>\n {/* los de la casa con sus textos; los del proyecto con su label y hint (o esas llaves en sus texts) */}\n <ListItemText primary={t(`download.formats.${format}.label`, {defaultValue: fileType?.label ?? format.toUpperCase()})}\n secondary={t(`download.formats.${format}.hint`, {defaultValue: fileType?.hint ?? ''})}\n slotProps={{secondary: {variant: 'caption'}}} />\n </MenuItem>\n );\n })}\n </Menu>\n {confirmation && (\n <ConfirmDialog\n {...confirmedDownload.dialogProps}\n title={confirmationTexts?.title ?? ''}\n description={confirmationTexts?.description}\n confirmLabel={confirmationTexts?.confirmLabel ?? t('actions.download')}\n />\n )}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DownloadMenu.js","sources":["../../../src/ui/actions/DownloadMenu.jsx"],"sourcesContent":["// \"Descargar ▾\" con los formatos de un reporte: PDF para leer o archivar, Excel o CSV para trabajar.\n//\n// Un solo botón y no tres: en la barra de una pantalla tres botones de descarga compiten con la acción principal.\n// Se acomoda a donde quedó, como BarActionButton: en una cápsula de la barra (las `actions` de PageHeading con cápsulas)\n// es solo el ícono con su nombre en el tooltip, como las demás acciones; antes salía la píldora «Descargar ▾» dentro de\n// la cápsula y se veía una cápsula dentro de otra. En el «⋯» del teléfono es un renglón que abre los formatos.\n// Quien llama pasa QUÉ descargar por formato (download(format, transferOptions) → {blob, fileName}, la forma de\n// un cliente HTTP que descarga). La descarga va al panel de descargas (startDownload, downloads): el diálogo se cierra al\n// confirmar y el avance, el aviso de \"descargado\" y el error se ven allá, mientras la persona sigue trabajando.\n//\n// Regla de tablas: una descarga pasa por un diálogo de confirmación que dice qué se va a bajar (p. ej. que la base\n// completa de clientes tarda unos minutos). Con `confirmation` el formato elegido NO se descarga de inmediato: abre\n// ConfirmDialog (máquina confirmActionMachine) y solo al confirmar se pide el archivo, una sola vez aunque haya doble clic.\n//\n// Se cambia desde el tema del proyecto, como las piezas de MUI: components.CalcitaDownloadMenu con defaultProps y\n// styleOverrides de sus partes: button.\n//\n// Genérico del paquete: function (regla de la casa).\nimport {useState} from 'react';\nimport {useToolkitTranslation} from '@/toolkit/useToolkitTranslation.js';\nimport Button from '@mui/material/Button';\nimport IconButton from '@mui/material/IconButton';\nimport ListItemIcon from '@mui/material/ListItemIcon';\nimport ListItemText from '@mui/material/ListItemText';\nimport Menu from '@mui/material/Menu';\nimport MenuItem from '@mui/material/MenuItem';\nimport Tooltip from '@mui/material/Tooltip';\nimport ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';\nimport FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';\n\nimport {BAR_ACTIONS_PLACEMENT, useBarActionsPlacement, useCloseBarActionsMenu} from '@/appShell/barActionsSlot.js';\nimport {startDownload} from '@/downloads/downloadQueue.js';\nimport {useFileTypes} from '@/downloads/fileTypes.js';\nimport ConfirmDialog from '@/feedback/ConfirmDialog.jsx';\nimport {useConfirmAction} from '@/feedback/useConfirmAction.js';\nimport {piecePart, usePieceProps} from '@/theme/themePieces.js';\n\n// el nombre de la pieza en el tema y sus partes (theme.components.CalcitaDownloadMenu)\nconst THEME_NAME = 'CalcitaDownloadMenu';\nconst DownloadButton = piecePart(THEME_NAME, 'Button', Button);\n\n\n/**\n * @param {object} props\n * @param {string[]} props.formats los tipos de archivo, en orden: los de la casa (xlsx, csv, pdf) y los que el proyecto declare\n * en ToolkitProvider fileTypes (zip, xml…)\n * @param {(format: string, transferOptions: {signal: AbortSignal, onDownloadProgress: (progress: {loaded: number, total?: number|null}) => void}) => Promise<{blob: Blob, fileName: string}>} props.download\n * @param {string} [props.label] ya traducido; por defecto \"Descargar\"\n * @param {string} [props.downloadLabel] ya traducido; lo que se ve en el panel de descargas antes de saber el nombre\n * del archivo\n * @param {boolean} [props.disabled]\n * @param {(format: string) => {title: string, description: import('react').ReactNode, confirmLabel?: string}} [props.confirmation]\n * @param {(format: string) => void} [props.onDownloaded] p. ej. volver a pedir la tabla (si la descarga cambia algo en\n * el servidor)\n * @param {(format: string, error: unknown) => void} [props.onFailed] cuando la descarga no se pudo (el panel ya lo dice)\n * @param {(format: string) => void} [props.onCanceled] cuando la persona la canceló desde el panel\n * @param {'button'|'icon'} [props.variant] icon = solo el icono (columna de acciones de una tabla)\n * @param {string} [props.ariaLabel] ya traducido; obligatorio en la variante icon\n * @param {(format: string) => void} [props.onChooseFormat] quien llama se encarga de confirmar y descargar\n * @param {import('react').ElementType} [props.icon] ícono del botón; por defecto el de descarga. Distingue dos descargas en la\n * misma fila\n *\n * IMPORTANTE: hay que pasar `confirmation` u `onChooseFormat`. Sin ninguno de los dos el menú no descarga nada (regla de\n * tablas: toda descarga pasa por confirmación).\n *\n * OJO onChooseFormat: dentro de una celda del DataGrid el diálogo de confirmación NO puede vivir en la celda (el grid\n * virtualiza y vuelve a pintar sus celdas; el diálogo se perdía al elegir el formato). Ahí el menú solo avisa qué formato\n * se eligió y la pantalla abre SU confirmación (useConfirmAction) fuera de la tabla.\n */\nexport default function DownloadMenu(props) {\n // lo que el proyecto puso en su tema (components.CalcitaDownloadMenu.defaultProps) y encima lo que llega aquí\n const {\n formats, download, label, downloadLabel, disabled = false, confirmation, onDownloaded, onFailed, onCanceled, variant = 'button', ariaLabel,\n onChooseFormat, icon: ButtonIcon = FileDownloadOutlinedIcon,\n} = usePieceProps(props, THEME_NAME);\n const {t} = useToolkitTranslation('common');\n const fileTypes = useFileTypes();\n // de dónde sale el menú de formatos: del botón, o (desde el «⋯» del teléfono, que se cierra) de donde estaba el renglón\n const [anchorElement, setAnchorElement] = useState(null);\n const [anchorPosition, setAnchorPosition] = useState(null);\n const placement = useBarActionsPlacement();\n const closeMoreMenu = useCloseBarActionsMenu();\n const closeFormats = () => {\n setAnchorElement(null);\n setAnchorPosition(null);\n };\n\n // no se espera a que termine: la descarga sigue en el panel y el diálogo de confirmación se cierra de inmediato\n const runDownload = (format) => {\n startDownload({\n label: downloadLabel ?? label ?? ariaLabel ?? t('actions.download'),\n format,\n request: (transferOptions) => download(format, transferOptions),\n onCompleted: () => onDownloaded?.(format),\n onFailed: (error) => onFailed?.(format, error),\n onCanceled: () => onCanceled?.(format),\n });\n };\n\n const confirmedDownload = useConfirmAction({run: ({subject}) => runDownload(subject.format)});\n\n const chooseFormat = (format) => {\n closeFormats();\n if (onChooseFormat) {\n onChooseFormat(format);\n return;\n }\n if (confirmation) {\n confirmedDownload.open({format});\n return;\n }\n // Regla de tablas: nada se descarga con un solo clic. Sin confirmation ni onChooseFormat es un error de quien\n // llama, no un camino válido: lo decimos en la consola y no descargamos\n console.error('DownloadMenu: falta confirmation u onChooseFormat; toda descarga pasa por un diálogo de confirmación');\n };\n\n const buttonLabel = label ?? t('actions.download');\n const openMenu = (event) => setAnchorElement(event.currentTarget);\n // desde el «⋯»: se cierra ese menú y los formatos salen donde estaba el renglón\n const openFromMoreMenu = (event) => {\n const {bottom, right} = event.currentTarget.getBoundingClientRect();\n closeMoreMenu();\n setAnchorPosition({top: bottom, left: right});\n };\n const isFormatsOpen = Boolean(anchorElement || anchorPosition);\n const confirmationTexts = confirmedDownload.subject ? confirmation?.(confirmedDownload.subject.format) : null;\n\n return (\n <>\n {placement === BAR_ACTIONS_PLACEMENT.menu && (\n <MenuItem disabled={disabled} aria-haspopup=\"menu\" onClick={openFromMoreMenu}>\n <ListItemIcon><ButtonIcon /></ListItemIcon>\n <ListItemText>{buttonLabel}</ListItemText>\n </MenuItem>\n )}\n {placement === BAR_ACTIONS_PLACEMENT.capsule && (\n // en la cápsula, del tamaño y color de las demás acciones (BarActionButton)\n <Tooltip title={buttonLabel} describeChild>\n <span>\n <IconButton color=\"primary\" aria-label={buttonLabel} aria-haspopup=\"menu\" aria-expanded={isFormatsOpen}\n disabled={disabled} onClick={openMenu}>\n <ButtonIcon />\n </IconButton>\n </span>\n </Tooltip>\n )}\n {placement === BAR_ACTIONS_PLACEMENT.inline && (variant === 'icon' ? (\n // describeChild: el nombre accesible ya lo trae el botón; sin esto el Tooltip le pone el mismo aria-label al\n // span y un lector de pantalla (o una prueba) encuentra dos \"botones\" con el mismo nombre\n <Tooltip title={ariaLabel ?? buttonLabel} describeChild>\n {/* el span deja que el tooltip funcione con el botón inhabilitado */}\n <span>\n <IconButton size=\"small\" aria-label={ariaLabel ?? buttonLabel} aria-haspopup=\"menu\"\n disabled={disabled} onClick={openMenu}>\n <ButtonIcon fontSize=\"small\" />\n </IconButton>\n </span>\n </Tooltip>\n ) : (\n <DownloadButton variant=\"outlined\" startIcon={<ButtonIcon />} endIcon={<ArrowDropDownIcon />}\n ownSx={{flexShrink: 0}} disabled={disabled} aria-haspopup=\"menu\" onClick={openMenu}>\n {buttonLabel}\n </DownloadButton>\n ))}\n <Menu open={isFormatsOpen} onClose={closeFormats}\n anchorReference={anchorPosition ? 'anchorPosition' : 'anchorEl'} anchorEl={anchorElement} anchorPosition={anchorPosition ?? undefined}\n anchorOrigin={{vertical: 'bottom', horizontal: 'right'}} transformOrigin={{vertical: 'top', horizontal: 'right'}}>\n {formats.map((format) => {\n const fileType = fileTypes[format];\n const Icon = fileType?.Icon ?? FileDownloadOutlinedIcon;\n return (\n <MenuItem key={format} onClick={() => chooseFormat(format)}>\n <ListItemIcon><Icon fontSize=\"small\" /></ListItemIcon>\n {/* los de la casa con sus textos; los del proyecto con su label y hint (o esas llaves en sus texts) */}\n <ListItemText primary={t(`download.formats.${format}.label`, {defaultValue: fileType?.label ?? format.toUpperCase()})}\n secondary={t(`download.formats.${format}.hint`, {defaultValue: fileType?.hint ?? ''})}\n slotProps={{secondary: {variant: 'caption'}}} />\n </MenuItem>\n );\n })}\n </Menu>\n {confirmation && (\n <ConfirmDialog\n {...confirmedDownload.dialogProps}\n title={confirmationTexts?.title ?? ''}\n description={confirmationTexts?.description}\n confirmLabel={confirmationTexts?.confirmLabel ?? t('actions.download')}\n />\n )}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,13 @@ import { usesMobileTabBar } from "../../appShell/tabBarRule.js";
|
|
|
18
18
|
import { minimalFloatingStylesOf } from "../../theme/components/minimalComponents.js";
|
|
19
19
|
import { isGlassTheme, glassStylesOf } from "../../theme/glassSurface.js";
|
|
20
20
|
import { useToolkitTranslation } from "../../toolkit/useToolkitTranslation.js";
|
|
21
|
+
import { piecePart, usePieceProps } from "../../theme/themePieces.js";
|
|
22
|
+
const THEME_NAME = "CalcitaSelectionActions";
|
|
23
|
+
const SelectionBar = piecePart(THEME_NAME, "Bar", Stack);
|
|
24
|
+
const SelectionCount = piecePart(THEME_NAME, "Count", Typography);
|
|
25
|
+
const SelectionClear = piecePart(THEME_NAME, "Clear", Button);
|
|
26
|
+
const SelectionPhoneCount = piecePart(THEME_NAME, "PhoneCount", Typography);
|
|
27
|
+
const SelectionPhoneActions = piecePart(THEME_NAME, "PhoneActions", Box);
|
|
21
28
|
const SELECTION_PHONE_LAYOUT = Object.freeze({ top: "top", split: "split" });
|
|
22
29
|
const FLOATING_GAP_PIXELS = 8;
|
|
23
30
|
const FLOATING_BOTTOM_SPACE_PIXELS = 64;
|
|
@@ -41,7 +48,8 @@ function bottomCapsuleSxOf(theme) {
|
|
|
41
48
|
...aboveMobileTabBarOf(FLOATING_GAP_PIXELS)
|
|
42
49
|
};
|
|
43
50
|
}
|
|
44
|
-
function SelectionActions(
|
|
51
|
+
function SelectionActions(props) {
|
|
52
|
+
const { countText, actions = [], onClear, phoneLayout = SELECTION_PHONE_LAYOUT.top, texts, sx } = usePieceProps(props, THEME_NAME);
|
|
45
53
|
const theme = useTheme();
|
|
46
54
|
const { t } = useToolkitTranslation("common", texts);
|
|
47
55
|
const [runningActionKey, setRunningActionKey] = useState(null);
|
|
@@ -58,20 +66,20 @@ function SelectionActions({ countText, actions = [], onClear, phoneLayout = SELE
|
|
|
58
66
|
const isDisabledOf = (action) => runningActionKey !== null || Boolean(action.disabled);
|
|
59
67
|
const clearButton = /* @__PURE__ */ jsx(Tooltip, { title: t("selection.clear"), children: /* @__PURE__ */ jsx(IconButton, { "aria-label": t("selection.clear"), onClick: onClear, children: /* @__PURE__ */ jsx(CloseRoundedIcon, {}) }) });
|
|
60
68
|
const row = /* @__PURE__ */ jsxs(
|
|
61
|
-
|
|
69
|
+
SelectionBar,
|
|
62
70
|
{
|
|
63
71
|
role: "toolbar",
|
|
64
72
|
"aria-label": t("selection.actionsLabel"),
|
|
65
73
|
direction: "row",
|
|
66
74
|
spacing: 1,
|
|
67
75
|
useFlexGap: true,
|
|
68
|
-
|
|
76
|
+
ownSx: [
|
|
69
77
|
{ flexGrow: 1, alignItems: "center", flexWrap: "wrap", minHeight: 32 },
|
|
70
78
|
floatsOnPhone && { [PHONE_MEDIA_QUERY]: { display: "none" } },
|
|
71
79
|
...extraSx
|
|
72
80
|
],
|
|
73
81
|
children: [
|
|
74
|
-
/* @__PURE__ */ jsx(
|
|
82
|
+
/* @__PURE__ */ jsx(SelectionCount, { variant: "body2", ownSx: { fontWeight: 600, mr: 1 }, children: countText }),
|
|
75
83
|
actions.map((action) => /* @__PURE__ */ jsx(
|
|
76
84
|
Button,
|
|
77
85
|
{
|
|
@@ -84,7 +92,7 @@ function SelectionActions({ countText, actions = [], onClear, phoneLayout = SELE
|
|
|
84
92
|
},
|
|
85
93
|
action.key
|
|
86
94
|
)),
|
|
87
|
-
/* @__PURE__ */ jsx(
|
|
95
|
+
/* @__PURE__ */ jsx(SelectionClear, { size: "small", color: "inherit", startIcon: /* @__PURE__ */ jsx(CloseRoundedIcon, {}), onClick: onClear, ownSx: { ml: "auto" }, children: t("selection.clear") })
|
|
88
96
|
]
|
|
89
97
|
}
|
|
90
98
|
);
|
|
@@ -95,7 +103,7 @@ function SelectionActions({ countText, actions = [], onClear, phoneLayout = SELE
|
|
|
95
103
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
96
104
|
row,
|
|
97
105
|
/* @__PURE__ */ jsx(BarActions, { bare: true, exclusive: true, order: -2, sx: PHONE_ONLY_SX, inlineSx: PHONE_ONLY_SX, children: /* @__PURE__ */ jsxs(BarCapsule, { "aria-label": t("selection.summaryLabel"), sx: { pl: 2 }, children: [
|
|
98
|
-
/* @__PURE__ */ jsx(
|
|
106
|
+
/* @__PURE__ */ jsx(SelectionPhoneCount, { variant: "body2", role: "status", "aria-live": "polite", ownSx: { fontWeight: 600, whiteSpace: "nowrap", mr: 0.5 }, children: countText }),
|
|
99
107
|
clearButton
|
|
100
108
|
] }) }),
|
|
101
109
|
phoneLayout === SELECTION_PHONE_LAYOUT.top && actions.length > 0 && /* @__PURE__ */ jsx(BarActions, { label: t("selection.actionsLabel"), exclusive: true, order: -1, sx: PHONE_ONLY_SX, inlineSx: PHONE_ONLY_SX, children: actions.map((action) => /* @__PURE__ */ jsx(
|
|
@@ -111,7 +119,7 @@ function SelectionActions({ countText, actions = [], onClear, phoneLayout = SELE
|
|
|
111
119
|
)) }),
|
|
112
120
|
showsBottomCapsule && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
113
121
|
/* @__PURE__ */ jsx(GlobalStyles, { styles: { ":root": { [FLOATING_BOTTOM_SPACE_CSS_VARIABLE]: `${FLOATING_BOTTOM_SPACE_PIXELS}px` } } }),
|
|
114
|
-
/* @__PURE__ */ jsx(
|
|
122
|
+
/* @__PURE__ */ jsx(SelectionPhoneActions, { role: "toolbar", "aria-label": t("selection.actionsLabel"), ownSx: [bottomCapsuleSxOf, PHONE_ONLY_SX], children: actions.map((action) => action.icon ? /* @__PURE__ */ jsx(Tooltip, { title: action.label, children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(
|
|
115
123
|
IconButton,
|
|
116
124
|
{
|
|
117
125
|
"aria-label": action.label,
|