@linzjs/step-ag-grid 31.1.1 → 31.2.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/dist/GridTheme.scss +4 -0
- package/dist/src/components/gridDragUtil.d.ts +10 -0
- package/dist/src/components/gridDragUtil.test.d.ts +1 -0
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/components/types.d.ts +4 -0
- package/dist/step-ag-grid.cjs +92 -4
- package/dist/step-ag-grid.cjs.map +1 -1
- package/dist/step-ag-grid.esm.js +92 -5
- package/dist/step-ag-grid.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Grid.tsx +69 -5
- package/src/components/gridDragUtil.test.ts +115 -0
- package/src/components/gridDragUtil.ts +32 -0
- package/src/components/index.ts +1 -0
- package/src/components/types.ts +4 -0
- package/src/stories/grid/GridDragRow.stories.tsx +61 -8
- package/src/styles/GridTheme.scss +4 -0
package/package.json
CHANGED
package/src/components/Grid.tsx
CHANGED
|
@@ -860,11 +860,39 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
860
860
|
});
|
|
861
861
|
}, []);
|
|
862
862
|
|
|
863
|
+
const clearDragRowClasses = useCallback(() => {
|
|
864
|
+
document.querySelectorAll(`.ag-row-dragging`)?.forEach((el) => {
|
|
865
|
+
el.classList.remove('ag-row-dragging');
|
|
866
|
+
});
|
|
867
|
+
}, []);
|
|
868
|
+
|
|
863
869
|
const gridElementRef = useRef<Element>(undefined);
|
|
870
|
+
const multiDragAppliedRef = useRef(false);
|
|
871
|
+
const multiDragCountRef = useRef(0);
|
|
864
872
|
const onRowDragMove = useCallback(
|
|
865
873
|
(event: RowDragMoveEvent) => {
|
|
866
874
|
if (startDragYRef.current === null) {
|
|
867
875
|
startDragYRef.current = event.y;
|
|
876
|
+
|
|
877
|
+
// On first move event, apply ag-row-dragging class to all selected rows for multi-drag
|
|
878
|
+
if (rowSelection === 'multiple' && event.node.isSelected()) {
|
|
879
|
+
const selectedNodes = event.api.getSelectedNodes().filter((n) => n.displayed && n.data != null);
|
|
880
|
+
if (selectedNodes.length > 1) {
|
|
881
|
+
multiDragAppliedRef.current = true;
|
|
882
|
+
multiDragCountRef.current = selectedNodes.length;
|
|
883
|
+
// Find the grid body element for scoped queries
|
|
884
|
+
const targetEl = event.event.target as Element | undefined;
|
|
885
|
+
const gridElement = targetEl?.closest('.ag-body');
|
|
886
|
+
if (gridElement) {
|
|
887
|
+
gridElementRef.current = gridElement;
|
|
888
|
+
for (const node of selectedNodes) {
|
|
889
|
+
gridElement.querySelectorAll(`[row-id='${node.data.id}']`)?.forEach((el) => {
|
|
890
|
+
el.classList.add('ag-row-dragging');
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
868
896
|
}
|
|
869
897
|
|
|
870
898
|
const yDiff = event.y - startDragYRef.current;
|
|
@@ -885,7 +913,7 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
885
913
|
});
|
|
886
914
|
}
|
|
887
915
|
},
|
|
888
|
-
[clearHighlightRowClasses],
|
|
916
|
+
[clearHighlightRowClasses, rowSelection],
|
|
889
917
|
);
|
|
890
918
|
|
|
891
919
|
const onCellFocused = useCallback(
|
|
@@ -922,6 +950,9 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
922
950
|
const onRowDragEnd = useCallback(
|
|
923
951
|
(event: RowDragEndEvent<TData>) => {
|
|
924
952
|
clearHighlightRowClasses();
|
|
953
|
+
clearDragRowClasses();
|
|
954
|
+
multiDragAppliedRef.current = false;
|
|
955
|
+
multiDragCountRef.current = 0;
|
|
925
956
|
gridElementRef.current = undefined;
|
|
926
957
|
if (!params.onRowDragEnd || startDragYRef.current === null) {
|
|
927
958
|
return;
|
|
@@ -934,10 +965,29 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
934
965
|
if (!movedRow || !targetRow || movedRow === targetRow || yDiff === 0) {
|
|
935
966
|
return;
|
|
936
967
|
}
|
|
937
|
-
|
|
968
|
+
|
|
969
|
+
// Determine movedRows: if dragged row is part of a multi-selection, include all selected & displayed rows
|
|
970
|
+
let movedRows: TData[];
|
|
971
|
+
if (rowSelection === 'multiple' && event.node.isSelected()) {
|
|
972
|
+
movedRows = event.api
|
|
973
|
+
.getSelectedNodes()
|
|
974
|
+
.filter((n) => n.displayed && n.data != null)
|
|
975
|
+
.sort((a, b) => (a.rowIndex ?? 0) - (b.rowIndex ?? 0))
|
|
976
|
+
.map((n) => n.data as TData);
|
|
977
|
+
} else {
|
|
978
|
+
movedRows = [movedRow];
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
// If targetRow is one of the moved rows, no-op
|
|
982
|
+
if (movedRows.some((r) => r.id === targetRow.id)) {
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
const direction: -1 | 1 = yDiff > 0 ? 1 : -1;
|
|
987
|
+
void params.onRowDragEnd({ movedRow, movedRows, targetRow, direction });
|
|
938
988
|
}
|
|
939
989
|
},
|
|
940
|
-
[params, clearHighlightRowClasses],
|
|
990
|
+
[params, clearHighlightRowClasses, clearDragRowClasses, rowSelection],
|
|
941
991
|
);
|
|
942
992
|
|
|
943
993
|
useEffect(
|
|
@@ -1081,7 +1131,12 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
1081
1131
|
onRowClicked={params.onRowClicked}
|
|
1082
1132
|
onRowDataUpdated={onRowDataUpdated}
|
|
1083
1133
|
onRowDoubleClicked={params.onRowDoubleClicked}
|
|
1084
|
-
onRowDragCancel={
|
|
1134
|
+
onRowDragCancel={() => {
|
|
1135
|
+
clearHighlightRowClasses();
|
|
1136
|
+
clearDragRowClasses();
|
|
1137
|
+
multiDragAppliedRef.current = false;
|
|
1138
|
+
multiDragCountRef.current = 0;
|
|
1139
|
+
}}
|
|
1085
1140
|
onRowDragEnd={onRowDragEnd}
|
|
1086
1141
|
onRowDragMove={onRowDragMove}
|
|
1087
1142
|
onSelectionChanged={synchroniseExternalStateToGridSelection}
|
|
@@ -1092,7 +1147,16 @@ export const Grid = <TData extends GridBaseRow = GridBaseRow>({
|
|
|
1092
1147
|
preventDefaultOnContextMenu={true}
|
|
1093
1148
|
quickFilterParser={quickFilterParser}
|
|
1094
1149
|
rowClassRules={params.rowClassRules}
|
|
1095
|
-
rowDragText={
|
|
1150
|
+
rowDragText={
|
|
1151
|
+
params.rowDragText ??
|
|
1152
|
+
(rowSelection === 'multiple'
|
|
1153
|
+
? () => {
|
|
1154
|
+
const count = multiDragCountRef.current;
|
|
1155
|
+
if (count > 1) return `Moving ${count} rows`;
|
|
1156
|
+
return '';
|
|
1157
|
+
}
|
|
1158
|
+
: undefined)
|
|
1159
|
+
}
|
|
1096
1160
|
rowHeight={rowHeight}
|
|
1097
1161
|
rowSelection={
|
|
1098
1162
|
selectable
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
|
|
3
|
+
import { reorderRows } from './gridDragUtil';
|
|
4
|
+
|
|
5
|
+
interface TestRow {
|
|
6
|
+
id: number;
|
|
7
|
+
name: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const makeRows = (...ids: number[]): TestRow[] => ids.map((id) => ({ id, name: `row-${id}` }));
|
|
11
|
+
const row = (id: number): TestRow => ({ id, name: `row-${id}` });
|
|
12
|
+
const ids = (rows: TestRow[]) => rows.map((r) => r.id);
|
|
13
|
+
|
|
14
|
+
describe('reorderRows', () => {
|
|
15
|
+
const rows = makeRows(1, 2, 3, 4, 5);
|
|
16
|
+
|
|
17
|
+
describe('single row move', () => {
|
|
18
|
+
test('move row down (below target)', () => {
|
|
19
|
+
// Drag row 1 below row 3: [2, 3, 1, 4, 5]
|
|
20
|
+
expect(ids(reorderRows(rows, [row(1)], row(3), 1))).toEqual([2, 3, 1, 4, 5]);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('move row up (above target)', () => {
|
|
24
|
+
// Drag row 4 above row 2: [1, 4, 2, 3, 5]
|
|
25
|
+
expect(ids(reorderRows(rows, [row(4)], row(2), -1))).toEqual([1, 4, 2, 3, 5]);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('move to first position', () => {
|
|
29
|
+
// Drag row 3 above row 1: [3, 1, 2, 4, 5]
|
|
30
|
+
expect(ids(reorderRows(rows, [row(3)], row(1), -1))).toEqual([3, 1, 2, 4, 5]);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('move to last position', () => {
|
|
34
|
+
// Drag row 2 below row 5: [1, 3, 4, 5, 2]
|
|
35
|
+
expect(ids(reorderRows(rows, [row(2)], row(5), 1))).toEqual([1, 3, 4, 5, 2]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('move to adjacent position down', () => {
|
|
39
|
+
// Drag row 2 below row 3: [1, 3, 2, 4, 5]
|
|
40
|
+
expect(ids(reorderRows(rows, [row(2)], row(3), 1))).toEqual([1, 3, 2, 4, 5]);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('move to adjacent position up', () => {
|
|
44
|
+
// Drag row 3 above row 2: [1, 3, 2, 4, 5]
|
|
45
|
+
expect(ids(reorderRows(rows, [row(3)], row(2), -1))).toEqual([1, 3, 2, 4, 5]);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('multi-row move', () => {
|
|
50
|
+
test('move multiple contiguous rows down', () => {
|
|
51
|
+
// Drag rows 1,2 below row 4: [3, 4, 1, 2, 5]
|
|
52
|
+
expect(ids(reorderRows(rows, [row(1), row(2)], row(4), 1))).toEqual([3, 4, 1, 2, 5]);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('move multiple contiguous rows up', () => {
|
|
56
|
+
// Drag rows 4,5 above row 2: [1, 4, 5, 2, 3]
|
|
57
|
+
expect(ids(reorderRows(rows, [row(4), row(5)], row(2), -1))).toEqual([1, 4, 5, 2, 3]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('move rows with gaps — gaps are collapsed', () => {
|
|
61
|
+
// Drag rows 1,3,5 below row 4: [2, 4, 1, 3, 5]
|
|
62
|
+
expect(ids(reorderRows(rows, [row(1), row(3), row(5)], row(4), 1))).toEqual([2, 4, 1, 3, 5]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('move rows with gaps above target', () => {
|
|
66
|
+
// Drag rows 2,4 above row 5: [1, 3, 2, 4, 5]
|
|
67
|
+
expect(ids(reorderRows(rows, [row(2), row(4)], row(5), -1))).toEqual([1, 3, 2, 4, 5]);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('move rows with gaps to first position', () => {
|
|
71
|
+
// Drag rows 3,5 above row 1: [3, 5, 1, 2, 4]
|
|
72
|
+
expect(ids(reorderRows(rows, [row(3), row(5)], row(1), -1))).toEqual([3, 5, 1, 2, 4]);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('move rows with gaps to last position', () => {
|
|
76
|
+
// Drag rows 1,3 below row 5: [2, 4, 5, 1, 3]
|
|
77
|
+
expect(ids(reorderRows(rows, [row(1), row(3)], row(5), 1))).toEqual([2, 4, 5, 1, 3]);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('preserves insertion order of movedRows', () => {
|
|
81
|
+
// movedRows given in display order [2,4] should insert as [2,4] not [4,2]
|
|
82
|
+
const result = reorderRows(rows, [row(2), row(4)], row(1), -1);
|
|
83
|
+
expect(ids(result)).toEqual([2, 4, 1, 3, 5]);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe('edge cases', () => {
|
|
88
|
+
test('target is one of the moved rows — returns original array', () => {
|
|
89
|
+
const result = reorderRows(rows, [row(2), row(3)], row(2), 1);
|
|
90
|
+
expect(result).toBe(rows);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('empty movedRows — returns original array', () => {
|
|
94
|
+
const result = reorderRows(rows, [], row(3), 1);
|
|
95
|
+
expect(result).toBe(rows);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test('target not found in rows — returns original array', () => {
|
|
99
|
+
const result = reorderRows(rows, [row(1)], row(99), 1);
|
|
100
|
+
expect(result).toBe(rows);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('single row array — move is no-op (target is the moved row)', () => {
|
|
104
|
+
const single = makeRows(1);
|
|
105
|
+
const result = reorderRows(single, [row(1)], row(1), 1);
|
|
106
|
+
expect(result).toBe(single);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('two row array — swap positions', () => {
|
|
110
|
+
const two = makeRows(1, 2);
|
|
111
|
+
expect(ids(reorderRows(two, [row(1)], row(2), 1))).toEqual([2, 1]);
|
|
112
|
+
expect(ids(reorderRows(two, [row(2)], row(1), -1))).toEqual([2, 1]);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { GridBaseRow } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Reorders rows by removing movedRows from the array and inserting them at the target position.
|
|
5
|
+
* @param rows - The current row array.
|
|
6
|
+
* @param movedRows - Rows to move, in desired insertion order (typically display order).
|
|
7
|
+
* @param targetRow - The row to insert relative to.
|
|
8
|
+
* @param direction - -1 inserts above targetRow, 1 inserts below targetRow.
|
|
9
|
+
* @returns A new array with the rows reordered, or the original array if the operation is a no-op.
|
|
10
|
+
*/
|
|
11
|
+
export function reorderRows<T extends GridBaseRow>(rows: T[], movedRows: T[], targetRow: T, direction: -1 | 1): T[] {
|
|
12
|
+
if (movedRows.length === 0) return rows;
|
|
13
|
+
|
|
14
|
+
const movedIds = new Set(movedRows.map((r) => r.id));
|
|
15
|
+
|
|
16
|
+
// If targetRow is one of the moved rows, no-op
|
|
17
|
+
if (movedIds.has(targetRow.id)) return rows;
|
|
18
|
+
|
|
19
|
+
// Remove moved rows from the array
|
|
20
|
+
const remaining = rows.filter((r) => !movedIds.has(r.id));
|
|
21
|
+
|
|
22
|
+
// Find where to insert relative to the target
|
|
23
|
+
const targetIndex = remaining.findIndex((r) => r.id === targetRow.id);
|
|
24
|
+
if (targetIndex === -1) return rows;
|
|
25
|
+
|
|
26
|
+
const insertIndex = direction === 1 ? targetIndex + 1 : targetIndex;
|
|
27
|
+
|
|
28
|
+
// Insert movedRows at the calculated position
|
|
29
|
+
const result = [...remaining];
|
|
30
|
+
result.splice(insertIndex, 0, ...movedRows);
|
|
31
|
+
return result;
|
|
32
|
+
}
|
package/src/components/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './GridCell';
|
|
|
4
4
|
export * from './GridCellFiller';
|
|
5
5
|
export * from './GridCellMultiEditor';
|
|
6
6
|
export * from './GridCellMultiSelectClassRules';
|
|
7
|
+
export * from './gridDragUtil';
|
|
7
8
|
export * from './gridFilter';
|
|
8
9
|
export * from './gridForm';
|
|
9
10
|
export * from './gridHook';
|
package/src/components/types.ts
CHANGED
|
@@ -8,8 +8,12 @@ export interface GridBaseRow {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export interface GridOnRowDragEndProps<TData extends GridBaseRow> {
|
|
11
|
+
/** The row the user physically grabbed by its drag handle. */
|
|
11
12
|
movedRow: TData;
|
|
13
|
+
/** All rows being moved, ordered by display index. Single-element array when dragging an unselected row. */
|
|
14
|
+
movedRows: TData[];
|
|
12
15
|
targetRow: TData;
|
|
16
|
+
/** -1 = dropped above target, 1 = dropped below target. */
|
|
13
17
|
direction: -1 | 1;
|
|
14
18
|
}
|
|
15
19
|
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
GridProps,
|
|
16
16
|
GridUpdatingContextProvider,
|
|
17
17
|
GridWrapper,
|
|
18
|
+
reorderRows,
|
|
18
19
|
} from '../..';
|
|
19
20
|
import { waitForGridReady } from '../../utils/__tests__/storybookTestUtil';
|
|
20
21
|
|
|
@@ -98,14 +99,8 @@ const GridDragRowTemplate: StoryFn<typeof Grid<ITestRow>> = (props: GridProps<IT
|
|
|
98
99
|
{ id: 1003, position: 'BA', age: 42, height: `5'7"`, desc: 'BAs', dd: '4' },
|
|
99
100
|
]);
|
|
100
101
|
|
|
101
|
-
const onRowDragEnd = useCallback(({
|
|
102
|
-
setRowData((rowData) =>
|
|
103
|
-
rowData.map((r) => {
|
|
104
|
-
if (r.id === movedRow.id) return targetRow;
|
|
105
|
-
if (r.id === targetRow.id) return movedRow;
|
|
106
|
-
return r;
|
|
107
|
-
}),
|
|
108
|
-
);
|
|
102
|
+
const onRowDragEnd = useCallback(({ movedRows, targetRow, direction }: GridOnRowDragEndProps<ITestRow>) => {
|
|
103
|
+
setRowData((rowData) => reorderRows(rowData, movedRows, targetRow, direction));
|
|
109
104
|
}, []);
|
|
110
105
|
|
|
111
106
|
return (
|
|
@@ -128,3 +123,61 @@ const GridDragRowTemplate: StoryFn<typeof Grid<ITestRow>> = (props: GridProps<IT
|
|
|
128
123
|
|
|
129
124
|
export const DragRowSingleSelection = GridDragRowTemplate.bind({});
|
|
130
125
|
DragRowSingleSelection.play = waitForGridReady;
|
|
126
|
+
|
|
127
|
+
const GridDragRowMultiTemplate: StoryFn<typeof Grid<ITestRow>> = (props: GridProps<ITestRow>) => {
|
|
128
|
+
const columnDefs: ColDefT<ITestRow>[] = useMemo(
|
|
129
|
+
() => [
|
|
130
|
+
GridCell({
|
|
131
|
+
field: 'id',
|
|
132
|
+
headerName: 'Id',
|
|
133
|
+
lockVisible: true,
|
|
134
|
+
}),
|
|
135
|
+
GridCell<ITestRow, ITestRow['position']>({
|
|
136
|
+
field: 'position',
|
|
137
|
+
headerName: 'Position',
|
|
138
|
+
}),
|
|
139
|
+
GridCell({
|
|
140
|
+
field: 'age',
|
|
141
|
+
headerName: 'Age',
|
|
142
|
+
}),
|
|
143
|
+
GridCell({
|
|
144
|
+
field: 'desc',
|
|
145
|
+
headerName: 'Description',
|
|
146
|
+
flex: 1,
|
|
147
|
+
}),
|
|
148
|
+
],
|
|
149
|
+
[],
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
const [rowData, setRowData] = useState<ITestRow[]>([
|
|
153
|
+
{ id: 1, position: 'Tester', age: 30, height: `6'4"`, desc: 'Tests application', dd: '1' },
|
|
154
|
+
{ id: 2, position: 'Developer', age: 12, height: `5'3"`, desc: 'Develops application', dd: '2' },
|
|
155
|
+
{ id: 3, position: 'Manager', age: 65, height: `5'9"`, desc: 'Manages', dd: '3' },
|
|
156
|
+
{ id: 4, position: 'BA', age: 42, height: `5'7"`, desc: 'BAs', dd: '4' },
|
|
157
|
+
{ id: 5, position: 'Designer', age: 28, height: `5'6"`, desc: 'Designs', dd: '5' },
|
|
158
|
+
{ id: 6, position: 'DevOps', age: 35, height: `5'11"`, desc: 'Deploys', dd: '6' },
|
|
159
|
+
]);
|
|
160
|
+
|
|
161
|
+
const onRowDragEnd = useCallback(({ movedRows, targetRow, direction }: GridOnRowDragEndProps<ITestRow>) => {
|
|
162
|
+
setRowData((rowData) => reorderRows(rowData, movedRows, targetRow, direction));
|
|
163
|
+
}, []);
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<GridWrapper maxHeight={400}>
|
|
167
|
+
<Grid
|
|
168
|
+
data-testid={'drag-multi'}
|
|
169
|
+
{...props}
|
|
170
|
+
selectable={true}
|
|
171
|
+
rowSelection="multiple"
|
|
172
|
+
animateRows={true}
|
|
173
|
+
columnDefs={columnDefs}
|
|
174
|
+
defaultColDef={{ sortable: false }}
|
|
175
|
+
rowData={rowData}
|
|
176
|
+
onRowDragEnd={onRowDragEnd}
|
|
177
|
+
/>
|
|
178
|
+
</GridWrapper>
|
|
179
|
+
);
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export const DragRowMultiSelection = GridDragRowMultiTemplate.bind({});
|
|
183
|
+
DragRowMultiSelection.play = waitForGridReady;
|
|
@@ -259,6 +259,10 @@ $grid-base-font-size: calc(#{lui.$base-font-size} - 1px);
|
|
|
259
259
|
border-bottom: 2px dashed lui.$andrea;
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
+
.ag-row-dragging {
|
|
263
|
+
opacity: 0.5;
|
|
264
|
+
}
|
|
265
|
+
|
|
262
266
|
.ag-pinned-left-header,
|
|
263
267
|
.ag-pinned-right-header,
|
|
264
268
|
.ag-pinned-right-cols-container,
|