@gravity-ui/dashkit 8.8.0 → 8.8.1-beta.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.
@@ -5,6 +5,8 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
5
5
  state: {
6
6
  isDragging: boolean;
7
7
  isPageHidden: boolean;
8
+ currentDraggingElement: null;
9
+ draggedOverGroup: null;
8
10
  };
9
11
  componentDidMount(): void;
10
12
  componentDidUpdate(): void;
@@ -36,10 +38,14 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
36
38
  getMemoForwardRefCallback: (refIndex: any) => any;
37
39
  mergeGroupsLayout(group: any, newLayout: any, temporaryItem: any): any;
38
40
  reloadItems(): void;
39
- _onStart: () => void;
41
+ _onDragStart: (group: any, _newLayout: any, layoutItem: any) => void;
42
+ _onResizeStart: () => void;
43
+ _onDragExit: () => void;
40
44
  _onStop: (group: any, newLayout: any) => void;
41
- _onDropDragOver: (group: any, e: any) => any;
45
+ _onSharedDrop: (targetGroup: any, newLayout: any, tempItem: any) => void;
46
+ _onExternalDrop: (group: any, newLayout: any, item: any, e: any) => void;
42
47
  _onDrop: (group: any, newLayout: any, item: any, e: any) => false | undefined;
48
+ _onDropDragOver: (group: any, e: any) => any;
43
49
  renderTemporaryPlaceholder(): JSX.Element | null;
44
50
  renderGroup(group: any, renderLayout: any, renderItems: any, offset: number | undefined, groupGridProperties: any): JSX.Element;
45
51
  render(): any;
@@ -56,17 +56,18 @@ class GridLayout extends react_1.default.PureComponent {
56
56
  };
57
57
  this.getMemoGroupCallbacks = (group) => {
58
58
  if (!this._memoCallbacksForGroups[group]) {
59
- const onStart = this._onStart;
59
+ const onDragStart = this._onDragStart.bind(this, group);
60
60
  const onStop = this._onStop.bind(this, group);
61
61
  const onDrop = this._onDrop.bind(this, group);
62
62
  const onDropDragOver = this._onDropDragOver.bind(this, group);
63
+ const onDragExit = this._onDragExit.bind(this, group);
63
64
  this._memoCallbacksForGroups[group] = {
64
- onDragStart: onStart,
65
- onResizeStart: onStart,
65
+ onDragStart,
66
66
  onDragStop: onStop,
67
67
  onResizeStop: onStop,
68
- onDrop: onDrop,
68
+ onDrop,
69
69
  onDropDragOver,
70
+ onDragExit,
70
71
  };
71
72
  }
72
73
  return this._memoCallbacksForGroups[group];
@@ -93,48 +94,128 @@ class GridLayout extends react_1.default.PureComponent {
93
94
  }
94
95
  return this._memoForwardedPluginRef[refIndex];
95
96
  };
96
- this._onStart = () => {
97
+ this._onDragStart = (group, _newLayout, layoutItem) => {
97
98
  if (this.temporaryLayout)
98
99
  return;
99
- this.setState({ isDragging: true });
100
+ let currentDraggingElement = this.state.currentDraggingElement;
101
+ if (!currentDraggingElement) {
102
+ const _id = layoutItem.i;
103
+ const item = this.context.config.items.find(({ id }) => id === _id);
104
+ currentDraggingElement = [group, layoutItem, item];
105
+ }
106
+ if (this.context.dragOverPlugin) {
107
+ this.setState({ isDragging: true });
108
+ }
109
+ else {
110
+ this.setState({
111
+ isDragging: true,
112
+ currentDraggingElement,
113
+ draggedOverGroup: group,
114
+ });
115
+ }
116
+ };
117
+ this._onResizeStart = () => {
118
+ this.setState({
119
+ isDragging: true,
120
+ });
121
+ };
122
+ this._onDragExit = () => {
123
+ this.setState({
124
+ draggedOverGroup: null,
125
+ });
100
126
  };
101
127
  this._onStop = (group, newLayout) => {
102
128
  const { layoutChange, onDrop, temporaryLayout } = this.context;
129
+ const { draggedOverGroup, currentDraggingElement } = this.state;
130
+ if (currentDraggingElement &&
131
+ draggedOverGroup !== null &&
132
+ draggedOverGroup !== currentDraggingElement[0]) {
133
+ // Skipping layout update when change event called for source grid
134
+ // and waiting _onDrop
135
+ return;
136
+ }
103
137
  const groupedLayout = this.mergeGroupsLayout(group, newLayout);
138
+ this.setState({
139
+ isDragging: false,
140
+ currentDraggingElement: null,
141
+ draggedOverGroup: null,
142
+ });
104
143
  if (temporaryLayout) {
105
144
  onDrop === null || onDrop === void 0 ? void 0 : onDrop(groupedLayout, groupedLayout.find(({ i }) => i === constants_1.TEMPORARY_ITEM_ID));
106
145
  }
107
146
  else {
108
147
  layoutChange(groupedLayout);
109
148
  }
110
- this.setState({ isDragging: false });
111
149
  };
112
- this._onDropDragOver = (group, e) => {
113
- const { editMode, dragOverPlugin } = this.context;
114
- if (!editMode || !dragOverPlugin) {
115
- return false;
150
+ this._onSharedDrop = (targetGroup, newLayout, tempItem) => {
151
+ const { currentDraggingElement } = this.state;
152
+ const { layoutChange } = this.context;
153
+ if (!currentDraggingElement) {
154
+ return;
116
155
  }
117
- const { properties, layout } = this.getLayoutAndPropsByGroup(group);
118
- return this.context.onDropDragOver(e, properties, layout);
156
+ const [, sourceItem] = currentDraggingElement;
157
+ const groupedLayout = this.mergeGroupsLayout(targetGroup, newLayout, tempItem).map((item) => {
158
+ if (item.i === sourceItem.i) {
159
+ const copy = Object.assign({}, tempItem);
160
+ delete copy.parent;
161
+ if (targetGroup !== constants_1.DEFAULT_GROUP) {
162
+ copy.parent = targetGroup;
163
+ }
164
+ copy.i = sourceItem.i;
165
+ return copy;
166
+ }
167
+ return item;
168
+ });
169
+ this.setState({
170
+ isDragging: false,
171
+ currentDraggingElement: null,
172
+ draggedOverGroup: null,
173
+ });
174
+ layoutChange(groupedLayout);
175
+ };
176
+ this._onExternalDrop = (group, newLayout, item, e) => {
177
+ const { onDrop } = this.context;
178
+ if (group !== constants_1.DEFAULT_GROUP) {
179
+ item.parent = group;
180
+ }
181
+ const groupedLayout = this.mergeGroupsLayout(group, newLayout, item);
182
+ this.setState({ isDragging: false });
183
+ onDrop === null || onDrop === void 0 ? void 0 : onDrop(groupedLayout, item, e);
119
184
  };
120
185
  this._onDrop = (group, newLayout, item, e) => {
121
- if (!item) {
186
+ if (!item || !this.context.editMode) {
122
187
  return false;
123
188
  }
124
- const { editMode, onDrop } = this.context;
125
- if (!editMode) {
189
+ const { draggedOverGroup, currentDraggingElement } = this.state;
190
+ if (currentDraggingElement && draggedOverGroup === group) {
191
+ this._onSharedDrop(group, newLayout, item);
192
+ }
193
+ else {
194
+ this._onExternalDrop(group, newLayout, item, e);
195
+ }
196
+ };
197
+ this._onDropDragOver = (group, e) => {
198
+ const { editMode, dragOverPlugin, onDropDragOver } = this.context;
199
+ const { currentDraggingElement } = this.state;
200
+ if (!editMode || (!dragOverPlugin && !currentDraggingElement)) {
126
201
  return false;
127
202
  }
128
- if (group !== constants_1.DEFAULT_GROUP) {
129
- item.parent = group;
203
+ const { properties, layout } = this.getLayoutAndPropsByGroup(group);
204
+ if (currentDraggingElement) {
205
+ const [, { h, w, i }, { type }] = currentDraggingElement;
206
+ return onDropDragOver(e, properties, layout, { h, w, i, type });
130
207
  }
131
- const groupedLayout = this.mergeGroupsLayout(group, newLayout, item);
132
- onDrop === null || onDrop === void 0 ? void 0 : onDrop(groupedLayout, item, e);
208
+ if (dragOverPlugin) {
209
+ return onDropDragOver(e, properties, layout);
210
+ }
211
+ return false;
133
212
  };
134
213
  this.pluginsRefs = [];
135
214
  this.state = {
136
215
  isDragging: false,
137
216
  isPageHidden: false,
217
+ currentDraggingElement: null,
218
+ draggedOverGroup: null,
138
219
  };
139
220
  }
140
221
  componentDidMount() {
@@ -201,6 +282,7 @@ class GridLayout extends react_1.default.PureComponent {
201
282
  }
202
283
  renderGroup(group, renderLayout, renderItems, offset = 0, groupGridProperties) {
203
284
  const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
285
+ const { currentDraggingElement } = this.state;
204
286
  const properties = groupGridProperties
205
287
  ? groupGridProperties(Object.assign({}, registerManager.gridLayout))
206
288
  : registerManager.gridLayout;
@@ -209,13 +291,12 @@ class GridLayout extends react_1.default.PureComponent {
209
291
  compactType = 'horizontal';
210
292
  }
211
293
  const { callbacks, layout } = this.getMemoGroupProps(group, renderLayout, properties);
212
- return (react_1.default.createElement(ReactGridLayout_1.Layout, Object.assign({}, properties, { compactType: compactType, layout: layout, key: `group_${group}`, isDraggable: editMode, isResizable: editMode, onDragStart: callbacks.onDragStart, onDragStop: callbacks.onDragStop, onResizeStart: callbacks.onResizeStart, onResizeStop: callbacks.onResizeStop }, (draggableHandleClassName
294
+ const hasSharedDragItem = Boolean(currentDraggingElement && currentDraggingElement[0] !== group);
295
+ return (react_1.default.createElement(ReactGridLayout_1.Layout, Object.assign({}, properties, { compactType: compactType, layout: layout, key: `group_${group}`, isDraggable: editMode, isResizable: editMode, onResizeStart: this._onResizeStart, onDragStart: callbacks.onDragStart, onDragStop: callbacks.onDragStop, onResizeStop: callbacks.onResizeStop, onDragExit: callbacks.onDragExit, onDropDragOver: callbacks.onDropDragOver, onDrop: callbacks.onDrop, hasSharedDragItem: hasSharedDragItem }, (draggableHandleClassName
213
296
  ? { draggableHandle: `.${draggableHandleClassName}` }
214
297
  : null), (outerDnDEnable
215
298
  ? {
216
299
  isDroppable: true,
217
- onDropDragOver: callbacks.onDropDragOver,
218
- onDrop: callbacks.onDrop,
219
300
  }
220
301
  : null), { draggableCancel: `.${constants_1.OVERLAY_CONTROLS_CLASS_NAME}` }),
221
302
  renderItems.map((item, i) => {
@@ -5,62 +5,213 @@ const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const react_grid_layout_1 = tslib_1.__importStar(require("react-grid-layout"));
7
7
  const constants_1 = require("../../constants");
8
+ const { compact, compactType } = react_grid_layout_1.utils;
9
+ // pointer-events disabled to make mouse events be able to passthrought
10
+ // while dragging element out of the grid the mouse positioned over grid item
11
+ // so there is only two ways to get it, calculate rect or just give browser make his work
12
+ const DRAGGING_PLACEHOLDER_STYLE = { pointerEvents: 'none' };
13
+ // when shared element is dragged over another group we still creating placeholder for it
14
+ // cause react-grid-layout is havely dependent on this element
15
+ // while in future there will be some wey not to create dummy div and hide it with opacity
16
+ // this hack is all what i've got now
17
+ const DRAGGING_PLACEHOLDER_HIDDEN_STYLE = Object.assign(Object.assign({}, DRAGGING_PLACEHOLDER_STYLE), { opacity: 0 });
8
18
  class DragOverLayout extends react_grid_layout_1.default {
9
19
  constructor(...args) {
10
20
  super(...args);
11
- this.dragReset = () => {
21
+ this._isMouseOver = true;
22
+ this._savedDragoutState = null;
23
+ // Reset placeholder when item dragged from outside
24
+ this.resetExternalPlaceholder = () => {
12
25
  if (this.dragEnterCounter) {
13
26
  this.dragEnterCounter = 0;
14
27
  this.removeDroppingPlaceholder();
15
28
  }
16
29
  };
30
+ // Hide placeholder when element is dragged out
31
+ this.hideLocalPlaceholder = (i) => {
32
+ const { layout } = this.state;
33
+ const { cols } = this.props;
34
+ const savedLayout = layout.map((item) => (Object.assign({}, item)));
35
+ let hiddenElement;
36
+ const newLayout = compact(layout.filter((item) => {
37
+ if (item.i === i) {
38
+ hiddenElement = item;
39
+ return false;
40
+ }
41
+ return true;
42
+ }), compactType(this.props), cols);
43
+ if (hiddenElement) {
44
+ newLayout.push(hiddenElement);
45
+ }
46
+ this.setState({
47
+ activeDrag: null,
48
+ layout: newLayout,
49
+ });
50
+ this.resetExternalPlaceholder();
51
+ return { layout: savedLayout, id: hiddenElement.i };
52
+ };
53
+ this.extendedOnDrag = (i, x, y, sintEv) => {
54
+ var _a, _b;
55
+ if (!this._isMouseOver) {
56
+ if (!this._savedDragoutState) {
57
+ this._savedDragoutState = this.hideLocalPlaceholder(i);
58
+ (_b = (_a = this.props).onDragExit) === null || _b === void 0 ? void 0 : _b.call(_a);
59
+ }
60
+ return;
61
+ }
62
+ // parent onDrag will show new placeholder again
63
+ this.parentOnDrag(i, x, y, sintEv);
64
+ };
65
+ this.extendedOnDragStop = (i, x, y, sintEv) => {
66
+ // Restoring layout if item was dropped outside of the grid and wasn't captured
67
+ if (this._savedDragoutState) {
68
+ const savedLayout = this._savedDragoutState.layout;
69
+ const l = react_grid_layout_1.utils.getLayoutItem(savedLayout, i);
70
+ // Create placeholder (display only)
71
+ const placeholder = {
72
+ w: l.w,
73
+ h: l.h,
74
+ x: l.x,
75
+ y: l.y,
76
+ placeholder: true,
77
+ i: i,
78
+ };
79
+ this.setState({
80
+ layout: savedLayout,
81
+ activeDrag: placeholder,
82
+ }, () => {
83
+ this.parentOnDragStop(i, x, y, sintEv);
84
+ });
85
+ this._savedDragoutState = null;
86
+ }
87
+ else {
88
+ this.parentOnDragStop(i, x, y, sintEv);
89
+ }
90
+ };
91
+ this.extendedOnDragEnter = (...args) => {
92
+ this._isMouseOver = true;
93
+ return this.parentOnDragEnter(...args);
94
+ };
95
+ this.extendedOnDragLeave = (...args) => {
96
+ this._isMouseOver = true;
97
+ return this.parentOnDragLeave(...args);
98
+ };
99
+ // Proxy mouse events -> drag methods for dnd between groups
100
+ this.mouseEnterHandler = (e) => {
101
+ this._isMouseOver = true;
102
+ if (this.props.hasSharedDragItem) {
103
+ this.parentOnDragEnter(e);
104
+ }
105
+ };
17
106
  this.mouseLeaveHandler = (e) => {
18
- var _a;
19
- const rect = ((_a = this.props.innerRef) === null || _a === void 0 ? void 0 : _a.current.getBoundingClientRect()) || {};
20
- if (rect.bottom <= e.clientY ||
21
- rect.top >= e.clientY ||
22
- rect.left >= e.clientX ||
23
- rect.right <= e.clientX) {
24
- this.dragReset();
107
+ this._isMouseOver = false;
108
+ if (this.props.hasSharedDragItem) {
109
+ this.parentOnDragLeave(e);
25
110
  }
26
111
  };
27
- this.parentOnDrag = this.onDrag;
28
- this.onDrag = (i, x, y, sintE) => {
29
- this.parentOnDrag(i, x, y, sintE);
30
- this.mouseLeaveHandler(sintE.e);
112
+ this.mouseMoveHandler = (e) => {
113
+ this._isMouseOver = true;
114
+ if (this.props.hasSharedDragItem) {
115
+ this.onDragOver(e);
116
+ }
117
+ };
118
+ this.mouseUpHandler = (e) => {
119
+ var _a, _b;
120
+ this._isMouseOver = true;
121
+ if (this.props.hasSharedDragItem) {
122
+ e.preventDefault();
123
+ const { droppingItem } = this.props;
124
+ const { layout } = this.state;
125
+ const item = layout.find((l) => l.i === droppingItem.i);
126
+ // reset dragEnter counter on drop
127
+ this.resetExternalPlaceholder();
128
+ (_b = (_a = this.props).onDrop) === null || _b === void 0 ? void 0 : _b.call(_a, layout, item, e);
129
+ }
31
130
  };
131
+ this.parentOnDrag = this.onDrag;
132
+ this.onDrag = this.extendedOnDrag;
133
+ this.parentOnDragStop = this.onDragStop;
134
+ this.onDragStop = this.extendedOnDragStop;
135
+ this.parentOnDragEnter = this.onDragEnter;
136
+ this.onDragEnter = this.extendedOnDragEnter;
137
+ this.parentOnDragLeave = this.onDragLeave;
138
+ this.onDragLeave = this.extendedOnDragLeave;
32
139
  }
33
140
  componentDidMount() {
34
141
  var _a;
35
142
  (_a = super.componentDidMount) === null || _a === void 0 ? void 0 : _a.call(this);
36
- window.addEventListener('dragend', this.dragReset);
143
+ // If cursor is moved out of the window there is a bug
144
+ // which leaves placeholder element in grid, this action needed to reset this state
145
+ window.addEventListener('dragend', this.resetExternalPlaceholder);
146
+ const innerElement = this.getInnerElement();
147
+ if (innerElement) {
148
+ innerElement.addEventListener('mouseup', this.mouseUpHandler);
149
+ innerElement.addEventListener('mouseenter', this.mouseEnterHandler);
150
+ innerElement.addEventListener('mouseleave', this.mouseLeaveHandler);
151
+ innerElement.addEventListener('mousemove', this.mouseMoveHandler);
152
+ }
37
153
  }
38
154
  componentWillUnmount() {
39
- window.removeEventListener('dragend', this.dragReset);
155
+ window.removeEventListener('dragend', this.resetExternalPlaceholder);
156
+ const innerElement = this.getInnerElement();
157
+ if (innerElement) {
158
+ innerElement.removeEventListener('mouseup', this.mouseUpHandler);
159
+ innerElement.removeEventListener('mouseenter', this.mouseEnterHandler);
160
+ innerElement.removeEventListener('mouseleave', this.mouseLeaveHandler);
161
+ innerElement.removeEventListener('mousemove', this.mouseMoveHandler);
162
+ }
163
+ // Resetting instance props
164
+ this._savedDragoutState = null;
40
165
  }
166
+ // react-grid-layout doens't calculate it's height when last element is removed
167
+ // and just keeps the previous value
168
+ // so for autosize to work in that case we are resetting it's height value
41
169
  containerHeight() {
42
170
  if (this.props.autoSize && this.state.layout.length === 0) {
43
- return 'unset';
171
+ return;
44
172
  }
173
+ // eslint-disable-next-line consistent-return
45
174
  return super.containerHeight();
46
175
  }
47
- processGridItem(child, isDroppingItem) {
176
+ // innerRef is passed by WithProvider without this wrapper there are only
177
+ // * findDOMNode - deprecated
178
+ // * rewrite whole ReactGridLayout.render method
179
+ // so in that case don't try to use this class on it's own
180
+ // or pass innerRef: React.MutableRef as it's not optional prop
181
+ getInnerElement() {
48
182
  var _a;
183
+ return ((_a = this.props.innerRef) === null || _a === void 0 ? void 0 : _a.current) || null;
184
+ }
185
+ // Drop item from outside gets 0,0 droppingPosition
186
+ // centering cursor on newly creted grid item
187
+ // And cause grid-layout using it's own GridItem to make it look
188
+ // like overlay adding className
189
+ processGridItem(child, isDroppingItem) {
190
+ var _a, _b, _c;
49
191
  const gridItem = (_a = super.processGridItem) === null || _a === void 0 ? void 0 : _a.call(this, child, isDroppingItem);
192
+ if (!gridItem) {
193
+ return gridItem;
194
+ }
195
+ const { props: itemProps } = gridItem;
50
196
  if (isDroppingItem) {
51
- // Drop item from outside gets 0,0 droppingPosition
52
- // centering cursor on newly creted grid item
53
- // And cause grid-layout using it's own GridItem to make it look
54
- // like overlay adding className
55
- if (!gridItem)
56
- return null;
57
- const { props } = gridItem;
58
- const { containerWidth, cols, w, h, rowHeight, margin, transformScale } = props;
197
+ const { containerWidth, cols, w, h, rowHeight, margin, transformScale, droppingPosition, } = itemProps;
59
198
  const leftOffset = (((containerWidth / cols) * w) / 2 || 0) * transformScale;
60
199
  const topOffset = ((h * rowHeight + (h - 1) * margin[1]) / 2 || 0) * transformScale;
200
+ const dragStyles = this.props.hasSharedDragItem
201
+ ? DRAGGING_PLACEHOLDER_HIDDEN_STYLE
202
+ : DRAGGING_PLACEHOLDER_STYLE;
203
+ // React.cloneElement is just cleaner then copy-paste whole processGridItem method
61
204
  return react_1.default.cloneElement(gridItem, {
205
+ style: itemProps.style ? Object.assign(Object.assign({}, itemProps.style), dragStyles) : dragStyles,
62
206
  className: constants_1.OVERLAY_CLASS_NAME,
63
- droppingPosition: Object.assign(Object.assign({}, props.droppingPosition), { left: props.droppingPosition.left - leftOffset, top: props.droppingPosition.top - topOffset }),
207
+ droppingPosition: Object.assign(Object.assign({}, droppingPosition), { left: droppingPosition.left - leftOffset, top: droppingPosition.top - topOffset }),
208
+ });
209
+ }
210
+ else if (itemProps.i === ((_b = this.state.activeDrag) === null || _b === void 0 ? void 0 : _b.i) ||
211
+ itemProps.i === ((_c = this._savedDragoutState) === null || _c === void 0 ? void 0 : _c.id)) {
212
+ const dragStyles = DRAGGING_PLACEHOLDER_STYLE;
213
+ return react_1.default.cloneElement(gridItem, {
214
+ style: itemProps.style ? Object.assign(Object.assign({}, itemProps.style), dragStyles) : dragStyles,
64
215
  });
65
216
  }
66
217
  return gridItem;
@@ -32,7 +32,7 @@ function useMemoStateContext(props) {
32
32
  (0, isEqual_1.default)(groups, props.groups))) {
33
33
  props.onChange({ config, itemsStateAndParams, groups });
34
34
  }
35
- }, [props.config, props.itemsStateAndParams, props.onChange]);
35
+ }, [props.config, props.groups, props.itemsStateAndParams, props.onChange]);
36
36
  // каллбэк вызывающийся при изменение лэйаута сетки, первым аргументом приходит актуальный конфиг лэйаута,
37
37
  // т.е. если на текущей сетке есть виджеты, с активированной опцией автовысоты, их параметр "h" будет
38
38
  // "подстроенный"; чтобы, для сохранения в сторе "ушли" значения без учёта подстройки (как если бы у этих
@@ -40,7 +40,17 @@ function useMemoStateContext(props) {
40
40
  const onLayoutChange = react_1.default.useCallback((layout) => {
41
41
  const currentInnerLayout = layout.map((item) => {
42
42
  if (item.i in originalLayouts.current) {
43
- return Object.assign(Object.assign({}, originalLayouts.current[item.i]), { w: item.w, x: item.x, y: item.y });
43
+ // eslint-disable-next-line no-unused-vars
44
+ const _a = originalLayouts.current[item.i], { parent } = _a, originalCopy = tslib_1.__rest(_a, ["parent"]);
45
+ // Updating original if parent has changed and saving copy as original
46
+ // or leaving default
47
+ if (item.parent) {
48
+ originalCopy.parent = item.parent;
49
+ }
50
+ originalCopy.w = item.w;
51
+ originalCopy.x = item.x;
52
+ originalCopy.y = item.y;
53
+ return originalCopy;
44
54
  }
45
55
  else {
46
56
  return Object.assign({}, item);
@@ -237,16 +247,24 @@ function useMemoStateContext(props) {
237
247
  return null;
238
248
  }
239
249
  }, [dragProps, props.registerManager]);
240
- const onDropDragOver = react_1.default.useCallback((_e, gridProps, groupLayout) => {
250
+ const onDropDragOver = react_1.default.useCallback((_e, gridProps, groupLayout, sharedItem) => {
241
251
  if (temporaryLayout) {
242
252
  resetTemporaryLayout();
243
253
  return false;
244
254
  }
245
- if (!dragOverPlugin) {
255
+ let defaultLayout;
256
+ if (sharedItem) {
257
+ const { type, h, w } = sharedItem;
258
+ const _defaults = props.registerManager.getItem(type);
259
+ defaultLayout = _defaults ? Object.assign(Object.assign({}, _defaults.defaultLayout), { h, w }) : { h, w };
260
+ }
261
+ else if (dragOverPlugin) {
262
+ defaultLayout = dragOverPlugin.defaultLayout;
263
+ }
264
+ else {
246
265
  return false;
247
266
  }
248
267
  let maxW = gridProps.cols;
249
- const { defaultLayout } = dragOverPlugin;
250
268
  const maxH = Math.min(gridProps.maxRows || Infinity, defaultLayout.maxH || Infinity);
251
269
  if (gridProps.compactType === common_1.COMPACT_TYPE_HORIZONTAL_NOWRAP) {
252
270
  maxW = groupLayout.reduce((memo, item) => memo - item.w, gridProps.cols);
@@ -257,7 +275,7 @@ function useMemoStateContext(props) {
257
275
  maxH < defaultLayout.minH) {
258
276
  return false;
259
277
  }
260
- const { h = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.h) || common_1.DEFAULT_WIDGET_HEIGHT, w = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.w) || common_1.DEFAULT_WIDGET_WIDTH, } = dragProps.layout || {};
278
+ const { h = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.h) || common_1.DEFAULT_WIDGET_HEIGHT, w = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.w) || common_1.DEFAULT_WIDGET_WIDTH, } = (dragProps === null || dragProps === void 0 ? void 0 : dragProps.layout) || {};
261
279
  return {
262
280
  h: maxH ? Math.min(h, maxH) : h,
263
281
  w: maxW ? Math.min(w, maxW) : w,
@@ -5,6 +5,8 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
5
5
  state: {
6
6
  isDragging: boolean;
7
7
  isPageHidden: boolean;
8
+ currentDraggingElement: null;
9
+ draggedOverGroup: null;
8
10
  };
9
11
  componentDidMount(): void;
10
12
  componentDidUpdate(): void;
@@ -36,10 +38,14 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
36
38
  getMemoForwardRefCallback: (refIndex: any) => any;
37
39
  mergeGroupsLayout(group: any, newLayout: any, temporaryItem: any): any;
38
40
  reloadItems(): void;
39
- _onStart: () => void;
41
+ _onDragStart: (group: any, _newLayout: any, layoutItem: any) => void;
42
+ _onResizeStart: () => void;
43
+ _onDragExit: () => void;
40
44
  _onStop: (group: any, newLayout: any) => void;
41
- _onDropDragOver: (group: any, e: any) => any;
45
+ _onSharedDrop: (targetGroup: any, newLayout: any, tempItem: any) => void;
46
+ _onExternalDrop: (group: any, newLayout: any, item: any, e: any) => void;
42
47
  _onDrop: (group: any, newLayout: any, item: any, e: any) => false | undefined;
48
+ _onDropDragOver: (group: any, e: any) => any;
43
49
  renderTemporaryPlaceholder(): JSX.Element | null;
44
50
  renderGroup(group: any, renderLayout: any, renderItems: any, offset: number | undefined, groupGridProperties: any): JSX.Element;
45
51
  render(): any;
@@ -53,17 +53,18 @@ class GridLayout extends React.PureComponent {
53
53
  };
54
54
  this.getMemoGroupCallbacks = (group) => {
55
55
  if (!this._memoCallbacksForGroups[group]) {
56
- const onStart = this._onStart;
56
+ const onDragStart = this._onDragStart.bind(this, group);
57
57
  const onStop = this._onStop.bind(this, group);
58
58
  const onDrop = this._onDrop.bind(this, group);
59
59
  const onDropDragOver = this._onDropDragOver.bind(this, group);
60
+ const onDragExit = this._onDragExit.bind(this, group);
60
61
  this._memoCallbacksForGroups[group] = {
61
- onDragStart: onStart,
62
- onResizeStart: onStart,
62
+ onDragStart,
63
63
  onDragStop: onStop,
64
64
  onResizeStop: onStop,
65
- onDrop: onDrop,
65
+ onDrop,
66
66
  onDropDragOver,
67
+ onDragExit,
67
68
  };
68
69
  }
69
70
  return this._memoCallbacksForGroups[group];
@@ -90,48 +91,128 @@ class GridLayout extends React.PureComponent {
90
91
  }
91
92
  return this._memoForwardedPluginRef[refIndex];
92
93
  };
93
- this._onStart = () => {
94
+ this._onDragStart = (group, _newLayout, layoutItem) => {
94
95
  if (this.temporaryLayout)
95
96
  return;
96
- this.setState({ isDragging: true });
97
+ let currentDraggingElement = this.state.currentDraggingElement;
98
+ if (!currentDraggingElement) {
99
+ const _id = layoutItem.i;
100
+ const item = this.context.config.items.find(({ id }) => id === _id);
101
+ currentDraggingElement = [group, layoutItem, item];
102
+ }
103
+ if (this.context.dragOverPlugin) {
104
+ this.setState({ isDragging: true });
105
+ }
106
+ else {
107
+ this.setState({
108
+ isDragging: true,
109
+ currentDraggingElement,
110
+ draggedOverGroup: group,
111
+ });
112
+ }
113
+ };
114
+ this._onResizeStart = () => {
115
+ this.setState({
116
+ isDragging: true,
117
+ });
118
+ };
119
+ this._onDragExit = () => {
120
+ this.setState({
121
+ draggedOverGroup: null,
122
+ });
97
123
  };
98
124
  this._onStop = (group, newLayout) => {
99
125
  const { layoutChange, onDrop, temporaryLayout } = this.context;
126
+ const { draggedOverGroup, currentDraggingElement } = this.state;
127
+ if (currentDraggingElement &&
128
+ draggedOverGroup !== null &&
129
+ draggedOverGroup !== currentDraggingElement[0]) {
130
+ // Skipping layout update when change event called for source grid
131
+ // and waiting _onDrop
132
+ return;
133
+ }
100
134
  const groupedLayout = this.mergeGroupsLayout(group, newLayout);
135
+ this.setState({
136
+ isDragging: false,
137
+ currentDraggingElement: null,
138
+ draggedOverGroup: null,
139
+ });
101
140
  if (temporaryLayout) {
102
141
  onDrop === null || onDrop === void 0 ? void 0 : onDrop(groupedLayout, groupedLayout.find(({ i }) => i === TEMPORARY_ITEM_ID));
103
142
  }
104
143
  else {
105
144
  layoutChange(groupedLayout);
106
145
  }
107
- this.setState({ isDragging: false });
108
146
  };
109
- this._onDropDragOver = (group, e) => {
110
- const { editMode, dragOverPlugin } = this.context;
111
- if (!editMode || !dragOverPlugin) {
112
- return false;
147
+ this._onSharedDrop = (targetGroup, newLayout, tempItem) => {
148
+ const { currentDraggingElement } = this.state;
149
+ const { layoutChange } = this.context;
150
+ if (!currentDraggingElement) {
151
+ return;
113
152
  }
114
- const { properties, layout } = this.getLayoutAndPropsByGroup(group);
115
- return this.context.onDropDragOver(e, properties, layout);
153
+ const [, sourceItem] = currentDraggingElement;
154
+ const groupedLayout = this.mergeGroupsLayout(targetGroup, newLayout, tempItem).map((item) => {
155
+ if (item.i === sourceItem.i) {
156
+ const copy = Object.assign({}, tempItem);
157
+ delete copy.parent;
158
+ if (targetGroup !== DEFAULT_GROUP) {
159
+ copy.parent = targetGroup;
160
+ }
161
+ copy.i = sourceItem.i;
162
+ return copy;
163
+ }
164
+ return item;
165
+ });
166
+ this.setState({
167
+ isDragging: false,
168
+ currentDraggingElement: null,
169
+ draggedOverGroup: null,
170
+ });
171
+ layoutChange(groupedLayout);
172
+ };
173
+ this._onExternalDrop = (group, newLayout, item, e) => {
174
+ const { onDrop } = this.context;
175
+ if (group !== DEFAULT_GROUP) {
176
+ item.parent = group;
177
+ }
178
+ const groupedLayout = this.mergeGroupsLayout(group, newLayout, item);
179
+ this.setState({ isDragging: false });
180
+ onDrop === null || onDrop === void 0 ? void 0 : onDrop(groupedLayout, item, e);
116
181
  };
117
182
  this._onDrop = (group, newLayout, item, e) => {
118
- if (!item) {
183
+ if (!item || !this.context.editMode) {
119
184
  return false;
120
185
  }
121
- const { editMode, onDrop } = this.context;
122
- if (!editMode) {
186
+ const { draggedOverGroup, currentDraggingElement } = this.state;
187
+ if (currentDraggingElement && draggedOverGroup === group) {
188
+ this._onSharedDrop(group, newLayout, item);
189
+ }
190
+ else {
191
+ this._onExternalDrop(group, newLayout, item, e);
192
+ }
193
+ };
194
+ this._onDropDragOver = (group, e) => {
195
+ const { editMode, dragOverPlugin, onDropDragOver } = this.context;
196
+ const { currentDraggingElement } = this.state;
197
+ if (!editMode || (!dragOverPlugin && !currentDraggingElement)) {
123
198
  return false;
124
199
  }
125
- if (group !== DEFAULT_GROUP) {
126
- item.parent = group;
200
+ const { properties, layout } = this.getLayoutAndPropsByGroup(group);
201
+ if (currentDraggingElement) {
202
+ const [, { h, w, i }, { type }] = currentDraggingElement;
203
+ return onDropDragOver(e, properties, layout, { h, w, i, type });
127
204
  }
128
- const groupedLayout = this.mergeGroupsLayout(group, newLayout, item);
129
- onDrop === null || onDrop === void 0 ? void 0 : onDrop(groupedLayout, item, e);
205
+ if (dragOverPlugin) {
206
+ return onDropDragOver(e, properties, layout);
207
+ }
208
+ return false;
130
209
  };
131
210
  this.pluginsRefs = [];
132
211
  this.state = {
133
212
  isDragging: false,
134
213
  isPageHidden: false,
214
+ currentDraggingElement: null,
215
+ draggedOverGroup: null,
135
216
  };
136
217
  }
137
218
  componentDidMount() {
@@ -198,6 +279,7 @@ class GridLayout extends React.PureComponent {
198
279
  }
199
280
  renderGroup(group, renderLayout, renderItems, offset = 0, groupGridProperties) {
200
281
  const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
282
+ const { currentDraggingElement } = this.state;
201
283
  const properties = groupGridProperties
202
284
  ? groupGridProperties(Object.assign({}, registerManager.gridLayout))
203
285
  : registerManager.gridLayout;
@@ -206,13 +288,12 @@ class GridLayout extends React.PureComponent {
206
288
  compactType = 'horizontal';
207
289
  }
208
290
  const { callbacks, layout } = this.getMemoGroupProps(group, renderLayout, properties);
209
- return (React.createElement(Layout, Object.assign({}, properties, { compactType: compactType, layout: layout, key: `group_${group}`, isDraggable: editMode, isResizable: editMode, onDragStart: callbacks.onDragStart, onDragStop: callbacks.onDragStop, onResizeStart: callbacks.onResizeStart, onResizeStop: callbacks.onResizeStop }, (draggableHandleClassName
291
+ const hasSharedDragItem = Boolean(currentDraggingElement && currentDraggingElement[0] !== group);
292
+ return (React.createElement(Layout, Object.assign({}, properties, { compactType: compactType, layout: layout, key: `group_${group}`, isDraggable: editMode, isResizable: editMode, onResizeStart: this._onResizeStart, onDragStart: callbacks.onDragStart, onDragStop: callbacks.onDragStop, onResizeStop: callbacks.onResizeStop, onDragExit: callbacks.onDragExit, onDropDragOver: callbacks.onDropDragOver, onDrop: callbacks.onDrop, hasSharedDragItem: hasSharedDragItem }, (draggableHandleClassName
210
293
  ? { draggableHandle: `.${draggableHandleClassName}` }
211
294
  : null), (outerDnDEnable
212
295
  ? {
213
296
  isDroppable: true,
214
- onDropDragOver: callbacks.onDropDragOver,
215
- onDrop: callbacks.onDrop,
216
297
  }
217
298
  : null), { draggableCancel: `.${OVERLAY_CONTROLS_CLASS_NAME}` }),
218
299
  renderItems.map((item, i) => {
@@ -1,62 +1,213 @@
1
1
  import React from 'react';
2
- import ReactGridLayout, { WidthProvider } from 'react-grid-layout';
2
+ import ReactGridLayout, { WidthProvider, utils } from 'react-grid-layout';
3
3
  import { OVERLAY_CLASS_NAME } from '../../constants';
4
+ const { compact, compactType } = utils;
5
+ // pointer-events disabled to make mouse events be able to passthrought
6
+ // while dragging element out of the grid the mouse positioned over grid item
7
+ // so there is only two ways to get it, calculate rect or just give browser make his work
8
+ const DRAGGING_PLACEHOLDER_STYLE = { pointerEvents: 'none' };
9
+ // when shared element is dragged over another group we still creating placeholder for it
10
+ // cause react-grid-layout is havely dependent on this element
11
+ // while in future there will be some wey not to create dummy div and hide it with opacity
12
+ // this hack is all what i've got now
13
+ const DRAGGING_PLACEHOLDER_HIDDEN_STYLE = Object.assign(Object.assign({}, DRAGGING_PLACEHOLDER_STYLE), { opacity: 0 });
4
14
  class DragOverLayout extends ReactGridLayout {
5
15
  constructor(...args) {
6
16
  super(...args);
7
- this.dragReset = () => {
17
+ this._isMouseOver = true;
18
+ this._savedDragoutState = null;
19
+ // Reset placeholder when item dragged from outside
20
+ this.resetExternalPlaceholder = () => {
8
21
  if (this.dragEnterCounter) {
9
22
  this.dragEnterCounter = 0;
10
23
  this.removeDroppingPlaceholder();
11
24
  }
12
25
  };
26
+ // Hide placeholder when element is dragged out
27
+ this.hideLocalPlaceholder = (i) => {
28
+ const { layout } = this.state;
29
+ const { cols } = this.props;
30
+ const savedLayout = layout.map((item) => (Object.assign({}, item)));
31
+ let hiddenElement;
32
+ const newLayout = compact(layout.filter((item) => {
33
+ if (item.i === i) {
34
+ hiddenElement = item;
35
+ return false;
36
+ }
37
+ return true;
38
+ }), compactType(this.props), cols);
39
+ if (hiddenElement) {
40
+ newLayout.push(hiddenElement);
41
+ }
42
+ this.setState({
43
+ activeDrag: null,
44
+ layout: newLayout,
45
+ });
46
+ this.resetExternalPlaceholder();
47
+ return { layout: savedLayout, id: hiddenElement.i };
48
+ };
49
+ this.extendedOnDrag = (i, x, y, sintEv) => {
50
+ var _a, _b;
51
+ if (!this._isMouseOver) {
52
+ if (!this._savedDragoutState) {
53
+ this._savedDragoutState = this.hideLocalPlaceholder(i);
54
+ (_b = (_a = this.props).onDragExit) === null || _b === void 0 ? void 0 : _b.call(_a);
55
+ }
56
+ return;
57
+ }
58
+ // parent onDrag will show new placeholder again
59
+ this.parentOnDrag(i, x, y, sintEv);
60
+ };
61
+ this.extendedOnDragStop = (i, x, y, sintEv) => {
62
+ // Restoring layout if item was dropped outside of the grid and wasn't captured
63
+ if (this._savedDragoutState) {
64
+ const savedLayout = this._savedDragoutState.layout;
65
+ const l = utils.getLayoutItem(savedLayout, i);
66
+ // Create placeholder (display only)
67
+ const placeholder = {
68
+ w: l.w,
69
+ h: l.h,
70
+ x: l.x,
71
+ y: l.y,
72
+ placeholder: true,
73
+ i: i,
74
+ };
75
+ this.setState({
76
+ layout: savedLayout,
77
+ activeDrag: placeholder,
78
+ }, () => {
79
+ this.parentOnDragStop(i, x, y, sintEv);
80
+ });
81
+ this._savedDragoutState = null;
82
+ }
83
+ else {
84
+ this.parentOnDragStop(i, x, y, sintEv);
85
+ }
86
+ };
87
+ this.extendedOnDragEnter = (...args) => {
88
+ this._isMouseOver = true;
89
+ return this.parentOnDragEnter(...args);
90
+ };
91
+ this.extendedOnDragLeave = (...args) => {
92
+ this._isMouseOver = true;
93
+ return this.parentOnDragLeave(...args);
94
+ };
95
+ // Proxy mouse events -> drag methods for dnd between groups
96
+ this.mouseEnterHandler = (e) => {
97
+ this._isMouseOver = true;
98
+ if (this.props.hasSharedDragItem) {
99
+ this.parentOnDragEnter(e);
100
+ }
101
+ };
13
102
  this.mouseLeaveHandler = (e) => {
14
- var _a;
15
- const rect = ((_a = this.props.innerRef) === null || _a === void 0 ? void 0 : _a.current.getBoundingClientRect()) || {};
16
- if (rect.bottom <= e.clientY ||
17
- rect.top >= e.clientY ||
18
- rect.left >= e.clientX ||
19
- rect.right <= e.clientX) {
20
- this.dragReset();
103
+ this._isMouseOver = false;
104
+ if (this.props.hasSharedDragItem) {
105
+ this.parentOnDragLeave(e);
21
106
  }
22
107
  };
23
- this.parentOnDrag = this.onDrag;
24
- this.onDrag = (i, x, y, sintE) => {
25
- this.parentOnDrag(i, x, y, sintE);
26
- this.mouseLeaveHandler(sintE.e);
108
+ this.mouseMoveHandler = (e) => {
109
+ this._isMouseOver = true;
110
+ if (this.props.hasSharedDragItem) {
111
+ this.onDragOver(e);
112
+ }
113
+ };
114
+ this.mouseUpHandler = (e) => {
115
+ var _a, _b;
116
+ this._isMouseOver = true;
117
+ if (this.props.hasSharedDragItem) {
118
+ e.preventDefault();
119
+ const { droppingItem } = this.props;
120
+ const { layout } = this.state;
121
+ const item = layout.find((l) => l.i === droppingItem.i);
122
+ // reset dragEnter counter on drop
123
+ this.resetExternalPlaceholder();
124
+ (_b = (_a = this.props).onDrop) === null || _b === void 0 ? void 0 : _b.call(_a, layout, item, e);
125
+ }
27
126
  };
127
+ this.parentOnDrag = this.onDrag;
128
+ this.onDrag = this.extendedOnDrag;
129
+ this.parentOnDragStop = this.onDragStop;
130
+ this.onDragStop = this.extendedOnDragStop;
131
+ this.parentOnDragEnter = this.onDragEnter;
132
+ this.onDragEnter = this.extendedOnDragEnter;
133
+ this.parentOnDragLeave = this.onDragLeave;
134
+ this.onDragLeave = this.extendedOnDragLeave;
28
135
  }
29
136
  componentDidMount() {
30
137
  var _a;
31
138
  (_a = super.componentDidMount) === null || _a === void 0 ? void 0 : _a.call(this);
32
- window.addEventListener('dragend', this.dragReset);
139
+ // If cursor is moved out of the window there is a bug
140
+ // which leaves placeholder element in grid, this action needed to reset this state
141
+ window.addEventListener('dragend', this.resetExternalPlaceholder);
142
+ const innerElement = this.getInnerElement();
143
+ if (innerElement) {
144
+ innerElement.addEventListener('mouseup', this.mouseUpHandler);
145
+ innerElement.addEventListener('mouseenter', this.mouseEnterHandler);
146
+ innerElement.addEventListener('mouseleave', this.mouseLeaveHandler);
147
+ innerElement.addEventListener('mousemove', this.mouseMoveHandler);
148
+ }
33
149
  }
34
150
  componentWillUnmount() {
35
- window.removeEventListener('dragend', this.dragReset);
151
+ window.removeEventListener('dragend', this.resetExternalPlaceholder);
152
+ const innerElement = this.getInnerElement();
153
+ if (innerElement) {
154
+ innerElement.removeEventListener('mouseup', this.mouseUpHandler);
155
+ innerElement.removeEventListener('mouseenter', this.mouseEnterHandler);
156
+ innerElement.removeEventListener('mouseleave', this.mouseLeaveHandler);
157
+ innerElement.removeEventListener('mousemove', this.mouseMoveHandler);
158
+ }
159
+ // Resetting instance props
160
+ this._savedDragoutState = null;
36
161
  }
162
+ // react-grid-layout doens't calculate it's height when last element is removed
163
+ // and just keeps the previous value
164
+ // so for autosize to work in that case we are resetting it's height value
37
165
  containerHeight() {
38
166
  if (this.props.autoSize && this.state.layout.length === 0) {
39
- return 'unset';
167
+ return;
40
168
  }
169
+ // eslint-disable-next-line consistent-return
41
170
  return super.containerHeight();
42
171
  }
43
- processGridItem(child, isDroppingItem) {
172
+ // innerRef is passed by WithProvider without this wrapper there are only
173
+ // * findDOMNode - deprecated
174
+ // * rewrite whole ReactGridLayout.render method
175
+ // so in that case don't try to use this class on it's own
176
+ // or pass innerRef: React.MutableRef as it's not optional prop
177
+ getInnerElement() {
44
178
  var _a;
179
+ return ((_a = this.props.innerRef) === null || _a === void 0 ? void 0 : _a.current) || null;
180
+ }
181
+ // Drop item from outside gets 0,0 droppingPosition
182
+ // centering cursor on newly creted grid item
183
+ // And cause grid-layout using it's own GridItem to make it look
184
+ // like overlay adding className
185
+ processGridItem(child, isDroppingItem) {
186
+ var _a, _b, _c;
45
187
  const gridItem = (_a = super.processGridItem) === null || _a === void 0 ? void 0 : _a.call(this, child, isDroppingItem);
188
+ if (!gridItem) {
189
+ return gridItem;
190
+ }
191
+ const { props: itemProps } = gridItem;
46
192
  if (isDroppingItem) {
47
- // Drop item from outside gets 0,0 droppingPosition
48
- // centering cursor on newly creted grid item
49
- // And cause grid-layout using it's own GridItem to make it look
50
- // like overlay adding className
51
- if (!gridItem)
52
- return null;
53
- const { props } = gridItem;
54
- const { containerWidth, cols, w, h, rowHeight, margin, transformScale } = props;
193
+ const { containerWidth, cols, w, h, rowHeight, margin, transformScale, droppingPosition, } = itemProps;
55
194
  const leftOffset = (((containerWidth / cols) * w) / 2 || 0) * transformScale;
56
195
  const topOffset = ((h * rowHeight + (h - 1) * margin[1]) / 2 || 0) * transformScale;
196
+ const dragStyles = this.props.hasSharedDragItem
197
+ ? DRAGGING_PLACEHOLDER_HIDDEN_STYLE
198
+ : DRAGGING_PLACEHOLDER_STYLE;
199
+ // React.cloneElement is just cleaner then copy-paste whole processGridItem method
57
200
  return React.cloneElement(gridItem, {
201
+ style: itemProps.style ? Object.assign(Object.assign({}, itemProps.style), dragStyles) : dragStyles,
58
202
  className: OVERLAY_CLASS_NAME,
59
- droppingPosition: Object.assign(Object.assign({}, props.droppingPosition), { left: props.droppingPosition.left - leftOffset, top: props.droppingPosition.top - topOffset }),
203
+ droppingPosition: Object.assign(Object.assign({}, droppingPosition), { left: droppingPosition.left - leftOffset, top: droppingPosition.top - topOffset }),
204
+ });
205
+ }
206
+ else if (itemProps.i === ((_b = this.state.activeDrag) === null || _b === void 0 ? void 0 : _b.i) ||
207
+ itemProps.i === ((_c = this._savedDragoutState) === null || _c === void 0 ? void 0 : _c.id)) {
208
+ const dragStyles = DRAGGING_PLACEHOLDER_STYLE;
209
+ return React.cloneElement(gridItem, {
210
+ style: itemProps.style ? Object.assign(Object.assign({}, itemProps.style), dragStyles) : dragStyles,
60
211
  });
61
212
  }
62
213
  return gridItem;
@@ -29,7 +29,7 @@ function useMemoStateContext(props) {
29
29
  isEqual(groups, props.groups))) {
30
30
  props.onChange({ config, itemsStateAndParams, groups });
31
31
  }
32
- }, [props.config, props.itemsStateAndParams, props.onChange]);
32
+ }, [props.config, props.groups, props.itemsStateAndParams, props.onChange]);
33
33
  // каллбэк вызывающийся при изменение лэйаута сетки, первым аргументом приходит актуальный конфиг лэйаута,
34
34
  // т.е. если на текущей сетке есть виджеты, с активированной опцией автовысоты, их параметр "h" будет
35
35
  // "подстроенный"; чтобы, для сохранения в сторе "ушли" значения без учёта подстройки (как если бы у этих
@@ -37,7 +37,17 @@ function useMemoStateContext(props) {
37
37
  const onLayoutChange = React.useCallback((layout) => {
38
38
  const currentInnerLayout = layout.map((item) => {
39
39
  if (item.i in originalLayouts.current) {
40
- return Object.assign(Object.assign({}, originalLayouts.current[item.i]), { w: item.w, x: item.x, y: item.y });
40
+ // eslint-disable-next-line no-unused-vars
41
+ const _a = originalLayouts.current[item.i], { parent } = _a, originalCopy = __rest(_a, ["parent"]);
42
+ // Updating original if parent has changed and saving copy as original
43
+ // or leaving default
44
+ if (item.parent) {
45
+ originalCopy.parent = item.parent;
46
+ }
47
+ originalCopy.w = item.w;
48
+ originalCopy.x = item.x;
49
+ originalCopy.y = item.y;
50
+ return originalCopy;
41
51
  }
42
52
  else {
43
53
  return Object.assign({}, item);
@@ -234,16 +244,24 @@ function useMemoStateContext(props) {
234
244
  return null;
235
245
  }
236
246
  }, [dragProps, props.registerManager]);
237
- const onDropDragOver = React.useCallback((_e, gridProps, groupLayout) => {
247
+ const onDropDragOver = React.useCallback((_e, gridProps, groupLayout, sharedItem) => {
238
248
  if (temporaryLayout) {
239
249
  resetTemporaryLayout();
240
250
  return false;
241
251
  }
242
- if (!dragOverPlugin) {
252
+ let defaultLayout;
253
+ if (sharedItem) {
254
+ const { type, h, w } = sharedItem;
255
+ const _defaults = props.registerManager.getItem(type);
256
+ defaultLayout = _defaults ? Object.assign(Object.assign({}, _defaults.defaultLayout), { h, w }) : { h, w };
257
+ }
258
+ else if (dragOverPlugin) {
259
+ defaultLayout = dragOverPlugin.defaultLayout;
260
+ }
261
+ else {
243
262
  return false;
244
263
  }
245
264
  let maxW = gridProps.cols;
246
- const { defaultLayout } = dragOverPlugin;
247
265
  const maxH = Math.min(gridProps.maxRows || Infinity, defaultLayout.maxH || Infinity);
248
266
  if (gridProps.compactType === COMPACT_TYPE_HORIZONTAL_NOWRAP) {
249
267
  maxW = groupLayout.reduce((memo, item) => memo - item.w, gridProps.cols);
@@ -254,7 +272,7 @@ function useMemoStateContext(props) {
254
272
  maxH < defaultLayout.minH) {
255
273
  return false;
256
274
  }
257
- const { h = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.h) || DEFAULT_WIDGET_HEIGHT, w = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.w) || DEFAULT_WIDGET_WIDTH, } = dragProps.layout || {};
275
+ const { h = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.h) || DEFAULT_WIDGET_HEIGHT, w = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.w) || DEFAULT_WIDGET_WIDTH, } = (dragProps === null || dragProps === void 0 ? void 0 : dragProps.layout) || {};
258
276
  return {
259
277
  h: maxH ? Math.min(h, maxH) : h,
260
278
  w: maxW ? Math.min(w, maxW) : w,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dashkit",
3
- "version": "8.8.0",
3
+ "version": "8.8.1-beta.0",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {