@gravity-ui/dashkit 8.17.3 → 8.17.4

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.
@@ -34,6 +34,9 @@
34
34
  border-color: transparent;
35
35
  pointer-events: none;
36
36
  }
37
+ .dashkit-grid-item_is-dragged-out {
38
+ pointer-events: none;
39
+ }
37
40
 
38
41
  .react-grid-layout {
39
42
  position: relative;
@@ -57,7 +60,6 @@
57
60
  transition: none;
58
61
  z-index: 3;
59
62
  will-change: transform;
60
- pointer-events: none;
61
63
  }
62
64
 
63
65
  .react-grid-item.dashkit-grid-item_is-focused {
@@ -74,6 +76,14 @@
74
76
  user-select: none;
75
77
  }
76
78
 
79
+ .react-grid-focus-capture {
80
+ position: absolute;
81
+ display: block;
82
+ z-index: 6;
83
+ max-width: 100%;
84
+ max-height: 100%;
85
+ }
86
+
77
87
  .react-grid-item .react-resizable-handle {
78
88
  position: absolute;
79
89
  width: 20px;
@@ -96,7 +96,7 @@ class GridItem extends react_1.default.PureComponent {
96
96
  render() {
97
97
  // из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
98
98
  // https://github.com/STRML/react-grid-layout/issues/721
99
- const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, isPlaceholder = false, } = this.props;
99
+ const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, isDraggedOut, noOverlay, focusable, withCustomHandle, isPlaceholder = false, } = this.props;
100
100
  const { editMode } = this.context;
101
101
  const width = Number.parseInt(style.width, 10);
102
102
  const height = Number.parseInt(style.height, 10);
@@ -115,6 +115,7 @@ class GridItem extends react_1.default.PureComponent {
115
115
  const { _editActive } = this.props.item.data;
116
116
  return (react_1.default.createElement("div", Object.assign({ className: b({
117
117
  'is-dragging': isDragging,
118
+ 'is-dragged-out': isDraggedOut,
118
119
  'is-focused': this.state.isFocused,
119
120
  'with-custom-handle': withCustomHandle,
120
121
  }, preparedClassName), "data-qa": "dashkit-grid-item", style: style, ref: this.props.forwardedRef }, reactGridLayoutProps, (focusable
@@ -135,6 +136,7 @@ GridItem.propTypes = {
135
136
  id: prop_types_1.default.string,
136
137
  item: prop_types_1.default.object,
137
138
  isDragging: prop_types_1.default.bool,
139
+ isDraggedOut: prop_types_1.default.bool,
138
140
  layout: prop_types_1.default.array,
139
141
  forwardedRef: prop_types_1.default.any,
140
142
  forwardedPluginRef: prop_types_1.default.any,
@@ -7,6 +7,7 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
7
7
  isPageHidden: boolean;
8
8
  currentDraggingElement: null;
9
9
  draggedOverGroup: null;
10
+ draggedOut: boolean;
10
11
  };
11
12
  componentDidMount(): void;
12
13
  componentDidUpdate(): void;
@@ -47,7 +48,12 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
47
48
  e: any;
48
49
  element: any;
49
50
  };
50
- updateeDraggingElementState(group: any, layoutItem: any, e: any): void;
51
+ updateDraggingElementState(group: any, layoutItem: any, e: any): void;
52
+ _initDragCoordinatesWatcher(element: any): void;
53
+ _parendDragNode: any;
54
+ _forceCursorCapture(parentElement: any, position: any, parentRect: any): void;
55
+ _updateDragCoordinates(e: any): void;
56
+ _resetDragWatcher(): void;
51
57
  _onDragStart(group: any, _newLayout: any, layoutItem: any, _newItem: any, _placeholder: any, e: any, element: any): void;
52
58
  _onDrag(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
53
59
  _onDragStop(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
@@ -155,6 +155,7 @@ class GridLayout extends react_1.default.PureComponent {
155
155
  isPageHidden: false,
156
156
  currentDraggingElement: null,
157
157
  draggedOverGroup: null,
158
+ draggedOut: false,
158
159
  };
159
160
  }
160
161
  componentDidMount() {
@@ -269,7 +270,7 @@ class GridLayout extends react_1.default.PureComponent {
269
270
  element,
270
271
  };
271
272
  }
272
- updateeDraggingElementState(group, layoutItem, e) {
273
+ updateDraggingElementState(group, layoutItem, e) {
273
274
  let currentDraggingElement = this.state.currentDraggingElement;
274
275
  if (!currentDraggingElement) {
275
276
  const { temporaryLayout } = this.context;
@@ -287,23 +288,79 @@ class GridLayout extends react_1.default.PureComponent {
287
288
  }
288
289
  this.setState({ currentDraggingElement, draggedOverGroup: group });
289
290
  }
291
+ _initDragCoordinatesWatcher(element) {
292
+ if (!this._parendDragNode) {
293
+ this._parendDragNode = element.parentElement;
294
+ this.setState({ draggedOut: false });
295
+ }
296
+ }
297
+ // When element is going back and prointer-event: none is removed mouse enter event is not fired
298
+ // So to trigger it we are forcing this event by adding transparent block under the mouse
299
+ _forceCursorCapture(parentElement, position, parentRect) {
300
+ const block = document.createElement('div');
301
+ block.classList.add('react-grid-focus-capture');
302
+ const blockSize = 44;
303
+ const offset = blockSize / 2;
304
+ // Keeping elemnt inside current grid
305
+ const top = Math.min(Math.max(position.top - offset, 0), parentRect.height - blockSize);
306
+ const left = Math.min(Math.max(position.left - offset, 0), parentRect.width - blockSize);
307
+ block.style.width = `${blockSize}px`;
308
+ block.style.height = `${blockSize}px`;
309
+ block.style.top = `${top}px`;
310
+ block.style.left = `${left}px`;
311
+ parentElement.appendChild(block);
312
+ setTimeout(() => {
313
+ block.remove();
314
+ }, 100);
315
+ }
316
+ _updateDragCoordinates(e) {
317
+ const parent = this._parendDragNode;
318
+ const parentRect = parent.getBoundingClientRect();
319
+ const { clientX, clientY } = e;
320
+ let draggedOut = this.state.draggedOut;
321
+ if (clientX < parentRect.left ||
322
+ clientX > parentRect.right ||
323
+ clientY < parentRect.top ||
324
+ clientY > parentRect.bottom) {
325
+ draggedOut = true;
326
+ }
327
+ else {
328
+ draggedOut = false;
329
+ }
330
+ if (draggedOut !== this.state.draggedOut) {
331
+ this.setState({ draggedOut });
332
+ if (!draggedOut) {
333
+ this._forceCursorCapture(parent, {
334
+ top: clientY - parentRect.top,
335
+ left: clientX - parentRect.left,
336
+ }, parentRect);
337
+ }
338
+ }
339
+ }
340
+ _resetDragWatcher() {
341
+ this._parendDragNode = null;
342
+ this.setState({ draggedOut: false });
343
+ }
290
344
  _onDragStart(group, _newLayout, layoutItem, _newItem, _placeholder, e, element) {
291
345
  var _a;
292
346
  (_a = this.context.onDragStart) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, _newLayout, layoutItem, _newItem, _placeholder, e, element));
347
+ this._initDragCoordinatesWatcher(element);
293
348
  if (this.context.dragOverPlugin) {
294
349
  this.setState({ isDragging: true });
295
350
  }
296
351
  else {
297
- this.updateeDraggingElementState(group, layoutItem, e);
352
+ this.updateDraggingElementState(group, layoutItem, e);
298
353
  this.setState({ isDragging: true });
299
354
  }
300
355
  }
301
356
  _onDrag(group, layout, oldItem, newItem, placeholder, e, element) {
302
357
  var _a;
358
+ this._updateDragCoordinates(e);
303
359
  (_a = this.context.onDrag) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
304
360
  }
305
361
  _onDragStop(group, layout, oldItem, newItem, placeholder, e, element) {
306
362
  var _a;
363
+ this._resetDragWatcher();
307
364
  this._onStop(group, layout);
308
365
  (_a = this.context.onDragStop) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
309
366
  }
@@ -375,7 +432,9 @@ class GridLayout extends react_1.default.PureComponent {
375
432
  }
376
433
  : null)),
377
434
  renderItems.map((item, i) => {
378
- return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: this.getMemoForwardRefCallback(offset + i), key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), onItemMountChange: onItemMountChange, onItemRender: onItemRender }));
435
+ const isCurrentItem = (currentDraggingElement === null || currentDraggingElement === void 0 ? void 0 : currentDraggingElement.item.id) === item.id;
436
+ const isDraggedOut = isCurrentItem && this.state.draggedOut;
437
+ return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: this.getMemoForwardRefCallback(offset + i), key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, isDraggedOut: isDraggedOut, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), onItemMountChange: onItemMountChange, onItemRender: onItemRender }));
379
438
  }),
