@gravity-ui/dashkit 8.8.0 → 8.8.1-beta.1

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
+ if (this.context.dragOverPlugin) {
101
+ this.setState({ isDragging: true });
102
+ }
103
+ else {
104
+ let currentDraggingElement = this.state.currentDraggingElement;
105
+ if (!currentDraggingElement) {
106
+ const _id = layoutItem.i;
107
+ const item = this.context.config.items.find(({ id }) => id === _id);
108
+ currentDraggingElement = [group, layoutItem, item];
109
+ }
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,215 @@ 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
+ if (!this._isMouseOver) {
55
+ if (!this._savedDragoutState) {
56
+ this._savedDragoutState = this.hideLocalPlaceholder(i);
57
+ }
58
+ return;
59
+ }
60
+ // parent onDrag will show new placeholder again
61
+ this.parentOnDrag(i, x, y, sintEv);
62
+ };
63
+ this.extendedOnDragStop = (i, x, y, sintEv) => {
64
+ // Restoring layout if item was dropped outside of the grid and wasn't captured
65
+ if (this._savedDragoutState) {
66
+ const savedLayout = this._savedDragoutState.layout;
67
+ const l = react_grid_layout_1.utils.getLayoutItem(savedLayout, i);
68
+ // Create placeholder (display only)
69
+ const placeholder = {
70
+ w: l.w,
71
+ h: l.h,
72
+ x: l.x,
73
+ y: l.y,
74
+ placeholder: true,
75
+ i: i,
76
+ };
77
+ this.setState({
78
+ layout: savedLayout,
79
+ activeDrag: placeholder,
80
+ }, () => {
81
+ this.parentOnDragStop(i, x, y, sintEv);
82
+ });
83
+ this._savedDragoutState = null;
84
+ }
85
+ else {
86
+ this.parentOnDragStop(i, x, y, sintEv);
87
+ }
88
+ };
89
+ this.extendedOnDragEnter = (...args) => {
90
+ this._isMouseOver = true;
91
+ this.parentOnDragEnter(...args);
92
+ };
93
+ this.extendedOnDragLeave = (...args) => {
94
+ var _a, _b;
95
+ this._isMouseOver = false;
96
+ this.parentOnDragLeave(...args);
97
+ (_b = (_a = this.props).onDragExit) === null || _b === void 0 ? void 0 : _b.call(_a);
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
+ var _a, _b;
108
+ this._isMouseOver = false;
109
+ if (this.props.hasSharedDragItem) {
110
+ this.parentOnDragLeave(e);
111
+ (_b = (_a = this.props).onDragExit) === null || _b === void 0 ? void 0 : _b.call(_a);
25
112
  }
26
113
  };
27
- this.parentOnDrag = this.onDrag;
28
- this.onDrag = (i, x, y, sintE) => {
29
- this.parentOnDrag(i, x, y, sintE);
30
- this.mouseLeaveHandler(sintE.e);
114
+ this.mouseMoveHandler = (e) => {
115
+ this._isMouseOver = true;
116
+ if (this.props.hasSharedDragItem) {
117
+ this.onDragOver(e);
118
+ }
119
+ };
120
+ this.mouseUpHandler = (e) => {
121
+ var _a, _b;
122
+ this._isMouseOver = true;
123
+ if (this.props.hasSharedDragItem) {
124
+ e.preventDefault();
125
+ const { droppingItem } = this.props;
126
+ const { layout } = this.state;
127
+ const item = layout.find((l) => l.i === droppingItem.i);
128
+ // reset dragEnter counter on drop
129
+ this.resetExternalPlaceholder();
130
+ (_b = (_a = this.props).onDrop) === null || _b === void 0 ? void 0 : _b.call(_a, layout, item, e);
131
+ }
31
132
  };
133
+ this.parentOnDrag = this.onDrag;
134
+ this.onDrag = this.extendedOnDrag;
135
+ this.parentOnDragStop = this.onDragStop;
136
+ this.onDragStop = this.extendedOnDragStop;
137
+ this.parentOnDragEnter = this.onDragEnter;
138
+ this.onDragEnter = this.extendedOnDragEnter;
139
+ this.parentOnDragLeave = this.onDragLeave;
140
+ this.onDragLeave = this.extendedOnDragLeave;
32
141
  }
33
142
  componentDidMount() {
34
143
  var _a;
35
144
  (_a = super.componentDidMount) === null || _a === void 0 ? void 0 : _a.call(this);
36
- window.addEventListener('dragend', this.dragReset);
145
+ // If cursor is moved out of the window there is a bug
146
+ // which leaves placeholder element in grid, this action needed to reset this state
147
+ window.addEventListener('dragend', this.resetExternalPlaceholder);
148
+ const innerElement = this.getInnerElement();
149
+ if (innerElement) {
150
+ innerElement.addEventListener('mouseup', this.mouseUpHandler);
151
+ innerElement.addEventListener('mouseenter', this.mouseEnterHandler);
152
+ innerElement.addEventListener('mouseleave', this.mouseLeaveHandler);
153
+ innerElement.addEventListener('mousemove', this.mouseMoveHandler);
154
+ }
37
155
  }
38
156
  componentWillUnmount() {
39
- window.removeEventListener('dragend', this.dragReset);
157
+ window.removeEventListener('dragend', this.resetExternalPlaceholder);
158
+ const innerElement = this.getInnerElement();
159
+ if (innerElement) {
160
+ innerElement.removeEventListener('mouseup', this.mouseUpHandler);
161
+ innerElement.removeEventListener('mouseenter', this.mouseEnterHandler);
162
+ innerElement.removeEventListener('mouseleave', this.mouseLeaveHandler);
163
+ innerElement.removeEventListener('mousemove', this.mouseMoveHandler);
164
+ }
165
+ // Resetting instance props
166
+ this._savedDragoutState = null;
40
167
  }
168
+ // react-grid-layout doens't calculate it's height when last element is removed
169
+ // and just keeps the previous value
170
+ // so for autosize to work in that case we are resetting it's height value
41
171
  containerHeight() {
42
172
  if (this.props.autoSize && this.state.layout.length === 0) {
43
- return 'unset';
173
+ return;
44
174
  }
175
+ // eslint-disable-next-line consistent-return
45
176
  return super.containerHeight();
46
177
  }
