@m4l/components 9.3.21 → 9.3.22-JT22102025.beta.1

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.
Files changed (94) hide show
  1. package/components/DataGrid/DataGrid.js +9 -4
  2. package/components/DataGrid/Datagrid.styles.js +270 -0
  3. package/components/DataGrid/constants.js +2 -2
  4. package/components/DataGrid/contexts/DataGridContext/index.js +322 -112
  5. package/components/DataGrid/contexts/DataGridContext/types.d.ts +63 -4
  6. package/components/DataGrid/dictionary.d.ts +5 -0
  7. package/components/DataGrid/dictionary.js +6 -1
  8. package/components/DataGrid/formatters/ColumnSetCheckFormatter/formatter.js +2 -2
  9. package/components/DataGrid/hooks/useModalCardDetail.d.ts +6 -0
  10. package/components/DataGrid/hooks/useModalCardDetail.js +74 -0
  11. package/components/DataGrid/hooks/useProcessedColumns.d.ts +50 -0
  12. package/components/DataGrid/hooks/useProcessedColumns.js +44 -0
  13. package/components/DataGrid/icons.d.ts +7 -0
  14. package/components/DataGrid/icons.js +5 -1
  15. package/components/DataGrid/index.d.ts +1 -1
  16. package/components/DataGrid/slots/DataGridEnum.d.ts +22 -1
  17. package/components/DataGrid/slots/DataGridEnum.js +21 -0
  18. package/components/DataGrid/slots/DataGridSlot.d.ts +24 -0
  19. package/components/DataGrid/slots/DataGridSlot.js +123 -21
  20. package/components/DataGrid/subcomponents/Cards/hooks/useCardContent.d.ts +9 -0
  21. package/components/DataGrid/subcomponents/Cards/hooks/useCardContent.js +91 -0
  22. package/components/DataGrid/subcomponents/Cards/index.d.ts +5 -0
  23. package/components/DataGrid/subcomponents/Cards/index.js +40 -0
  24. package/components/DataGrid/subcomponents/Cards/subcomponents/CardDetails/index.d.ts +8 -0
  25. package/components/DataGrid/subcomponents/Cards/subcomponents/CardDetails/index.js +79 -0
  26. package/components/DataGrid/subcomponents/Cards/subcomponents/CardHeader/index.d.ts +7 -0
  27. package/components/DataGrid/subcomponents/Cards/subcomponents/CardHeader/index.js +98 -0
  28. package/components/DataGrid/subcomponents/Cards/subcomponents/CardRow/index.d.ts +6 -0
  29. package/components/DataGrid/subcomponents/Cards/subcomponents/CardRow/index.js +71 -0
  30. package/components/DataGrid/subcomponents/Cards/subcomponents/IntersectCard/index.d.ts +20 -0
  31. package/components/DataGrid/subcomponents/Cards/subcomponents/IntersectCard/index.js +46 -0
  32. package/components/DataGrid/subcomponents/Cards/subcomponents/LazyLoadCard/index.d.ts +17 -0
  33. package/components/DataGrid/subcomponents/Cards/subcomponents/LazyLoadCard/index.js +34 -0
  34. package/components/DataGrid/subcomponents/Cards/types.d.ts +118 -0
  35. package/components/DataGrid/subcomponents/CheckboxCellAdapter/index.d.ts +7 -0
  36. package/components/DataGrid/subcomponents/CheckboxCellAdapter/index.js +43 -0
  37. package/components/DataGrid/subcomponents/CheckboxCellAdapter/types.d.ts +7 -0
  38. package/components/DataGrid/subcomponents/ControlNavigate/ControlNavigate.js +1 -1
  39. package/components/DataGrid/subcomponents/HeaderActions/index.js +5 -3
  40. package/components/DataGrid/subcomponents/HeaderActions/subcomponents/RowsCount/index.js +1 -1
  41. package/components/DataGrid/subcomponents/HeaderActions/subcomponents/Settings/index.js +11 -2
  42. package/components/DataGrid/subcomponents/HeaderActions/subcomponents/Settings/subcomponents/ColumnsConfig/index.js +1 -1
  43. package/components/DataGrid/subcomponents/HeaderActions/subcomponents/Settings/subcomponents/ColumnsConfigCards/index.d.ts +2 -0
  44. package/components/DataGrid/subcomponents/HeaderActions/subcomponents/Settings/subcomponents/ColumnsConfigCards/index.js +304 -0
  45. package/components/DataGrid/subcomponents/HeaderActions/subcomponents/Settings/subcomponents/ColumnsConfigCards/types.d.ts +31 -0
  46. package/components/DataGrid/subcomponents/HeaderActions/subcomponents/ViewMode/index.d.ts +4 -0
  47. package/components/DataGrid/subcomponents/HeaderActions/subcomponents/ViewMode/index.js +125 -0
  48. package/components/DataGrid/subcomponents/HeaderActions/subcomponents/hooks/useModalSettings/index.js +2 -2
  49. package/components/DataGrid/subcomponents/HeaderActions/subcomponents/hooks/useModalSettingsCards/index.d.ts +7 -0
  50. package/components/DataGrid/subcomponents/HeaderActions/subcomponents/hooks/useModalSettingsCards/index.js +74 -0
  51. package/components/DataGrid/subcomponents/HeaderActions/subcomponents/hooks/useModalSettingsCards/types.d.ts +4 -0
  52. package/components/DataGrid/subcomponents/RenderContent/index.d.ts +5 -0
  53. package/components/DataGrid/subcomponents/RenderContent/index.js +11 -0
  54. package/components/DataGrid/subcomponents/Table/hooks/useHeaderMenuActions.js +2 -2
  55. package/components/DataGrid/subcomponents/Table/hooks/useSortColumnsRows.js +1 -1
  56. package/components/DataGrid/subcomponents/Table/index.js +1 -1
  57. package/components/DataGrid/subcomponents/Table/subcomponents/ActionsColumn.js +1 -1
  58. package/components/DataGrid/subcomponents/Table/subcomponents/DraggableHeaderRenderer.js +1 -1
  59. package/components/DataGrid/subcomponents/Table/subcomponents/HeaderRenderClick/HeaderRenderClick.js +1 -1
  60. package/components/DataGrid/subcomponents/editors/TextEditor/index.js +1 -1
  61. package/components/DataGrid/tests/components/CardDetails.test.d.ts +1 -0
  62. package/components/DataGrid/tests/components/CardHeader.test.d.ts +1 -0
  63. package/components/DataGrid/tests/components/CardRow.test.d.ts +1 -0
  64. package/components/DataGrid/tests/components/Cards.test.d.ts +1 -0
  65. package/components/DataGrid/tests/components/CheckboxCellAdapter.test.d.ts +1 -0
  66. package/components/DataGrid/tests/components/ColumnsConfigCards.test.d.ts +1 -0
  67. package/components/DataGrid/tests/components/IntersectCard.test.d.ts +1 -0
  68. package/components/DataGrid/tests/components/ViewMode.test.d.ts +1 -0
  69. package/components/DataGrid/tests/helpers/types.d.ts +1 -0
  70. package/components/DataGrid/tests/helpers/useCardsViewConfig.d.ts +24 -0
  71. package/components/DataGrid/tests/helpers/useCustomCardExample.d.ts +7 -0
  72. package/components/DataGrid/tests/hooks/useCardContent.test.d.ts +1 -0
  73. package/components/DataGrid/tests/hooks/useModalDetail.test.d.ts +1 -0
  74. package/components/DataGrid/tests/hooks/useModalSettingsCards.test.d.ts +1 -0
  75. package/components/DataGrid/tests/hooks/useProcessedColumns.test.d.ts +1 -0
  76. package/components/DataGrid/types.d.ts +87 -5
  77. package/components/MFIsolationAppStorybook/MFIsolationAppStorybook.d.ts +5 -0
  78. package/components/MFIsolationAppStorybook/constants.d.ts +1 -0
  79. package/components/MFIsolationAppStorybook/icons.d.ts +3 -0
  80. package/components/MFIsolationAppStorybook/index.d.ts +1 -0
  81. package/components/MFIsolationAppStorybook/subcomponents/AppBarSettings/AppBarSettings.d.ts +4 -0
  82. package/components/MFIsolationAppStorybook/subcomponents/AppBarSettings/index.d.ts +1 -0
  83. package/components/MFIsolationAppStorybook/subcomponents/MFAuthAppStorybook/MFAuthAppStorybook.d.ts +5 -0
  84. package/components/MFIsolationAppStorybook/subcomponents/MFAuthAppStorybook/index.d.ts +1 -0
  85. package/components/MFIsolationAppStorybook/subcomponents/MFAuthAppStorybook/types.d.ts +4 -0
  86. package/components/MFIsolationAppStorybook/types.d.ts +31 -0
  87. package/components/MenuActions/MenuActions.js +105 -55
  88. package/components/areas/contexts/AreasContext/store.js +2 -2
  89. package/components/hook-form/RHFormContext/index.d.ts +1 -1
  90. package/hooks/useDataGridPersistence/helpers.d.ts +2 -2
  91. package/hooks/useDataGridPersistence/useDataGridPersistence.d.ts +2 -2
  92. package/hooks/useDataGridPersistence/useDataGridPersistence.js +5 -0
  93. package/index.js +8 -8
  94. package/package.json +1 -1