380
439
  this.renderTemporaryPlaceholder()));
381
440
  }
@@ -34,6 +34,9 @@
34
34
  border-color: transparent;
35
35
  pointer-events: none;
36
36
  }
37
+ .dashkit-grid-item_is-dragged-out {
38
+ pointer-events: none;
39
+ }
37
40
 
38
41
  .react-grid-layout {
39
42
  position: relative;
@@ -57,7 +60,6 @@
57
60
  transition: none;
58
61
  z-index: 3;
59
62
  will-change: transform;
60
- pointer-events: none;
61
63
  }
62
64
 
63
65
  .react-grid-item.dashkit-grid-item_is-focused {
@@ -74,6 +76,14 @@
74
76
  user-select: none;
75
77
  }
76
78
 
79
+ .react-grid-focus-capture {
80
+ position: absolute;
81
+ display: block;
82
+ z-index: 6;
83
+ max-width: 100%;
84
+ max-height: 100%;
85
+ }
86
+
77
87
  .react-grid-item .react-resizable-handle {
78
88
  position: absolute;
79
89
  width: 20px;
@@ -94,7 +94,7 @@ class GridItem extends React.PureComponent {
94
94
  render() {
95
95
  // из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
96
96
  // https://github.com/STRML/react-grid-layout/issues/721
97
- const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, isPlaceholder = false, } = this.props;
97
+ const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, isDraggedOut, noOverlay, focusable, withCustomHandle, isPlaceholder = false, } = this.props;
98
98
  const { editMode } = this.context;
99
99
  const width = Number.parseInt(style.width, 10);
100
100
  const height = Number.parseInt(style.height, 10);
@@ -113,6 +113,7 @@ class GridItem extends React.PureComponent {
113
113
  const { _editActive } = this.props.item.data;
114
114
  return (React.createElement("div", Object.assign({ className: b({
115
115
  'is-dragging': isDragging,
116
+ 'is-dragged-out': isDraggedOut,
116
117
  'is-focused': this.state.isFocused,
117
118
  'with-custom-handle': withCustomHandle,
118
119
  }, preparedClassName), "data-qa": "dashkit-grid-item", style: style, ref: this.props.forwardedRef }, reactGridLayoutProps, (focusable
@@ -133,6 +134,7 @@ GridItem.propTypes = {
133
134
  id: PropTypes.string,
134
135
  item: PropTypes.object,
135
136
  isDragging: PropTypes.bool,
137
+ isDraggedOut: PropTypes.bool,
136
138
  layout: PropTypes.array,
137
139
  forwardedRef: PropTypes.any,
138
140
  forwardedPluginRef: PropTypes.any,
@@ -7,6 +7,7 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
7
7
  isPageHidden: boolean;
8
8
  currentDraggingElement: null;
9
9
  draggedOverGroup: null;
10
+ draggedOut: boolean;
10
11
  };
11
12
  componentDidMount(): void;
12
13
  componentDidUpdate(): void;
@@ -47,7 +48,12 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
47
48
  e: any;
48
49
  element: any;
49
50
  };
50
- updateeDraggingElementState(group: any, layoutItem: any, e: any): void;
51
+ updateDraggingElementState(group: any, layoutItem: any, e: any): void;
52
+ _initDragCoordinatesWatcher(element: any): void;
53
+ _parendDragNode: any;
54
+ _forceCursorCapture(parentElement: any, position: any, parentRect: any): void;
55
+ _updateDragCoordinates(e: any): void;
56
+ _resetDragWatcher(): void;
51
57
  _onDragStart(group: any, _newLayout: any, layoutItem: any, _newItem: any, _placeholder: any, e: any, element: any): void;
52
58
  _onDrag(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
53
59
  _onDragStop(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
@@ -152,6 +152,7 @@ class GridLayout extends React.PureComponent {
152
152
  isPageHidden: false,
153
153
  currentDraggingElement: null,
154
154
  draggedOverGroup: null,
155
+ draggedOut: false,
155
156
  };
156
157
  }
157
158
  componentDidMount() {
@@ -266,7 +267,7 @@ class GridLayout extends React.PureComponent {
266
267
  element,
267
268
  };
268
269
  }
269
- updateeDraggingElementState(group, layoutItem, e) {
270
+ updateDraggingElementState(group, layoutItem, e) {
270
271
  let currentDraggingElement = this.state.currentDraggingElement;
271
272
  if (!currentDraggingElement) {
272
273
  const { temporaryLayout } = this.context;
@@ -284,23 +285,79 @@ class GridLayout extends React.PureComponent {
284
285
  }
285
286
  this.setState({ currentDraggingElement, draggedOverGroup: group });
286
287
  }
288
+ _initDragCoordinatesWatcher(element) {
289
+ if (!this._parendDragNode) {
290
+ this._parendDragNode = element.parentElement;
291
+ this.setState({ draggedOut: false });
292
+ }
293
+ }
294
+ // When element is going back and prointer-event: none is removed mouse enter event is not fired
295
+ // So to trigger it we are forcing this event by adding transparent block under the mouse
296
+ _forceCursorCapture(parentElement, position, parentRect) {
297
+ const block = document.createElement('div');
298
+ block.classList.add('react-grid-focus-capture');
299
+ const blockSize = 44;
300
+ const offset = blockSize / 2;
301
+ // Keeping elemnt inside current grid
302
+ const top = Math.min(Math.max(position.top - offset, 0), parentRect.height - blockSize);
303
+ const left = Math.min(Math.max(position.left - offset, 0), parentRect.width - blockSize);
304
+ block.style.width = `${blockSize}px`;
305
+ block.style.height = `${blockSize}px`;
306
+ block.style.top = `${top}px`;
307
+ block.style.left = `${left}px`;
308
+ parentElement.appendChild(block);
309
+ setTimeout(() => {
310
+ block.remove();
311
+ }, 100);
312
+ }
313
+ _updateDragCoordinates(e) {
314
+ const parent = this._parendDragNode;
315
+ const parentRect = parent.getBoundingClientRect();
316
+ const { clientX, clientY } = e;
317
+ let draggedOut = this.state.draggedOut;
318
+ if (clientX < parentRect.left ||
319
+ clientX > parentRect.right ||
320
+ clientY < parentRect.top ||
321
+ clientY > parentRect.bottom) {
322
+ draggedOut = true;
323
+ }
324
+ else {
325
+ draggedOut = false;
326
+ }
327
+ if (draggedOut !== this.state.draggedOut) {
328
+ this.setState({ draggedOut });
329
+ if (!draggedOut) {
330
+ this._forceCursorCapture(parent, {
331
+ top: clientY - parentRect.top,
332
+ left: clientX - parentRect.left,
333
+ }, parentRect);
334
+ }
335
+ }
336
+ }
337
+ _resetDragWatcher() {
338
+ this._parendDragNode = null;
339
+ this.setState({ draggedOut: false });
340
+ }
287
341
  _onDragStart(group, _newLayout, layoutItem, _newItem, _placeholder, e, element) {
288
342
  var _a;
289
343
  (_a = this.context.onDragStart) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, _newLayout, layoutItem, _newItem, _placeholder, e, element));
344
+ this._initDragCoordinatesWatcher(element);
290
345
  if (this.context.dragOverPlugin) {
291
346
  this.setState({ isDragging: true });
292
347
  }
293
348
  else {
294
- this.updateeDraggingElementState(group, layoutItem, e);
349
+ this.updateDraggingElementState(group, layoutItem, e);
295
350
  this.setState({ isDragging: true });
296
351
  }
297
352
  }
298
353
  _onDrag(group, layout, oldItem, newItem, placeholder, e, element) {
299
354
  var _a;
355
+ this._updateDragCoordinates(e);
300
356
  (_a = this.context.onDrag) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
301
357
  }
302
358
  _onDragStop(group, layout, oldItem, newItem, placeholder, e, element) {
303
359
  var _a;
360
+ this._resetDragWatcher();
304
361
  this._onStop(group, layout);
305
362
  (_a = this.context.onDragStop) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
306
363
  }
@@ -372,7 +429,9 @@ class GridLayout extends React.PureComponent {
372
429
  }
373
430
  : null)),
374
431
  renderItems.map((item, i) => {
375
- return (React.createElement(GridItem, { forwardedPluginRef: this.getMemoForwardRefCallback(offset + i), key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), onItemMountChange: onItemMountChange, onItemRender: onItemRender }));
432
+ const isCurrentItem = (currentDraggingElement === null || currentDraggingElement === void 0 ? void 0 : currentDraggingElement.item.id) === item.id;
433
+ const isDraggedOut = isCurrentItem && this.state.draggedOut;
434
+ return (React.createElement(GridItem, { forwardedPluginRef: this.getMemoForwardRefCallback(offset + i), key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, isDraggedOut: isDraggedOut, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), onItemMountChange: onItemMountChange, onItemRender: onItemRender }));
376
435
  }),
377
436
  this.renderTemporaryPlaceholder()));
378
437
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dashkit",
3
- "version": "8.17.3",
3
+ "version": "8.17.4",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {