@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "26.10.4",
3
+ "version": "26.10.6",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "update:deps": "pnpx npm-check-updates -i --format group",
@@ -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
+ };