@gridsuite/commons-ui 0.194.0 → 0.196.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.
Files changed (51) hide show
  1. package/dist/components/index.d.ts +1 -0
  2. package/dist/components/index.js +53 -0
  3. package/dist/components/network-modification-table/columns-definition.d.ts +26 -0
  4. package/dist/components/network-modification-table/columns-definition.js +36 -0
  5. package/dist/components/network-modification-table/index.d.ts +13 -0
  6. package/dist/components/network-modification-table/index.js +55 -0
  7. package/dist/components/network-modification-table/network-modification-table-styles.d.ts +210 -0
  8. package/dist/components/network-modification-table/network-modification-table-styles.js +333 -0
  9. package/dist/components/network-modification-table/network-modifications-table.d.ts +20 -0
  10. package/dist/components/network-modification-table/network-modifications-table.js +166 -0
  11. package/dist/components/network-modification-table/renderers/depth-box.d.ts +6 -0
  12. package/dist/components/network-modification-table/renderers/depth-box.js +21 -0
  13. package/dist/components/network-modification-table/renderers/drag-handle-cell.d.ts +5 -0
  14. package/dist/components/network-modification-table/renderers/drag-handle-cell.js +10 -0
  15. package/dist/components/network-modification-table/renderers/index.d.ts +12 -0
  16. package/dist/components/network-modification-table/renderers/index.js +14 -0
  17. package/dist/components/network-modification-table/renderers/name-cell.d.ts +7 -0
  18. package/dist/components/network-modification-table/renderers/name-cell.js +84 -0
  19. package/dist/components/network-modification-table/renderers/network-modification-node-editor-name-header.d.ts +14 -0
  20. package/dist/components/network-modification-table/renderers/network-modification-node-editor-name-header.js +40 -0
  21. package/dist/components/network-modification-table/renderers/select-cell.d.ts +8 -0
  22. package/dist/components/network-modification-table/renderers/select-cell.js +60 -0
  23. package/dist/components/network-modification-table/renderers/select-header-cell.d.ts +7 -0
  24. package/dist/components/network-modification-table/renderers/select-header-cell.js +26 -0
  25. package/dist/components/network-modification-table/row/drag-row-clone.d.ts +7 -0
  26. package/dist/components/network-modification-table/row/drag-row-clone.js +35 -0
  27. package/dist/components/network-modification-table/row/index.d.ts +8 -0
  28. package/dist/components/network-modification-table/row/index.js +6 -0
  29. package/dist/components/network-modification-table/row/modification-row.d.ts +12 -0
  30. package/dist/components/network-modification-table/row/modification-row.js +117 -0
  31. package/dist/components/network-modification-table/use-modifications-drag-and-drop.d.ts +21 -0
  32. package/dist/components/network-modification-table/use-modifications-drag-and-drop.js +170 -0
  33. package/dist/components/network-modification-table/utils.d.ts +40 -0
  34. package/dist/components/network-modification-table/utils.js +164 -0
  35. package/dist/components/network-modifications/by-filter/assignment/assignment/assignment-form.js +72 -53
  36. package/dist/components/network-modifications/by-filter/assignment/assignment/assignment-utils.d.ts +1 -0
  37. package/dist/components/network-modifications/by-filter/assignment/assignment/assignment-utils.js +8 -5
  38. package/dist/components/network-modifications/by-filter/assignment/modificationByAssignment.utils.js +5 -5
  39. package/dist/components/parameters/common/parameter-table-field/parameter-table-field.js +1 -1
  40. package/dist/components/parameters/dynamic-margin-calculation/loads-variations-parameters.js +1 -2
  41. package/dist/hooks/useModificationLabelComputer.d.ts +1 -12
  42. package/dist/index.js +59 -1
  43. package/dist/module-tanstack.d.js +1 -0
  44. package/dist/services/index.js +6 -1
  45. package/dist/services/networkModification.d.ts +21 -0
  46. package/dist/services/networkModification.js +34 -0
  47. package/dist/utils/types/index.d.ts +1 -0
  48. package/dist/utils/types/network-modification-metadata.d.ts +15 -0
  49. package/dist/utils/types/network-modification-metadata.js +1 -0
  50. package/dist/utils/types/network-modification-types.d.ts +5 -6
  51. package/package.json +3 -1
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Copyright (c) 2025, RTE (http://www.rte-france.com)
3
+ * This Source Code Form is subject to the terms of the Mozilla Public
4
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
+ */
7
+ export interface NetworkModificationEditorNameHeaderProps {
8
+ modificationCount?: number;
9
+ notificationMessageId?: string;
10
+ isFetchingModifications: boolean;
11
+ isImpactedByNotification: () => boolean;
12
+ pendingState: boolean;
13
+ }
14
+ export declare function NetworkModificationEditorNameHeader({ modificationCount, isFetchingModifications, isImpactedByNotification, notificationMessageId, pendingState, }: Readonly<NetworkModificationEditorNameHeaderProps>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,40 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { Box, CircularProgress, Typography } from "@mui/material";
3
+ import { FormattedMessage } from "react-intl";
4
+ import { networkModificationTableStyles } from "../network-modification-table-styles.js";
5
+ function NetworkModificationEditorNameHeader({
6
+ modificationCount,
7
+ isFetchingModifications,
8
+ isImpactedByNotification,
9
+ notificationMessageId,
10
+ pendingState
11
+ }) {
12
+ if (isImpactedByNotification() && notificationMessageId) {
13
+ return /* @__PURE__ */ jsxs(Box, { sx: networkModificationTableStyles.modificationNameHeader, children: [
14
+ /* @__PURE__ */ jsx(Box, { sx: networkModificationTableStyles.icon, children: /* @__PURE__ */ jsx(CircularProgress, { size: "1em", sx: networkModificationTableStyles.modificationCircularProgress }) }),
15
+ /* @__PURE__ */ jsx(Typography, { noWrap: true, children: /* @__PURE__ */ jsx(FormattedMessage, { id: notificationMessageId }) })
16
+ ] });
17
+ }
18
+ if (isFetchingModifications) {
19
+ return /* @__PURE__ */ jsxs(Box, { sx: networkModificationTableStyles.modificationNameHeader, children: [
20
+ /* @__PURE__ */ jsx(Box, { sx: networkModificationTableStyles.icon, children: /* @__PURE__ */ jsx(CircularProgress, { size: "1em", sx: networkModificationTableStyles.modificationCircularProgress }) }),
21
+ /* @__PURE__ */ jsx(Typography, { noWrap: true, children: /* @__PURE__ */ jsx(FormattedMessage, { id: "network_modifications.modifications" }) })
22
+ ] });
23
+ }
24
+ return /* @__PURE__ */ jsxs(Box, { sx: networkModificationTableStyles.modificationNameHeader, children: [
25
+ pendingState && /* @__PURE__ */ jsx(Box, { sx: networkModificationTableStyles.icon, children: /* @__PURE__ */ jsx(CircularProgress, { size: "1em", sx: networkModificationTableStyles.modificationCircularProgress }) }),
26
+ /* @__PURE__ */ jsx(Typography, { noWrap: true, children: /* @__PURE__ */ jsx(
27
+ FormattedMessage,
28
+ {
29
+ id: "network_modifications.modificationsCount",
30
+ values: {
31
+ count: modificationCount ?? "",
32
+ hide: pendingState
33
+ }
34
+ }
35
+ ) })
36
+ ] });
37
+ }
38
+ export {
39
+ NetworkModificationEditorNameHeader
40
+ };
@@ -0,0 +1,8 @@
1
+ import { Row, Table } from '@tanstack/react-table';
2
+ import { ComposedModificationMetadata } from '../../../utils';
3
+ interface SelectCellRendererProps {
4
+ row: Row<ComposedModificationMetadata>;
5
+ table: Table<ComposedModificationMetadata>;
6
+ }
7
+ export declare function SelectCell({ row, table }: Readonly<SelectCellRendererProps>): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,60 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useCallback, useMemo } from "react";
3
+ import { Checkbox } from "@mui/material";
4
+ import { networkModificationTableStyles } from "../network-modification-table-styles.js";
5
+ function SelectCell({ row, table }) {
6
+ const { meta } = table.options;
7
+ const handleChange = useCallback(
8
+ (event) => {
9
+ const rows = table.getRowModel().flatRows;
10
+ const currentIndex = rows.indexOf(row);
11
+ const nextSelection = { ...table.getState().rowSelection };
12
+ if (event.shiftKey && meta?.lastClickedIndex.current !== null && meta?.lastClickedIndex.current !== void 0) {
13
+ const lastIndex = meta.lastClickedIndex.current;
14
+ const [from, to] = lastIndex < currentIndex ? [lastIndex, currentIndex] : [currentIndex, lastIndex];
15
+ const isRowSelected = row.getIsSelected();
16
+ rows.slice(from, to + 1).forEach((r) => {
17
+ if (r.getCanSelect()) {
18
+ r.toggleSelected(!isRowSelected);
19
+ if (isRowSelected) {
20
+ delete nextSelection[r.id];
21
+ } else {
22
+ nextSelection[r.id] = true;
23
+ }
24
+ }
25
+ });
26
+ } else {
27
+ row.toggleSelected();
28
+ if (row.getIsSelected()) {
29
+ delete nextSelection[row.id];
30
+ } else {
31
+ nextSelection[row.id] = true;
32
+ }
33
+ }
34
+ if (meta) {
35
+ meta.lastClickedIndex.current = currentIndex;
36
+ const selectedRows = rows.filter((r) => nextSelection[r.id]).map((r) => r.original);
37
+ meta.onRowSelected?.(selectedRows);
38
+ }
39
+ },
40
+ [table, row, meta]
41
+ );
42
+ const hasPartiallySelectedSubRows = useMemo(
43
+ () => row.subRows.some((subRow) => subRow.getIsSelected()) && !row.getIsSelected(),
44
+ [row]
45
+ );
46
+ return /* @__PURE__ */ jsx(
47
+ Checkbox,
48
+ {
49
+ size: "small",
50
+ checked: row.getIsSelected(),
51
+ indeterminate: hasPartiallySelectedSubRows,
52
+ disabled: !row.getCanSelect(),
53
+ onClick: handleChange,
54
+ sx: networkModificationTableStyles.selectCheckBox
55
+ }
56
+ );
57
+ }
58
+ export {
59
+ SelectCell
60
+ };
@@ -0,0 +1,7 @@
1
+ import { Table } from '@tanstack/react-table';
2
+ import { ComposedModificationMetadata } from '../../../utils';
3
+ interface SelectHeaderCellProps {
4
+ table: Table<ComposedModificationMetadata>;
5
+ }
6
+ export declare function SelectHeaderCell({ table }: Readonly<SelectHeaderCellProps>): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,26 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useCallback } from "react";
3
+ import { Checkbox } from "@mui/material";
4
+ function SelectHeaderCell({ table }) {
5
+ const handleClick = useCallback(() => {
6
+ const { meta } = table.options;
7
+ if (meta) {
8
+ const nextSelectedRows = table.getIsAllRowsSelected() ? [] : table.getCoreRowModel().rows.map((r) => r.original);
9
+ meta.onRowSelected?.(nextSelectedRows);
10
+ meta.lastClickedIndex.current = null;
11
+ }
12
+ table.toggleAllRowsSelected();
13
+ }, [table]);
14
+ return /* @__PURE__ */ jsx(
15
+ Checkbox,
16
+ {
17
+ size: "small",
18
+ checked: table.getIsAllRowsSelected(),
19
+ indeterminate: table.getSelectedRowModel().flatRows.length !== 0 && !table.getIsAllRowsSelected(),
20
+ onClick: handleClick
21
+ }
22
+ );
23
+ }
24
+ export {
25
+ SelectHeaderCell
26
+ };
@@ -0,0 +1,7 @@
1
+ import { Row } from '@tanstack/react-table';
2
+ import { ComposedModificationMetadata } from '../../../utils';
3
+ interface DragCloneRowProps {
4
+ row: Row<ComposedModificationMetadata>;
5
+ }
6
+ export declare function DragCloneRow({ row }: Readonly<DragCloneRowProps>): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,35 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { Box } from "@mui/material";
3
+ import { DragIndicator } from "@mui/icons-material";
4
+ import { useCallback } from "react";
5
+ import { useIntl } from "react-intl";
6
+ import { networkModificationTableStyles } from "../network-modification-table-styles.js";
7
+ import { useModificationLabelComputer } from "../../../hooks/useModificationLabelComputer.js";
8
+ import "../../../utils/conversionUtils.js";
9
+ import "../../../utils/types/equipmentType.js";
10
+ import { mergeSx } from "../../../utils/styles.js";
11
+ import "../../../utils/yupConfig.js";
12
+ import "localized-countries";
13
+ import "localized-countries/data/fr";
14
+ import "localized-countries/data/en";
15
+ import "notistack";
16
+ function DragCloneRow({ row }) {
17
+ const intl = useIntl();
18
+ const { computeLabel } = useModificationLabelComputer();
19
+ const getModificationLabel = useCallback(
20
+ (modification, formatBold = true) => {
21
+ return intl.formatMessage(
22
+ { id: `network_modifications.${modification.messageType}` },
23
+ { ...modification, ...computeLabel(modification, formatBold) }
24
+ );
25
+ },
26
+ [computeLabel, intl]
27
+ );
28
+ return /* @__PURE__ */ jsxs(Box, { sx: networkModificationTableStyles.dragRowClone, children: [
29
+ /* @__PURE__ */ jsx(Box, { sx: networkModificationTableStyles.tableCell, children: /* @__PURE__ */ jsx(Box, { sx: mergeSx(networkModificationTableStyles.dragHandle, { opacity: 1 }), children: /* @__PURE__ */ jsx(DragIndicator, { sx: networkModificationTableStyles.dragIndicatorIcon }) }) }),
30
+ /* @__PURE__ */ jsx(Box, { sx: networkModificationTableStyles.tableCell, children: /* @__PURE__ */ jsx(Box, { sx: networkModificationTableStyles.modificationLabel, children: getModificationLabel(row.original) }) })
31
+ ] });
32
+ }
33
+ export {
34
+ DragCloneRow
35
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Copyright (c) 2026, RTE (http://www.rte-france.com)
3
+ * This Source Code Form is subject to the terms of the Mozilla Public
4
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
+ */
7
+ export * from './drag-row-clone';
8
+ export * from './modification-row';
@@ -0,0 +1,6 @@
1
+ import { DragCloneRow } from "./drag-row-clone.js";
2
+ import { ModificationRow } from "./modification-row.js";
3
+ export {
4
+ DragCloneRow,
5
+ ModificationRow
6
+ };
@@ -0,0 +1,12 @@
1
+ import { Row } from '@tanstack/react-table';
2
+ import { VirtualItem } from '@tanstack/react-virtual';
3
+ import { ComposedModificationMetadata } from '../../../utils';
4
+ interface ModificationRowProps {
5
+ virtualRow: VirtualItem;
6
+ row: Row<ComposedModificationMetadata>;
7
+ handleCellClick?: (modification: ComposedModificationMetadata) => void;
8
+ isRowDragDisabled: boolean;
9
+ highlightedModificationUuid: string | null;
10
+ }
11
+ export declare function ModificationRow({ virtualRow, row, handleCellClick, isRowDragDisabled, highlightedModificationUuid, }: Readonly<ModificationRowProps>): import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,117 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useCallback } from "react";
3
+ import { flexRender } from "@tanstack/react-table";
4
+ import { useTheme, TableRow, TableCell, Tooltip, Box } from "@mui/material";
5
+ import { Draggable } from "@hello-pangea/dnd";
6
+ import { FormattedMessage } from "react-intl";
7
+ import { BASE_MODIFICATION_TABLE_COLUMNS, AUTO_EXTENSIBLE_COLUMNS } from "../columns-definition.js";
8
+ import { COLUMNS_WITHOUT_BORDER, createCellStyle, createCellContentWrapperSx, createRowSx, networkModificationTableStyles } from "../network-modification-table-styles.js";
9
+ import { isCompositeModification } from "../utils.js";
10
+ import "../../../utils/conversionUtils.js";
11
+ import "../../../utils/types/equipmentType.js";
12
+ import "@mui/icons-material";
13
+ import { mergeSx } from "../../../utils/styles.js";
14
+ import "../../../utils/yupConfig.js";
15
+ function ModificationRow({
16
+ virtualRow,
17
+ row,
18
+ handleCellClick,
19
+ isRowDragDisabled,
20
+ highlightedModificationUuid
21
+ }) {
22
+ const isHighlighted = row.original.uuid === highlightedModificationUuid;
23
+ const theme = useTheme();
24
+ const isExpanded = row.getIsExpanded() && row.subRows.length > 0;
25
+ const handleCellClickCallback = useCallback(
26
+ (columnId) => {
27
+ if (columnId === BASE_MODIFICATION_TABLE_COLUMNS.NAME.id) {
28
+ handleCellClick?.(row.original);
29
+ }
30
+ },
31
+ [handleCellClick, row.original]
32
+ );
33
+ return /* @__PURE__ */ jsx(Draggable, { draggableId: row.id, index: virtualRow.index, isDragDisabled: isRowDragDisabled, children: (provided, snapshot) => {
34
+ const { style, ...draggablePropsWithoutStyle } = provided.draggableProps;
35
+ return /* @__PURE__ */ jsx(
36
+ TableRow,
37
+ {
38
+ ref: provided.innerRef,
39
+ ...draggablePropsWithoutStyle,
40
+ "data-row-id": row.original.uuid,
41
+ sx: mergeSx(
42
+ networkModificationTableStyles.tableRow,
43
+ createRowSx(
44
+ theme,
45
+ isHighlighted,
46
+ snapshot.isDragging,
47
+ virtualRow,
48
+ row.depth,
49
+ isCompositeModification(row.original)
50
+ )
51
+ ),
52
+ children: row.getVisibleCells().map((cell) => {
53
+ const isNameColumn = cell.column.id === BASE_MODIFICATION_TABLE_COLUMNS.NAME.id;
54
+ const isDragHandle = cell.column.id === BASE_MODIFICATION_TABLE_COLUMNS.DRAG_HANDLE.id;
55
+ const isCheckboxColumn = cell.column.id === BASE_MODIFICATION_TABLE_COLUMNS.SELECT.id;
56
+ const cellContent = flexRender(cell.column.columnDef.cell, cell.getContext());
57
+ const cellWithoutBorders = (isExpanded || row.depth > 0) && COLUMNS_WITHOUT_BORDER.has(cell.column.columnDef.id ?? "");
58
+ if (isDragHandle) {
59
+ return /* @__PURE__ */ jsx(
60
+ TableCell,
61
+ {
62
+ sx: createCellStyle(cell, AUTO_EXTENSIBLE_COLUMNS.includes(cell.column.id)),
63
+ children: /* @__PURE__ */ jsx(Tooltip, { title: /* @__PURE__ */ jsx(FormattedMessage, { id: "moveModification" }), arrow: true, children: /* @__PURE__ */ jsx(
64
+ Box,
65
+ {
66
+ sx: createCellContentWrapperSx(theme, cellWithoutBorders),
67
+ ...provided.dragHandleProps,
68
+ children: cellContent
69
+ }
70
+ ) })
71
+ },
72
+ cell.id
73
+ );
74
+ }
75
+ if (isCheckboxColumn) {
76
+ return /* @__PURE__ */ jsx(
77
+ TableCell,
78
+ {
79
+ sx: createCellStyle(cell, AUTO_EXTENSIBLE_COLUMNS.includes(cell.column.id)),
80
+ onClick: () => handleCellClickCallback(cell.column.id),
81
+ children: /* @__PURE__ */ jsx(
82
+ Tooltip,
83
+ {
84
+ title: /* @__PURE__ */ jsx(
85
+ FormattedMessage,
86
+ {
87
+ id: row.getIsSelected() ? "deselectModification" : "selectModification"
88
+ }
89
+ ),
90
+ arrow: true,
91
+ children: /* @__PURE__ */ jsx(Box, { sx: createCellContentWrapperSx(theme, cellWithoutBorders), children: cellContent })
92
+ }
93
+ )
94
+ },
95
+ cell.id
96
+ );
97
+ }
98
+ return /* @__PURE__ */ jsx(
99
+ TableCell,
100
+ {
101
+ sx: createCellStyle(cell, AUTO_EXTENSIBLE_COLUMNS.includes(cell.column.id)),
102
+ onClick: () => handleCellClickCallback(cell.column.id),
103
+ children: isNameColumn ? (
104
+ // NameCell owns its own borders entirely
105
+ flexRender(cell.column.columnDef.cell, cell.getContext())
106
+ ) : /* @__PURE__ */ jsx(Box, { sx: createCellContentWrapperSx(theme, cellWithoutBorders), children: cellContent })
107
+ },
108
+ cell.id
109
+ );
110
+ })
111
+ }
112
+ );
113
+ } });
114
+ }
115
+ export {
116
+ ModificationRow
117
+ };
@@ -0,0 +1,21 @@
1
+ import { default as React, JSX, RefObject } from 'react';
2
+ import { Row } from '@tanstack/react-table';
3
+ import { DraggableProvided, DraggableRubric, DraggableStateSnapshot, DragUpdate, DropResult } from '@hello-pangea/dnd';
4
+ import { UUID } from 'node:crypto';
5
+ import { ComposedModificationMetadata } from '../../utils';
6
+ interface UseModificationsDragAndDropParams {
7
+ rows: Row<ComposedModificationMetadata>[];
8
+ containerRef: RefObject<HTMLDivElement | null>;
9
+ composedModifications: ComposedModificationMetadata[];
10
+ setComposedModifications: React.Dispatch<React.SetStateAction<ComposedModificationMetadata[]>>;
11
+ onDragEnd: () => void;
12
+ studyUuid: UUID | null;
13
+ currentNodeUuid?: UUID;
14
+ }
15
+ interface UseModificationsDragAndDropReturn {
16
+ handleDragUpdate: (update: DragUpdate) => void;
17
+ handleDragEnd: (result: DropResult) => void;
18
+ renderClone: (provided: DraggableProvided, snapshot: DraggableStateSnapshot, rubric: DraggableRubric) => JSX.Element;
19
+ }
20
+ export declare const useModificationsDragAndDrop: ({ rows, containerRef, composedModifications, setComposedModifications, onDragEnd, studyUuid, currentNodeUuid, }: UseModificationsDragAndDropParams) => UseModificationsDragAndDropReturn;
21
+ export {};
@@ -0,0 +1,170 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useCallback } from "react";
3
+ import { DragCloneRow } from "./row/drag-row-clone.js";
4
+ import "@tanstack/react-table";
5
+ import "@mui/material";
6
+ import "@hello-pangea/dnd";
7
+ import "react-intl";
8
+ import "./columns-definition.js";
9
+ import { DROP_FORBIDDEN_INDICATOR_BOTTOM, DROP_FORBIDDEN_INDICATOR_TOP, DROP_INDICATOR_BOTTOM, DROP_INDICATOR_TOP } from "./network-modification-table-styles.js";
10
+ import { moveSubModificationInTree, isCompositeModification, findModificationInTree } from "./utils.js";
11
+ import "../../utils/conversionUtils.js";
12
+ import { snackWithFallback } from "../../utils/error.js";
13
+ import "../../utils/types/equipmentType.js";
14
+ import "@mui/icons-material";
15
+ import "../../utils/yupConfig.js";
16
+ import { changeCompositeSubModificationOrder, changeNetworkModificationOrder } from "../../services/networkModification.js";
17
+ import "localized-countries";
18
+ import "localized-countries/data/fr";
19
+ import "localized-countries/data/en";
20
+ import { useSnackMessage } from "../../hooks/useSnackMessage.js";
21
+ const clearRowDragIndicators = (container) => {
22
+ const rowElements = container?.querySelectorAll("[data-row-id]");
23
+ rowElements?.forEach((rowElement) => {
24
+ rowElement.style.boxShadow = "";
25
+ });
26
+ };
27
+ const isDropForbidden = (sourceRow, targetRow) => {
28
+ const isDraggingDown = targetRow.index > sourceRow.index;
29
+ if (isCompositeModification(sourceRow.original) && (isCompositeModification(targetRow.original) && targetRow.getIsExpanded() && isDraggingDown || isCompositeModification(targetRow.getParentRow()?.original))) {
30
+ return true;
31
+ }
32
+ return !!(isCompositeModification(sourceRow.original) && findModificationInTree(targetRow.original.uuid, [sourceRow.original]));
33
+ };
34
+ function getTargetCompositeUuid(droppingIntoExpandedComposite, targetRow) {
35
+ if (droppingIntoExpandedComposite) {
36
+ return targetRow.original.uuid;
37
+ }
38
+ return targetRow.depth > 0 ? targetRow.getParentRow()?.original.uuid ?? null : null;
39
+ }
40
+ function getTargetSiblings(targetCompositeUuid, rows) {
41
+ return targetCompositeUuid ? rows.filter((r) => r.depth > 0 && r.getParentRow()?.original.uuid === targetCompositeUuid) : rows.filter((r) => r.depth === 0);
42
+ }
43
+ function getContainerShadow(forbidden, isMovingDown) {
44
+ if (forbidden) {
45
+ return isMovingDown ? DROP_FORBIDDEN_INDICATOR_BOTTOM : DROP_FORBIDDEN_INDICATOR_TOP;
46
+ }
47
+ return isMovingDown ? DROP_INDICATOR_BOTTOM : DROP_INDICATOR_TOP;
48
+ }
49
+ const useModificationsDragAndDrop = ({
50
+ rows,
51
+ containerRef,
52
+ composedModifications,
53
+ setComposedModifications,
54
+ onDragEnd,
55
+ studyUuid = null,
56
+ currentNodeUuid = void 0
57
+ }) => {
58
+ const { snackError } = useSnackMessage();
59
+ const handleDragUpdate = useCallback(
60
+ (update) => {
61
+ clearRowDragIndicators(containerRef.current);
62
+ const { source, destination } = update;
63
+ if (!destination || source.index === destination.index) {
64
+ return;
65
+ }
66
+ const sourceRow = rows[source.index];
67
+ const targetRow = rows[destination.index];
68
+ const el = containerRef.current?.querySelector(`[data-row-id="${targetRow?.original.uuid}"]`);
69
+ if (!el) {
70
+ return;
71
+ }
72
+ const forbidden = isDropForbidden(sourceRow, targetRow);
73
+ const isMovingDown = destination.index > source.index;
74
+ el.style.boxShadow = getContainerShadow(forbidden, isMovingDown);
75
+ },
76
+ [rows, containerRef]
77
+ );
78
+ const handleDragEndComposite = useCallback(
79
+ (sourceRow, targetRow, droppingIntoExpandedComposite, isDraggingDown) => {
80
+ const movingUuid = sourceRow.original.uuid;
81
+ const sourceCompositeUuid = sourceRow.depth > 0 ? sourceRow.getParentRow()?.original.uuid ?? null : null;
82
+ const targetCompositeUuid = getTargetCompositeUuid(droppingIntoExpandedComposite, targetRow);
83
+ const targetSiblings = getTargetSiblings(targetCompositeUuid, rows);
84
+ let beforeUuid;
85
+ if (droppingIntoExpandedComposite) {
86
+ beforeUuid = targetSiblings[0]?.original.uuid ?? null;
87
+ } else {
88
+ const landingIndexInSiblings = targetSiblings.findIndex(
89
+ (r) => r.original.uuid === targetRow.original.uuid
90
+ );
91
+ const beforeSiblingIndex = isDraggingDown ? landingIndexInSiblings + 1 : landingIndexInSiblings;
92
+ beforeUuid = targetSiblings[beforeSiblingIndex]?.original.uuid ?? null;
93
+ }
94
+ const previousComposed = composedModifications;
95
+ setComposedModifications(
96
+ (prev) => moveSubModificationInTree(movingUuid, sourceCompositeUuid, targetCompositeUuid, beforeUuid, prev)
97
+ );
98
+ changeCompositeSubModificationOrder(
99
+ studyUuid,
100
+ currentNodeUuid,
101
+ movingUuid,
102
+ sourceCompositeUuid,
103
+ targetCompositeUuid,
104
+ beforeUuid
105
+ ).catch((error) => {
106
+ snackWithFallback(snackError, error, { headerId: "errReorderModificationMsg" });
107
+ setComposedModifications(previousComposed);
108
+ });
109
+ },
110
+ [rows, studyUuid, currentNodeUuid, snackError, composedModifications, setComposedModifications]
111
+ );
112
+ const handleDragEnd = useCallback(
113
+ (result) => {
114
+ clearRowDragIndicators(containerRef.current);
115
+ onDragEnd();
116
+ const { source, destination } = result;
117
+ if (!destination || source.index === destination.index) {
118
+ return;
119
+ }
120
+ const sourceRow = rows[source.index];
121
+ const targetRow = rows[destination.index];
122
+ if (isDropForbidden(sourceRow, targetRow)) {
123
+ return;
124
+ }
125
+ const isSubRowInvolved = sourceRow.depth > 0 || targetRow.depth > 0;
126
+ const isDraggingDown = destination.index > source.index;
127
+ const droppingIntoExpandedComposite = isDraggingDown && targetRow.getIsExpanded();
128
+ if (isSubRowInvolved || droppingIntoExpandedComposite) {
129
+ handleDragEndComposite(sourceRow, targetRow, droppingIntoExpandedComposite, isDraggingDown);
130
+ } else {
131
+ const sourceDepth0Uuid = sourceRow.original.uuid;
132
+ const targetDepth0Uuid = targetRow.original.uuid;
133
+ const oldPosition = composedModifications.findIndex((m) => m.uuid === sourceDepth0Uuid);
134
+ const newPosition = composedModifications.findIndex((m) => m.uuid === targetDepth0Uuid);
135
+ if (oldPosition === -1 || newPosition === -1 || oldPosition === newPosition || !currentNodeUuid) {
136
+ return;
137
+ }
138
+ const previousModifications = [...composedModifications];
139
+ const updatedModifications = [...composedModifications];
140
+ const [movedItem] = updatedModifications.splice(oldPosition, 1);
141
+ updatedModifications.splice(newPosition, 0, movedItem);
142
+ setComposedModifications(updatedModifications);
143
+ const before = updatedModifications[newPosition + 1]?.uuid ?? null;
144
+ changeNetworkModificationOrder(studyUuid, currentNodeUuid, movedItem.uuid, before).catch((error) => {
145
+ snackWithFallback(snackError, error, { headerId: "errReorderModificationMsg" });
146
+ setComposedModifications(previousModifications);
147
+ });
148
+ }
149
+ },
150
+ [
151
+ containerRef,
152
+ onDragEnd,
153
+ rows,
154
+ studyUuid,
155
+ currentNodeUuid,
156
+ snackError,
157
+ composedModifications,
158
+ setComposedModifications,
159
+ handleDragEndComposite
160
+ ]
161
+ );
162
+ const renderClone = useCallback(
163
+ (provided, _snapshot, rubric) => /* @__PURE__ */ jsx("div", { ref: provided.innerRef, ...provided.draggableProps, ...provided.dragHandleProps, children: /* @__PURE__ */ jsx(DragCloneRow, { row: rows[rubric.source.index] }) }),
164
+ [rows]
165
+ );
166
+ return { handleDragUpdate, handleDragEnd, renderClone };
167
+ };
168
+ export {
169
+ useModificationsDragAndDrop
170
+ };
@@ -0,0 +1,40 @@
1
+ import { Dispatch, SetStateAction } from 'react';
2
+ import { UUID } from 'node:crypto';
3
+ import { ComposedModificationMetadata, NetworkModificationMetadata } from '../../utils';
4
+ export declare const formatToComposedModification: (modifications: NetworkModificationMetadata[]) => ComposedModificationMetadata[];
5
+ export declare function isCompositeModification(modification: ComposedModificationMetadata | undefined): boolean;
6
+ /**
7
+ *
8
+ * @param modifications source where the composite modifications are looked for
9
+ * @param composites result : all the composite modifications found
10
+ */
11
+ export declare function findAllLoadedCompositeModifications(modifications: ComposedModificationMetadata[], composites: ComposedModificationMetadata[]): void;
12
+ export declare function findModificationInTree(uuid: string, mods: ComposedModificationMetadata[]): ComposedModificationMetadata | undefined;
13
+ /**
14
+ * in the tree, replaces the sub-modifications of 'parentModUuid' with 'subModifications' and returns the result
15
+ * @param parentModUuid
16
+ * @param subModifications new subModifications of parentModUuid
17
+ * @param tree all the modifications of the tree
18
+ */
19
+ export declare function updateSubModificationsOfACompositeInTree(parentModUuid: string, subModifications: ComposedModificationMetadata[], tree: ComposedModificationMetadata[]): ComposedModificationMetadata[];
20
+ /**
21
+ * Recursively merges already-loaded subModifications from the previous tree into a freshly
22
+ * formatted tree (where all subModifications start as []). This ensures that when `modifications`
23
+ * changes, previously fetched children are preserved and do not need to be re-fetched.
24
+ */
25
+ export declare function mergeSubModificationsIntoTree(nextMods: ComposedModificationMetadata[], prevMods: ComposedModificationMetadata[]): ComposedModificationMetadata[];
26
+ /**
27
+ * Returns a new tree where the modification identified by {@code uuid} has the given
28
+ * partial fields merged in. All other nodes are returned as-is (referentially stable).
29
+ */
30
+ export declare function updateModificationFieldInTree(uuid: string, fields: Partial<ComposedModificationMetadata>, mods: ComposedModificationMetadata[]): ComposedModificationMetadata[];
31
+ /**
32
+ * @param movingUuid moved submodification uuid
33
+ * @param sourceParentUuid composite from which movingUuid comes from. null if movingUuid is at the root level
34
+ * @param targetParentUuid composite where movingUuid is moved. null if movingUuid is moved to the root level
35
+ * @param beforeUuid movingUuid is moved just before beforeUuid. If null, movingUuid is moved to the end.
36
+ * @param mods all the network modifications of the tree
37
+ * @return mods updated according to the moved submodification
38
+ */
39
+ export declare function moveSubModificationInTree(movingUuid: UUID, sourceParentUuid: UUID | null, targetParentUuid: UUID | null, beforeUuid: UUID | null, mods: ComposedModificationMetadata[]): ComposedModificationMetadata[];
40
+ export declare function fetchSubModificationsForExpandedRows(expandedIds: string[], mods: ComposedModificationMetadata[], setMods: Dispatch<SetStateAction<ComposedModificationMetadata[]>>, force?: boolean): void;