@centreon/ui 26.10.4 → 26.10.6
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/package.json +1 -1
- package/src/components/SortableEntriesList/Row.tsx +117 -0
- package/src/components/SortableEntriesList/SortableEntriesList.cypress.spec.tsx +792 -0
- package/src/components/SortableEntriesList/SortableEntriesList.stories.tsx +325 -0
- package/src/components/SortableEntriesList/SortableEntriesList.tsx +199 -0
- package/src/components/SortableEntriesList/index.ts +3 -0
- package/src/components/SortableEntriesList/models.ts +20 -0
- package/src/components/SortableEntriesList/translatedLabels.ts +12 -0
- package/src/components/SortableEntriesList/useMaxVisibleRows.ts +77 -0
- package/src/components/SortableEntriesList/useSortableEntries.ts +145 -0
- package/src/components/index.ts +1 -0
package/package.json
CHANGED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import DeleteIcon from '@mui/icons-material/Delete';
|
|
2
|
+
import DragIndicatorIcon from '@mui/icons-material/DragIndicator';
|
|
3
|
+
|
|
4
|
+
import { useSortable } from '@dnd-kit/sortable';
|
|
5
|
+
import { CSS } from '@dnd-kit/utilities';
|
|
6
|
+
import type { ComponentPropsWithRef, ReactNode } from 'react';
|
|
7
|
+
import { useTranslation } from 'react-i18next';
|
|
8
|
+
|
|
9
|
+
import { IconButton } from '../Button';
|
|
10
|
+
import { Tooltip } from '../Tooltip';
|
|
11
|
+
import type { RenderRowParams, RowParams, SortableRowAction } from './models';
|
|
12
|
+
import { labelDelete, labelDragToReorder } from './translatedLabels';
|
|
13
|
+
|
|
14
|
+
type RowButtonProps = ComponentPropsWithRef<typeof IconButton> & {
|
|
15
|
+
label: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// 30px buttons at a 32px pitch. The icon size is set here because the Tooltip
|
|
19
|
+
// overrides IconButton's own small-size class, and consumer icons may be any size.
|
|
20
|
+
const RowButton = ({
|
|
21
|
+
className = '',
|
|
22
|
+
label,
|
|
23
|
+
...buttonProps
|
|
24
|
+
}: RowButtonProps): JSX.Element => (
|
|
25
|
+
<Tooltip label={label}>
|
|
26
|
+
<IconButton
|
|
27
|
+
{...buttonProps}
|
|
28
|
+
aria-label={label}
|
|
29
|
+
className={`[&_.MuiSvgIcon-root]:text-xl ${className}`}
|
|
30
|
+
size="small"
|
|
31
|
+
variant="ghost"
|
|
32
|
+
/>
|
|
33
|
+
</Tooltip>
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
interface Props<T> {
|
|
37
|
+
actions: Array<SortableRowAction>;
|
|
38
|
+
className?: string;
|
|
39
|
+
draggable: boolean;
|
|
40
|
+
id: string;
|
|
41
|
+
onDelete: (id: string) => void;
|
|
42
|
+
onUpdate: (id: string, update: (value: T) => T) => void;
|
|
43
|
+
renderRow: (params: RenderRowParams<T>) => ReactNode;
|
|
44
|
+
rowParams: RowParams<T>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export const Row = <T,>({
|
|
48
|
+
actions,
|
|
49
|
+
className = '',
|
|
50
|
+
draggable,
|
|
51
|
+
id,
|
|
52
|
+
onDelete,
|
|
53
|
+
onUpdate,
|
|
54
|
+
renderRow,
|
|
55
|
+
rowParams
|
|
56
|
+
}: Props<T>): JSX.Element => {
|
|
57
|
+
const { t } = useTranslation();
|
|
58
|
+
const {
|
|
59
|
+
attributes,
|
|
60
|
+
isDragging,
|
|
61
|
+
listeners,
|
|
62
|
+
setActivatorNodeRef,
|
|
63
|
+
setNodeRef,
|
|
64
|
+
transform,
|
|
65
|
+
transition
|
|
66
|
+
} = useSortable({ disabled: !draggable, id });
|
|
67
|
+
|
|
68
|
+
const setValue = (value: T): void => onUpdate(id, () => value);
|
|
69
|
+
const setField = <K extends keyof T>(field: K, fieldValue: T[K]): void =>
|
|
70
|
+
onUpdate(
|
|
71
|
+
id,
|
|
72
|
+
(value) => ({ ...(value as object), [field]: fieldValue }) as T
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<li
|
|
77
|
+
className={`relative flex w-full items-center gap-2 ${isDragging ? 'z-1 opacity-70' : ''} ${className}`}
|
|
78
|
+
data-entry-id={id}
|
|
79
|
+
ref={setNodeRef}
|
|
80
|
+
style={{ transform: CSS.Translate.toString(transform), transition }}
|
|
81
|
+
>
|
|
82
|
+
<div className="min-w-0 flex-1" data-row-fields>
|
|
83
|
+
{renderRow({ ...rowParams, setField, setValue })}
|
|
84
|
+
</div>
|
|
85
|
+
<div className="flex flex-none items-center gap-0.5">
|
|
86
|
+
{actions.map(({ icon, id: actionId, isDisabled, label, onClick }) => (
|
|
87
|
+
<RowButton
|
|
88
|
+
data-testid={actionId}
|
|
89
|
+
disabled={isDisabled}
|
|
90
|
+
icon={icon}
|
|
91
|
+
key={actionId}
|
|
92
|
+
label={t(label)}
|
|
93
|
+
onClick={onClick}
|
|
94
|
+
/>
|
|
95
|
+
))}
|
|
96
|
+
<RowButton
|
|
97
|
+
className="text-error-main"
|
|
98
|
+
data-testid="delete-row"
|
|
99
|
+
icon={<DeleteIcon />}
|
|
100
|
+
label={t(labelDelete)}
|
|
101
|
+
onClick={(): void => onDelete(id)}
|
|
102
|
+
/>
|
|
103
|
+
{draggable && (
|
|
104
|
+
<RowButton
|
|
105
|
+
{...attributes}
|
|
106
|
+
{...listeners}
|
|
107
|
+
className="cursor-grab touch-none active:cursor-grabbing"
|
|
108
|
+
data-testid="drag-handle"
|
|
109
|
+
icon={<DragIndicatorIcon />}
|
|
110
|
+
label={t(labelDragToReorder)}
|
|
111
|
+
ref={setActivatorNodeRef}
|
|
112
|
+
/>
|
|
113
|
+
)}
|
|
114
|
+
</div>
|
|
115
|
+
</li>
|
|
116
|
+
);
|
|
117
|
+
};
|