@@ -0,0 +1,8 @@
1
+ import { CardDetailsProps } from '../../types';
2
+ /**
3
+ * Componente genérico que renderiza TODAS las columnas de una fila
4
+ * en formato detalle dentro del modal.
5
+ *
6
+ * A diferencia del componente Cards, este muestra TODAS las columnas
7
+ */
8
+ export declare function CardDetails<TRow>({ row, columns, viewColumnsConfig, onRowsChange, size, }: CardDetailsProps<TRow>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,79 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { f as CardDetailContainerStyled, c as ContainerLabelValueColumnStyled, d as ContentWrapperColumnStyled, L as LabelHeaderColumnStyled, E as EditorCellWrapperStyled, V as ValueColumnStyled } from "../../../../slots/DataGridSlot.js";
4
+ function CardDetails({
5
+ row,
6
+ columns,
7
+ viewColumnsConfig,
8
+ onRowsChange,
9
+ size = "medium"
10
+ }) {
11
+ const [editingColumnKey, setEditingColumnKey] = useState(null);
12
+ return /* @__PURE__ */ jsx(CardDetailContainerStyled, { children: columns.map((column, index) => {
13
+ const configColumn = viewColumnsConfig.find(
14
+ (config) => config.key === column.key
15
+ );
16
+ const shouldShowTitle = configColumn?.showTitle !== false;
17
+ return /* @__PURE__ */ jsx(ContainerLabelValueColumnStyled, { children: /* @__PURE__ */ jsxs(
18
+ ContentWrapperColumnStyled,
19
+ {
20
+ "data-testid": `card-detail-column-${column.key}`,
21
+ onDoubleClick: column.renderEditCell && editingColumnKey !== column.key ? () => {
22
+ setEditingColumnKey(column.key);
23
+ } : void 0,
24
+ children: [
25
+ shouldShowTitle && /* @__PURE__ */ jsxs(LabelHeaderColumnStyled, { variant: "body", color: "text.secondary", children: [
26
+ column.name,
27
+ ":"
28
+ ] }),
29
+ (() => {
30
+ if (column.renderEditCell && editingColumnKey === column.key) {
31
+ return /* @__PURE__ */ jsx(EditorCellWrapperStyled, { ownerState: { size }, children: column.renderEditCell({
32
+ column,
33
+ row,
34
+ rowIdx: index,
35
+ /**
36
+ * onRowChange es una función que se ejecuta cuando el usuario edita una celda.
37
+ */
38
+ onRowChange: (updatedRow) => {
39
+ if (onRowsChange) {
40
+ onRowsChange([updatedRow], {
41
+ indexes: [index],
42
+ column
43
+ });
44
+ }
45
+ },
46
+ onClose: () => setEditingColumnKey(null)
47
+ }) });
48
+ }
49
+ if (column.renderCell) {
50
+ const cellContent = column.renderCell({
51
+ column,
52
+ row,
53
+ rowIdx: index,
54
+ isCellSelected: false,
55
+ tabIndex: -1,
56
+ /**
57
+ * onRowChange es una función que se ejecuta cuando el usuario edita una celda.
58
+ */
59
+ onRowChange: (updatedRow) => {
60
+ if (onRowsChange) {
61
+ onRowsChange([updatedRow], {
62
+ indexes: [index],
63
+ column
64
+ });
65
+ }
66
+ }
67
+ });
68
+ return /* @__PURE__ */ jsx(ValueColumnStyled, { variant: "body", color: "text.primary", children: cellContent });
69
+ }
70
+ return /* @__PURE__ */ jsx(ValueColumnStyled, { variant: "body", color: "text.primary", children: row[column.key] ?? "-" });
71
+ })()
72
+ ]
73
+ }
74
+ ) }, column.key);
75
+ }) });
76
+ }
77
+ export {
78
+ CardDetails as C
79
+ };
@@ -0,0 +1,7 @@
1
+ import { CardHeaderProps } from '../../types';
2
+ /**
3
+ * Componente CardHeader que renderiza el header de cada card con:
4
+ * - Checkbox en el lado izquierdo (solo si existen checkedRows/onCheckedRowsChange)
5
+ * - Botones de acción en el lado derecho (IconButton + MenuActions)
6
+ */
7
+ export declare function CardHeader<TRow>({ row, onOpenDetail }: CardHeaderProps<TRow>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,98 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useMemo, useCallback } from "react";
3
+ import { useEnvironment } from "@m4l/core";
4
+ import { u as useDataGrid } from "../../../../hooks/useDataGrid.js";
5
+ import { g as CardHeaderStyled, h as CardHeaderLeftStyled, i as CardHeaderRightStyled } from "../../../../slots/DataGridSlot.js";
6
+ import { p as pathIcons } from "../../../../icons.js";
7
+ import { C as CheckboxCellAdapter } from "../../../CheckboxCellAdapter/index.js";
8
+ import { I as IconButton } from "../../../../../mui_extended/IconButton/IconButton.js";
9
+ import { M as MenuActions } from "../../../../../MenuActions/MenuActions.js";
10
+ function CardHeader({ row, onOpenDetail }) {
11
+ const {
12
+ rowKeyGetter,
13
+ checkedRows,
14
+ onCheckedRowsChange,
15
+ rowActionsGetter,
16
+ size
17
+ } = useDataGrid();
18
+ const { host_static_assets, environment_assets } = useEnvironment();
19
+ const rowKey = useMemo(() => rowKeyGetter(row), [rowKeyGetter, row]);
20
+ const showCheckbox = useMemo(
21
+ () => checkedRows !== void 0 && onCheckedRowsChange !== void 0,
22
+ [checkedRows, onCheckedRowsChange]
23
+ );
24
+ const isChecked = useMemo(
25
+ () => checkedRows?.has(rowKey) || false,
26
+ [checkedRows, rowKey]
27
+ );
28
+ const onChange = useCallback(
29
+ (checked, _isShiftClick) => {
30
+ if (!onCheckedRowsChange) {
31
+ return;
32
+ }
33
+ const newCheckedRows = new Set(checkedRows);
34
+ if (checked) {
35
+ newCheckedRows.add(rowKey);
36
+ } else {
37
+ newCheckedRows.delete(rowKey);
38
+ }
39
+ onCheckedRowsChange(newCheckedRows);
40
+ },
41
+ [checkedRows, onCheckedRowsChange, rowKey]
42
+ );
43
+ const anchorOrigin = useMemo(
44
+ () => ({
45
+ vertical: "bottom",
46
+ horizontal: "right"
47
+ }),
48
+ []
49
+ );
50
+ const transformOrigin = useMemo(
51
+ () => ({
52
+ vertical: "top",
53
+ horizontal: "right"
54
+ }),
55
+ []
56
+ );
57
+ return /* @__PURE__ */ jsxs(CardHeaderStyled, { ownerState: { hasCheckedRows: showCheckbox }, children: [
58
+ showCheckbox && /* @__PURE__ */ jsx(CardHeaderLeftStyled, { children: /* @__PURE__ */ jsx(
59
+ CheckboxCellAdapter,
60
+ {
61
+ value: isChecked,
62
+ tabIndex: -1,
63
+ onChange,
64
+ "aria-label": "Select"
65
+ }
66
+ ) }),
67
+ /* @__PURE__ */ jsxs(CardHeaderRightStyled, { children: [
68
+ /* @__PURE__ */ jsx(
69
+ IconButton,
70
+ {
71
+ icon: `${host_static_assets}/${environment_assets}/${pathIcons.expanded}`,
72
+ size,
73
+ variant: "text",
74
+ "data-testid": `card-details-button-${rowKey}`,
75
+ onClick: (e) => {
76
+ e.stopPropagation();
77
+ onOpenDetail();
78
+ }
79
+ }
80
+ ),
81
+ rowActionsGetter && /* @__PURE__ */ jsx(
82
+ MenuActions,
83
+ {
84
+ arrowType: "top-left",
85
+ objItem: row,
86
+ menuActions: rowActionsGetter,
87
+ anchorOrigin,
88
+ transformOrigin,
89
+ onClick: (e) => e.stopPropagation(),
90
+ variant: "text"
91
+ }
92
+ )
93
+ ] })
94
+ ] });
95
+ }
96
+ export {
97
+ CardHeader as C
98
+ };
@@ -0,0 +1,6 @@
1
+ import { RowKey } from '../../../../types';
2
+ import { CardRowProps } from '../../types';
3
+ /**
4
+ * Componente que muestra una fila de tarjetas.
5
+ */
6
+ export declare function CardRow<TRow, TKey extends RowKey = RowKey>({ row, columns, originalColumns, rowKeyGetter, selectedRows, onSelectedRowsChange, onRowsChange, customRender, }: CardRowProps<TRow, TKey>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,71 @@
1
+ import { jsxs, Fragment, jsx } from "react/jsx-runtime";
2
+ import { useMemo } from "react";
3
+ import { j as CardStyled } from "../../../../slots/DataGridSlot.js";
4
+ import { L as LazyLoadCard } from "../LazyLoadCard/index.js";
5
+ import { u as useCardContent } from "../../hooks/useCardContent.js";
6
+ import { C as CardHeader } from "../CardHeader/index.js";
7
+ import { u as useDataGrid } from "../../../../hooks/useDataGrid.js";
8
+ function CardRow({
9
+ row,
10
+ columns,
11
+ originalColumns,
12
+ rowKeyGetter,
13
+ selectedRows,
14
+ onSelectedRowsChange,
15
+ onRowsChange,
16
+ customRender
17
+ }) {
18
+ const { checkedRows } = useDataGrid();
19
+ const hasCustomRender = customRender !== void 0;
20
+ const { cardContent, columnsCount, onOpenDetail } = useCardContent({
21
+ row,
22
+ columns,
23
+ originalColumns,
24
+ onRowsChange
25
+ });
26
+ const isChecked = useMemo(
27
+ () => checkedRows?.has(rowKeyGetter(row)) || false,
28
+ [checkedRows, rowKeyGetter, row]
29
+ );
30
+ const content = useMemo(() => {
31
+ if (hasCustomRender) {
32
+ return customRender.renderContent(row);
33
+ }
34
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
35
+ /* @__PURE__ */ jsx(CardHeader, { row, onOpenDetail }),
36
+ cardContent
37
+ ] });
38
+ }, [hasCustomRender, customRender, row, cardContent, onOpenDetail]);
39
+ const onCardClick = () => {
40
+ if (selectedRows && onSelectedRowsChange) {
41
+ if (selectedRows.has(rowKeyGetter(row))) {
42
+ return;
43
+ }
44
+ const mySet = /* @__PURE__ */ new Set([rowKeyGetter(row)]);
45
+ onSelectedRowsChange(mySet);
46
+ }
47
+ };
48
+ const dynamicMinHeight = useMemo(() => {
49
+ if (hasCustomRender) {
50
+ return customRender.minHeight;
51
+ }
52
+ return Math.max(120, columnsCount * 32 + 40);
53
+ }, [hasCustomRender, customRender, columnsCount]);
54
+ return /* @__PURE__ */ jsx(LazyLoadCard, { threshold: 200, minHeight: dynamicMinHeight, children: /* @__PURE__ */ jsx(
55
+ CardStyled,
56
+ {
57
+ variant: "outlined",
58
+ selected: selectedRows?.has(rowKeyGetter(row)),
59
+ ownerState: {
60
+ checked: isChecked,
61
+ selected: selectedRows?.has(rowKeyGetter(row))
62
+ },
63
+ onClick: onCardClick,
64
+ "data-testid": "data-grid-card",
65
+ children: content
66
+ }
67
+ ) });
68
+ }
69
+ export {
70
+ CardRow as C
71
+ };
@@ -0,0 +1,20 @@
1
+ import { IntersectCardProps } from '../../types';
2
+ /**
3
+ * Componente centinela que detecta cuando una card debe ser renderizada.
4
+ *
5
+ * Utiliza la API IntersectionObserver para detectar cuándo este componente
6
+ * entra en el viewport del usuario, momento en el cual notifica al componente
7
+ * padre para que renderice la card real en lugar del placeholder.
8
+ * @param props - Props del componente IntersectCard
9
+ * @returns Elemento span invisible que actúa como centinela
10
+ *
11
+ * Flujo de funcionamiento:
12
+ * 1. Se renderiza un span invisible en la posición de la card
13
+ * 2. El IntersectionObserver vigila este span
14
+ * 3. Cuando el span entra en el viewport (+ threshold):
15
+ * - Se ejecuta checkIntersections
16
+ * - Se llama a setIsVisible(true)
17
+ * - El componente padre reemplaza este placeholder con la card real
18
+ * 4. El observer deja de observar automáticamente el elemento
19
+ */
20
+ export declare function IntersectCard(props: IntersectCardProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,46 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useState, useRef, useEffect } from "react";
3
+ import { styled } from "@mui/material/styles";
4
+ const checkIntersections = (entries) => {
5
+ entries.forEach((entry) => {
6
+ if (entry.isIntersecting) {
7
+ entry.target?.setIsVisible(true);
8
+ }
9
+ });
10
+ };
11
+ const LAZY_LOAD_OBSERVERS = {};
12
+ const getObserver = (threshold) => {
13
+ LAZY_LOAD_OBSERVERS[threshold] = LAZY_LOAD_OBSERVERS[threshold] || new IntersectionObserver(checkIntersections, {
14
+ rootMargin: threshold + "px"
15
+ });
16
+ return LAZY_LOAD_OBSERVERS[threshold];
17
+ };
18
+ const IntersectCardStyled = styled("div")(
19
+ ({ minHeight }) => ({
20
+ minHeight: `${minHeight}px`,
21
+ width: "100%"
22
+ })
23
+ );
24
+ function IntersectCard(props) {
25
+ const { setIsVisible, threshold, minHeight = 120 } = props;
26
+ const [observer] = useState(
27
+ getObserver(threshold)
28
+ );
29
+ const intersectCardRef = useRef(null);
30
+ useEffect(() => {
31
+ const element = intersectCardRef.current;
32
+ if (observer && element) {
33
+ element.setIsVisible = setIsVisible;
34
+ observer.observe(element);
35
+ }
36
+ return () => {
37
+ if (observer && element) {
38
+ observer.unobserve(element);
39
+ }
40
+ };
41
+ }, [observer, setIsVisible]);
42
+ return /* @__PURE__ */ jsx(IntersectCardStyled, { ref: intersectCardRef, minHeight });
43
+ }
44
+ export {
45
+ IntersectCard as I
46
+ };
@@ -0,0 +1,17 @@
1
+ import { LazyLoadCardProps } from '../../types';
2
+ /**
3
+ * Componente wrapper que implementa lazy loading para cards del DataGrid.
4
+ *
5
+ * Controla cuándo renderizar el contenido real de una card basándose en
6
+ * su visibilidad en el viewport.
7
+ * @returns Contenido de la card o placeholder según su visibilidad
8
+ *
9
+ * **Cuando IntersectionObserver NO está disponible:**
10
+ * - Se renderiza inmediatamente el contenido real
11
+ *
12
+ * **Cuando IntersectionObserver SÍ está disponible:**
13
+ * - Fase 1: Renderiza IntersectCard
14
+ * - Fase 2: Cuando entra en viewport → isVisible = true
15
+ * - Fase 3: Renderiza el contenido real (children)
16
+ */
17
+ export declare function LazyLoadCard(props: LazyLoadCardProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,34 @@
1
+ import { jsx, Fragment } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { I as IntersectCard } from "../IntersectCard/index.js";
4
+ const isIntersectionObserverAvailable = () => {
5
+ return typeof window !== "undefined" && "IntersectionObserver" in window && "IntersectionObserverEntry" in window && "intersectionRatio" in window.IntersectionObserverEntry.prototype;
6
+ };
7
+ function LazyLoadCard(props) {
8
+ const {
9
+ children,
10
+ enableIntersectionObserver = true,
11
+ threshold = 100,
12
+ minHeight = 120
13
+ } = props;
14
+ const [isVisible, setIsVisible] = useState(
15
+ !(enableIntersectionObserver && isIntersectionObserverAvailable())
16
+ );
17
+ return /* @__PURE__ */ jsx(Fragment, { children: isVisible ? (
18
+ // Contenido real: se renderiza cuando es visible o cuando no se usa observer
19
+ children
20
+ ) : (
21
+ // Placeholder: elemento centinela que detecta cuándo debe cargar el contenido
22
+ /* @__PURE__ */ jsx(
23
+ IntersectCard,
24
+ {
25
+ setIsVisible,
26
+ threshold,
27
+ minHeight
28
+ }
29
+ )
30
+ ) });
31
+ }
32
+ export {
33
+ LazyLoadCard as L
34
+ };
@@ -0,0 +1,118 @@
1
+ import { Column, RowsChangeData } from 'react-data-grid';
2
+ import { CardsViewConfig, RowKey } from '../../types';
3
+ import { Maybe } from '@m4l/core';
4
+ import { IViewConfig } from '../../contexts/DataGridContext/types';
5
+ import { Sizes } from '@m4l/styles';
6
+ /**
7
+ * Props para el componente IntersectCard
8
+ */
9
+ export interface IntersectCardProps {
10
+ /**
11
+ * Función callback que se ejecuta cuando el elemento entra en el viewport.
12
+ * Recibe true cuando el elemento es visible.
13
+ * @param visible - Estado de visibilidad del elemento
14
+ */
15
+ setIsVisible: (visible: boolean) => void;
16
+ /**
17
+ * Distancia en píxeles desde el borde del viewport donde se activa la detección.
18
+ * Un valor de 100 significa que el elemento se considerará visible cuando esté
19
+ * a 100px o menos del área visible de la pantalla.
20
+ * @default 100
21
+ */
22
+ threshold: number;
23
+ /**
24
+ * Altura mínima del placeholder en píxeles
25
+ * @default '120px'
26
+ */
27
+ minHeight?: number;
28
+ }
29
+ /**
30
+ * Tipo extendido para el elemento div que incluye el método setIsVisible.
31
+ * Este método se adjunta dinámicamente al elemento DOM para que el Observer
32
+ * pueda comunicarse con el componente React.
33
+ */
34
+ export type IntersectCardRef = HTMLDivElement & {
35
+ setIsVisible?: (visible: boolean) => void;
36
+ };
37
+ /**
38
+ * Props para el componente LazyLoadCard
39
+ */
40
+ export interface LazyLoadCardProps {
41
+ /**
42
+ * Contenido de la card que se renderizará una vez que sea visible.
43
+ * Típicamente será un componente Card con los datos de la fila.
44
+ */
45
+ children: React.ReactNode;
46
+ /**
47
+ * Habilita o deshabilita el lazy loading con IntersectionObserver.
48
+ * Si se deshabilita, la card se renderiza inmediatamente.
49
+ * @default true
50
+ */
51
+ enableIntersectionObserver?: boolean;
52
+ /**
53
+ * Distancia en píxeles desde el borde del viewport donde se activa la carga.
54
+ * Un valor más alto carga las cards antes de que sean visibles,
55
+ * mejorando la experiencia del usuario.
56
+ * @default 100
57
+ */
58
+ threshold?: number;
59
+ /**
60
+ * Altura mínima del placeholder en píxeles
61
+ * @default 120
62
+ */
63
+ minHeight?: number;
64
+ }
65
+ /**
66
+ * Props para el componente CardRow
67
+ */
68
+ export interface CardRowProps<TRow, TKey extends RowKey = RowKey> {
69
+ /**
70
+ * Fila que se mostrará en la tarjeta
71
+ */
72
+ row: TRow;
73
+ /**
74
+ * Columnas que se mostrarán en la tarjeta (procesadas, filtradas por visibilidad)
75
+ */
76
+ columns: readonly Column<TRow, any>[];
77
+ /**
78
+ * Columnas originales sin filtrar (para el modal de detalle)
79
+ */
80
+ originalColumns: readonly Column<TRow, any>[];
81
+ /**
82
+ * Función que devuelve la clave de la fila
83
+ */
84
+ rowKeyGetter: (row: TRow) => TKey;
85
+ /**
86
+ * Filas seleccionadas actualmente
87
+ */
88
+ selectedRows?: ReadonlySet<TKey>;
89
+ /**
90
+ * Función para manejar el cambio de filas seleccionadas
91
+ */
92
+ onSelectedRowsChange?: (mapRowsSelected: ReadonlySet<TKey>) => void;
93
+ /**
94
+ * Función para manejar cambios en las filas (para editores)
95
+ */
96
+ onRowsChange?: Maybe<(rows: TRow[], data: RowsChangeData<TRow, any>) => void>;
97
+ /**
98
+ * Indica si se debe renderizar el contenido personalizado de la tarjeta
99
+ */
100
+ customRender?: CardsViewConfig<TRow>['customRender'];
101
+ }
102
+ /**
103
+ * Props para el componente CardDetails
104
+ */
105
+ export interface CardDetailsProps<TRow> {
106
+ row: TRow;
107
+ columns: readonly Column<TRow, any>[];
108
+ viewColumnsConfig: IViewConfig<any, any>[];
109
+ onRowsChange?: Maybe<(rows: TRow[], data: RowsChangeData<TRow, any>) => void>;
110
+ size?: Extract<Sizes, 'small' | 'medium'>;
111
+ }
112
+ /**
113
+ * Props para el componente CardHeader
114
+ */
115
+ export interface CardHeaderProps<TRow> {
116
+ row: TRow;
117
+ onOpenDetail: () => void;
118
+ }
@@ -0,0 +1,7 @@
1
+ import { CheckboxCellAdapterProps } from './types';
2
+ /**
3
+ * Adaptador que renderiza el checkbox apropidado según el viewMode
4
+ * - En viewMode 'cards': usa CheckboxFormatter (MUI)
5
+ * - En viewMode 'table': usa SelectCellFormatter (react-data-grid)
6
+ */
7
+ export declare const CheckboxCellAdapter: import('react').ForwardRefExoticComponent<CheckboxCellAdapterProps & import('react').RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,43 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { forwardRef, useContext } from "react";
3
+ import { SelectCellFormatter } from "react-data-grid";
4
+ import { C as CheckboxFormatter } from "../Table/subcomponents/CheckboxFormatter.js";
5
+ import { a as DataGridContext } from "../../contexts/DataGridContext/index.js";
6
+ import { k as CheckboxCellWrapperStyled } from "../../slots/DataGridSlot.js";
7
+ const CheckboxCellAdapter = forwardRef(function CheckboxCellAdapter2(props, ref) {
8
+ const {
9
+ value,
10
+ disabled,
11
+ tabIndex,
12
+ onChange,
13
+ "aria-label": ariaLabel
14
+ } = props;
15
+ const context = useContext(DataGridContext);
16
+ const viewMode = context?.viewMode ?? "cards";
17
+ if (viewMode !== "table") {
18
+ return /* @__PURE__ */ jsx(CheckboxCellWrapperStyled, { children: /* @__PURE__ */ jsx(
19
+ CheckboxFormatter,
20
+ {
21
+ ref,
22
+ checked: value,
23
+ disabled,
24
+ tabIndex,
25
+ onChange,
26
+ "aria-label": ariaLabel
27
+ }
28
+ ) });
29
+ }
30
+ return /* @__PURE__ */ jsx(
31
+ SelectCellFormatter,
32
+ {
33
+ value,
34
+ disabled,
35
+ tabIndex,
36
+ onChange,
37
+ "aria-label": ariaLabel || "Select"
38
+ }
39
+ );
40
+ });
41
+ export {
42
+ CheckboxCellAdapter as C
43
+ };
@@ -0,0 +1,7 @@
1
+ export interface CheckboxCellAdapterProps {
2
+ value: boolean;
3
+ disabled?: boolean;
4
+ tabIndex?: number;
5
+ onChange: (checked: boolean, isShiftClick: boolean) => void;
6
+ 'aria-label'?: string;
7
+ }
@@ -1,6 +1,6 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { useIsMobile } from "@m4l/graphics";
3
- import { b as ControlNavigateStyled } from "../../slots/DataGridSlot.js";
3
+ import { l as ControlNavigateStyled } from "../../slots/DataGridSlot.js";
4
4
  import { R as RowsCount } from "../HeaderActions/subcomponents/RowsCount/index.js";
5
5
  import { u as useComponentSize } from "../../../../hooks/useComponentSize/useComponentSize.js";
6
6
  import { P as Pager } from "../../../Pager/Pager.js";
@@ -2,10 +2,11 @@ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { F as Filter } from "./subcomponents/Filter/index.js";
3
3
  import { S as Settings } from "./subcomponents/Settings/index.js";
4
4
  import { D as Density } from "./subcomponents/Density/index.js";
5
+ import { V as ViewMode } from "./subcomponents/ViewMode/index.js";
5
6
  import { u as useDataGrid } from "../../hooks/useDataGrid.js";
6
7
  import { useIsMobile } from "@m4l/graphics";
7
8
  import { M as MobileMenuActions } from "./subcomponents/MobileMenuActions/index.js";
8
- import { A as ActionsRootStyled, c as ActionsConfigContainerStyled, d as ContainerLeftActionsStyled, e as ContainerRightActionsStyled } from "../../slots/DataGridSlot.js";
9
+ import { A as ActionsRootStyled, m as ActionsConfigContainerStyled, n as ContainerLeftActionsStyled, o as ContainerRightActionsStyled } from "../../slots/DataGridSlot.js";
9
10
  import { u as useComponentSize } from "../../../../hooks/useComponentSize/useComponentSize.js";
10
11
  function HeaderActions(props) {
11
12
  const {
@@ -19,7 +20,7 @@ function HeaderActions(props) {
19
20
  columns
20
21
  } = props;
21
22
  const isMobile = useIsMobile();
22
- const { rowHeights } = useDataGrid();
23
+ const { rowHeights, viewMode, cardsViewConfig } = useDataGrid();
23
24
  const { currentSize } = useComponentSize(size);
24
25
  return /* @__PURE__ */ jsx(ActionsRootStyled, { ownerState: { size: currentSize }, children: isMobile ? /* @__PURE__ */ jsxs(Fragment, { children: [
25
26
  leftActions,
@@ -30,7 +31,8 @@ function HeaderActions(props) {
30
31
  leftActions,
31
32
  typeof rowHeights !== "number" && /* @__PURE__ */ jsx(Density, {}),
32
33
  withLocalFilters && /* @__PURE__ */ jsx(Filter, {}),
33
- withSettings && /* @__PURE__ */ jsx(Settings, { ...settingsProps, columns })
34
+ withSettings && !(viewMode === "cards" && cardsViewConfig?.customRender) && /* @__PURE__ */ jsx(Settings, { ...settingsProps, columns }),
35
+ cardsViewConfig !== void 0 && /* @__PURE__ */ jsx(ViewMode, {})
34
36
  ] }),
35
37
  rightActions && /* @__PURE__ */ jsx(ContainerRightActionsStyled, { children: rightActions })
36
38
  ] }) });
@@ -2,7 +2,7 @@ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { useModuleDictionary, useModuleSkeleton } from "@m4l/core";
3
3
  import { Skeleton } from "@mui/material";
4
4
  import { u as useDataGrid } from "../../../../hooks/useDataGrid.js";
5
- import { R as RowsCountRootStyled, f as RowsCountLabelStyled, g as RowsCountValueStyled } from "../../../../slots/DataGridSlot.js";
5
+ import { R as RowsCountRootStyled, p as RowsCountLabelStyled, q as RowsCountValueStyled } from "../../../../slots/DataGridSlot.js";
6
6
  function RowsCount() {
7
7
  const { rowsCount, size } = useDataGrid();
8
8
  const { getLabel } = useModuleDictionary();
@@ -4,17 +4,26 @@ import { useEnvironment, useModuleDictionary } from "@m4l/core";
4
4
  import { u as useModalSettings } from "../hooks/useModalSettings/index.js";
5
5
  import { p as pathIcons } from "../../../../icons.js";
6
6
  import { u as useDataGrid } from "../../../../hooks/useDataGrid.js";
7
+ import { u as useModalSettingsCards } from "../hooks/useModalSettingsCards/index.js";
7
8
  function Settings(props) {
8
9
  const { columns } = props;
9
10
  const { host_static_assets, environment_assets } = useEnvironment();
10
- const { size } = useDataGrid();
11
+ const { size, viewMode } = useDataGrid();
11
12
  const modalSettings = useModalSettings(size, columns);
13
+ const modalSettingsCards = useModalSettingsCards(size, columns);
12
14
  const { getLabel } = useModuleDictionary();
15
+ const handleClick = () => {
16
+ if (viewMode === "table") {
17
+ modalSettings();
18
+ } else {
19
+ modalSettingsCards();
20
+ }
21
+ };
13
22
  return /* @__PURE__ */ jsx(
14
23
  IconButton,
15
24
  {
16
25
  tooltip: getLabel("data_grid.tooltip_settings"),
17
- onClick: modalSettings,
26
+ onClick: handleClick,
18
27
  "aria-label": "settings",
19
28
  icon: `${host_static_assets}/${environment_assets}/${pathIcons.configuration}`,
20
29
  "data-testid": "settings-button"
@@ -4,7 +4,7 @@ import { useModuleDictionary, useEnvironment } from "@m4l/core";
4
4
  import DataGrid from "react-data-grid";
5
5
  import { I as IconButton } from "../../../../../../../mui_extended/IconButton/IconButton.js";
6
6
  import { p as pathIcons } from "../../../../../../icons.js";
7
- import { h as ColumnsConfigWrapperStyled, i as ColumnsConfigDataGridStyled, j as ColumnsConfigSelColumnsStyled, T as TableWrapperDataGridStyled, k as ColumnsConfigActiosStyled } from "../../../../../../slots/DataGridSlot.js";
7
+ import { r as ColumnsConfigWrapperStyled, s as ColumnsConfigDataGridStyled, t as ColumnsConfigSelColumnsStyled, T as TableWrapperDataGridStyled, u as ColumnsConfigActiosStyled } from "../../../../../../slots/DataGridSlot.js";
8
8
  import { D as DICTIONARY } from "../../../../../../dictionary.js";
9
9
  import { C as ColumnInteractiveCheckFormatter } from "../../../../../../formatters/ColumnInteractiveCheckFormatter/formatter.js";
10
10
  function getRowsFromColumnsConfig(columnsConfig, columns) {