47
- processGridItem(child, isDroppingItem) {
178
+ // innerRef is passed by WithProvider without this wrapper there are only
179
+ // * findDOMNode - deprecated
180
+ // * rewrite whole ReactGridLayout.render method
181
+ // so in that case don't try to use this class on it's own
182
+ // or pass innerRef: React.MutableRef as it's not optional prop
183
+ getInnerElement() {
48
184
  var _a;
185
+ return ((_a = this.props.innerRef) === null || _a === void 0 ? void 0 : _a.current) || null;
186
+ }
187
+ // Drop item from outside gets 0,0 droppingPosition
188
+ // centering cursor on newly creted grid item
189
+ // And cause grid-layout using it's own GridItem to make it look
190
+ // like overlay adding className
191
+ processGridItem(child, isDroppingItem) {
192
+ var _a, _b, _c;
49
193
  const gridItem = (_a = super.processGridItem) === null || _a === void 0 ? void 0 : _a.call(this, child, isDroppingItem);
194
+ if (!gridItem) {
195
+ return gridItem;
196
+ }
197
+ const { props: itemProps } = gridItem;
50
198
  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;
199
+ const { containerWidth, cols, w, h, rowHeight, margin, transformScale, droppingPosition, } = itemProps;
59
200
  const leftOffset = (((containerWidth / cols) * w) / 2 || 0) * transformScale;
60
201
  const topOffset = ((h * rowHeight + (h - 1) * margin[1]) / 2 || 0) * transformScale;
202
+ const dragStyles = this.props.hasSharedDragItem
203
+ ? DRAGGING_PLACEHOLDER_HIDDEN_STYLE
204
+ : DRAGGING_PLACEHOLDER_STYLE;
205
+ // React.cloneElement is just cleaner then copy-paste whole processGridItem method
61
206
  return react_1.default.cloneElement(gridItem, {
207
+ style: itemProps.style ? Object.assign(Object.assign({}, itemProps.style), dragStyles) : dragStyles,
62
208
  className: constants_1.OVERLAY_CLASS_NAME,
63
- droppingPosition: Object.assign(Object.assign({}, props.droppingPosition), { left: props.droppingPosition.left - leftOffset, top: props.droppingPosition.top - topOffset }),
209
+ droppingPosition: Object.assign(Object.assign({}, droppingPosition), { left: droppingPosition.left - leftOffset, top: droppingPosition.top - topOffset }),
210
+ });
211
+ }
212
+ else if (itemProps.i === ((_b = this.state.activeDrag) === null || _b === void 0 ? void 0 : _b.i) ||
213
+ itemProps.i === ((_c = this._savedDragoutState) === null || _c === void 0 ? void 0 : _c.id)) {
214
+ const dragStyles = DRAGGING_PLACEHOLDER_STYLE;
215
+ return react_1.default.cloneElement(gridItem, {
216
+ style: itemProps.style ? Object.assign(Object.assign({}, itemProps.style), dragStyles) : dragStyles,
64
217
  });
65
218
  }
66
219
  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
+ if (this.context.dragOverPlugin) {
98
+ this.setState({ isDragging: true });
99
+ }
100
+ else {
101
+ let currentDraggingElement = this.state.currentDraggingElement;
102
+ if (!currentDraggingElement) {
103
+ const _id = layoutItem.i;
104
+ const item = this.context.config.items.find(({ id }) => id === _id);
105
+ currentDraggingElement = [group, layoutItem, item];
106
+ }
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,215 @@
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
+ if (!this._isMouseOver) {
51
+ if (!this._savedDragoutState) {
52
+ this._savedDragoutState = this.hideLocalPlaceholder(i);
53
+ }
54
+ return;
55
+ }
56
+ // parent onDrag will show new placeholder again
57
+ this.parentOnDrag(i, x, y, sintEv);
58
+ };
59
+ this.extendedOnDragStop = (i, x, y, sintEv) => {
60
+ // Restoring layout if item was dropped outside of the grid and wasn't captured
61
+ if (this._savedDragoutState) {
62
+ const savedLayout = this._savedDragoutState.layout;
63
+ const l = utils.getLayoutItem(savedLayout, i);
64
+ // Create placeholder (display only)
65
+ const placeholder = {
66
+ w: l.w,
67
+ h: l.h,
68
+ x: l.x,
69
+ y: l.y,
70
+ placeholder: true,
71
+ i: i,
72
+ };
73
+ this.setState({
74
+ layout: savedLayout,
75
+ activeDrag: placeholder,
76
+ }, () => {
77
+ this.parentOnDragStop(i, x, y, sintEv);
78
+ });
79
+ this._savedDragoutState = null;
80
+ }
81
+ else {
82
+ this.parentOnDragStop(i, x, y, sintEv);
83
+ }
84
+ };
85
+ this.extendedOnDragEnter = (...args) => {
86
+ this._isMouseOver = true;
87
+ this.parentOnDragEnter(...args);
88
+ };
89
+ this.extendedOnDragLeave = (...args) => {
90
+ var _a, _b;
91
+ this._isMouseOver = false;
92
+ this.parentOnDragLeave(...args);
93
+ (_b = (_a = this.props).onDragExit) === null || _b === void 0 ? void 0 : _b.call(_a);
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
+ var _a, _b;
104
+ this._isMouseOver = false;
105
+ if (this.props.hasSharedDragItem) {
106
+ this.parentOnDragLeave(e);
107
+ (_b = (_a = this.props).onDragExit) === null || _b === void 0 ? void 0 : _b.call(_a);
21
108
  }
22
109
  };
23
- this.parentOnDrag = this.onDrag;
24
- this.onDrag = (i, x, y, sintE) => {
25
- this.parentOnDrag(i, x, y, sintE);
26
- this.mouseLeaveHandler(sintE.e);
110
+ this.mouseMoveHandler = (e) => {
111
+ this._isMouseOver = true;
112
+ if (this.props.hasSharedDragItem) {
113
+ this.onDragOver(e);
114
+ }
115
+ };
116
+ this.mouseUpHandler = (e) => {
117
+ var _a, _b;
118
+ this._isMouseOver = true;
119
+ if (this.props.hasSharedDragItem) {
120
+ e.preventDefault();
121
+ const { droppingItem } = this.props;
122
+ const { layout } = this.state;
123
+ const item = layout.find((l) => l.i === droppingItem.i);
124
+ // reset dragEnter counter on drop
125
+ this.resetExternalPlaceholder();
126
+ (_b = (_a = this.props).onDrop) === null || _b === void 0 ? void 0 : _b.call(_a, layout, item, e);
127
+ }
27
128
  };
129
+ this.parentOnDrag = this.onDrag;
130
+ this.onDrag = this.extendedOnDrag;
131
+ this.parentOnDragStop = this.onDragStop;
132
+ this.onDragStop = this.extendedOnDragStop;
133
+ this.parentOnDragEnter = this.onDragEnter;
134
+ this.onDragEnter = this.extendedOnDragEnter;
135
+ this.parentOnDragLeave = this.onDragLeave;
136
+ this.onDragLeave = this.extendedOnDragLeave;
28
137
  }
29
138
  componentDidMount() {
30
139
  var _a;
31
140
  (_a = super.componentDidMount) === null || _a === void 0 ? void 0 : _a.call(this);
32
- window.addEventListener('dragend', this.dragReset);
141
+ // If cursor is moved out of the window there is a bug
142
+ // which leaves placeholder element in grid, this action needed to reset this state
143
+ window.addEventListener('dragend', this.resetExternalPlaceholder);
144
+ const innerElement = this.getInnerElement();
145
+ if (innerElement) {
146
+ innerElement.addEventListener('mouseup', this.mouseUpHandler);
147
+ innerElement.addEventListener('mouseenter', this.mouseEnterHandler);
148
+ innerElement.addEventListener('mouseleave', this.mouseLeaveHandler);
149
+ innerElement.addEventListener('mousemove', this.mouseMoveHandler);
150
+ }
33
151
  }
34
152
  componentWillUnmount() {
35
- window.removeEventListener('dragend', this.dragReset);
153
+ window.removeEventListener('dragend', this.resetExternalPlaceholder);
154
+ const innerElement = this.getInnerElement();
155
+ if (innerElement) {
156
+ innerElement.removeEventListener('mouseup', this.mouseUpHandler);
157
+ innerElement.removeEventListener('mouseenter', this.mouseEnterHandler);
158
+ innerElement.removeEventListener('mouseleave', this.mouseLeaveHandler);
159
+ innerElement.removeEventListener('mousemove', this.mouseMoveHandler);
160
+ }
161
+ // Resetting instance props
162
+ this._savedDragoutState = null;
36
163
  }
164
+ // react-grid-layout doens't calculate it's height when last element is removed
165
+ // and just keeps the previous value
166
+ // so for autosize to work in that case we are resetting it's height value
37
167
  containerHeight() {
38
168
  if (this.props.autoSize && this.state.layout.length === 0) {
39
- return 'unset';
169
+ return;
40
170
  }
171
+ // eslint-disable-next-line consistent-return
41
172
  return super.containerHeight();
42
173
  }
43
- processGridItem(child, isDroppingItem) {
174
+ // innerRef is passed by WithProvider without this wrapper there are only
175
+ // * findDOMNode - deprecated
176
+ // * rewrite whole ReactGridLayout.render method
177
+ // so in that case don't try to use this class on it's own
178
+ // or pass innerRef: React.MutableRef as it's not optional prop
179
+ getInnerElement() {
44
180
  var _a;
181
+ return ((_a = this.props.innerRef) === null || _a === void 0 ? void 0 : _a.current) || null;
182
+ }
183
+ // Drop item from outside gets 0,0 droppingPosition
184
+ // centering cursor on newly creted grid item
185
+ // And cause grid-layout using it's own GridItem to make it look
186
+ // like overlay adding className
187
+ processGridItem(child, isDroppingItem) {
188
+ var _a, _b, _c;
45
189
  const gridItem = (_a = super.processGridItem) === null || _a === void 0 ? void 0 : _a.call(this, child, isDroppingItem);
190
+ if (!gridItem) {
191
+ return gridItem;
192
+ }
193
+ const { props: itemProps } = gridItem;
46
194
  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;
195
+ const { containerWidth, cols, w, h, rowHeight, margin, transformScale, droppingPosition, } = itemProps;
55
196
  const leftOffset = (((containerWidth / cols) * w) / 2 || 0) * transformScale;
56
197
  const topOffset = ((h * rowHeight + (h - 1) * margin[1]) / 2 || 0) * transformScale;
198
+ const dragStyles = this.props.hasSharedDragItem
199
+ ? DRAGGING_PLACEHOLDER_HIDDEN_STYLE
200
+ : DRAGGING_PLACEHOLDER_STYLE;
201
+ // React.cloneElement is just cleaner then copy-paste whole processGridItem method
57
202
  return React.cloneElement(gridItem, {
203
+ style: itemProps.style ? Object.assign(Object.assign({}, itemProps.style), dragStyles) : dragStyles,
58
204
  className: OVERLAY_CLASS_NAME,
59
- droppingPosition: Object.assign(Object.assign({}, props.droppingPosition), { left: props.droppingPosition.left - leftOffset, top: props.droppingPosition.top - topOffset }),
205
+ droppingPosition: Object.assign(Object.assign({}, droppingPosition), { left: droppingPosition.left - leftOffset, top: droppingPosition.top - topOffset }),
206
+ });
207
+ }
208
+ else if (itemProps.i === ((_b = this.state.activeDrag) === null || _b === void 0 ? void 0 : _b.i) ||
209
+ itemProps.i === ((_c = this._savedDragoutState) === null || _c === void 0 ? void 0 : _c.id)) {
210
+ const dragStyles = DRAGGING_PLACEHOLDER_STYLE;
211
+ return React.cloneElement(gridItem, {
212
+ style: itemProps.style ? Object.assign(Object.assign({}, itemProps.style), dragStyles) : dragStyles,
60
213
  });
61
214
  }
62
215
  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.1",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {