@gravity-ui/dashkit 8.17.2 → 8.17.3-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.
@@ -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 {
@@ -81,33 +81,6 @@ class GridItem extends react_1.default.PureComponent {
81
81
  this.controller = null;
82
82
  });
83
83
  };
84
- this.onMountChange = (isMounted) => {
85
- var _a, _b, _c, _d, _e, _f;
86
- if (isMounted) {
87
- this._inited = true;
88
- (_b = (_a = this.props).onItemMountChange) === null || _b === void 0 ? void 0 : _b.call(_a, this.props.item, {
89
- isAsync: this._isAsyncItem,
90
- isMounted: isMounted,
91
- });
92
- if (!this._isAsyncItem) {
93
- (_d = (_c = this.props).onItemRender) === null || _d === void 0 ? void 0 : _d.call(_c, this.props.item);
94
- }
95
- }
96
- else {
97
- (_f = (_e = this.props).onItemMountChange) === null || _f === void 0 ? void 0 : _f.call(_e, this.props.item, {
98
- isAsync: this._isAsyncItem,
99
- isMounted: isMounted,
100
- });
101
- }
102
- };
103
- this.onBeforeLoad = () => {
104
- this._isAsyncItem = true;
105
- return this.onLoad;
106
- };
107
- this.onLoad = () => {
108
- var _a, _b;
109
- (_b = (_a = this.props).onItemRender) === null || _b === void 0 ? void 0 : _b.call(_a, this.props.item);
110
- };
111
84
  }
112
85
  renderOverlay() {
113
86
  const { isPlaceholder } = this.props;
@@ -123,7 +96,7 @@ class GridItem extends react_1.default.PureComponent {
123
96
  render() {
124
97
  // из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
125
98
  // https://github.com/STRML/react-grid-layout/issues/721
126
- 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, draggedOut, noOverlay, focusable, withCustomHandle, isPlaceholder = false, } = this.props;
127
100
  const { editMode } = this.context;
128
101
  const width = Number.parseInt(style.width, 10);
129
102
  const height = Number.parseInt(style.height, 10);
@@ -142,6 +115,7 @@ class GridItem extends react_1.default.PureComponent {
142
115
  const { _editActive } = this.props.item.data;
143
116
  return (react_1.default.createElement("div", Object.assign({ className: b({
144
117
  'is-dragging': isDragging,
118
+ 'is-dragged-out': draggedOut,
145
119
  'is-focused': this.state.isFocused,
146
120
  'with-custom-handle': withCustomHandle,
147
121
  }, preparedClassName), "data-qa": "dashkit-grid-item", style: style, ref: this.props.forwardedRef }, reactGridLayoutProps, (focusable
@@ -152,7 +126,7 @@ class GridItem extends react_1.default.PureComponent {
152
126
  }
153
127
  : {})),
154
128
  react_1.default.createElement("div", { className: b('item', { editMode: editMode && !_editActive && !noOverlay }) },
155
- react_1.default.createElement(Item_1.default, { id: this.props.id, item: this.props.item, shouldItemUpdate: !isDragging, width: width, height: height, transform: transform, isPlaceholder: isPlaceholder, adjustWidgetLayout: this.props.adjustWidgetLayout, layout: this.props.layout, forwardedPluginRef: this.props.forwardedPluginRef, onMountChange: this.onMountChange, onBeforeLoad: this.onBeforeLoad })),
129
+ react_1.default.createElement(Item_1.default, { id: this.props.id, item: this.props.item, shouldItemUpdate: !isDragging, width: width, height: height, transform: transform, isPlaceholder: isPlaceholder, adjustWidgetLayout: this.props.adjustWidgetLayout, layout: this.props.layout, forwardedPluginRef: this.props.forwardedPluginRef, onItemMountChange: this.props.onItemMountChange, onItemRender: this.props.onItemRender })),
156
130
  !noOverlay && this.renderOverlay(),
157
131
  preparedChildren));
158
132
  }
@@ -162,10 +136,13 @@ GridItem.propTypes = {
162
136
  id: prop_types_1.default.string,
163
137
  item: prop_types_1.default.object,
164
138
  isDragging: prop_types_1.default.bool,
139
+ draggedOut: prop_types_1.default.bool,
165
140
  layout: prop_types_1.default.array,
166
141
  forwardedRef: prop_types_1.default.any,
167
142
  forwardedPluginRef: prop_types_1.default.any,
168
143
  isPlaceholder: prop_types_1.default.bool,
144
+ onItemMountChange: prop_types_1.default.func,
145
+ onItemRender: prop_types_1.default.func,
169
146
  // from react-grid-layout:
170
147
  children: prop_types_1.default.node,
171
148
  className: prop_types_1.default.string,
@@ -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;
@@ -48,6 +49,11 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
48
49
  element: any;
49
50
  };
50
51
  updateeDraggingElementState(group: any, layoutItem: any, e: any): void;
52
+ _initDragCoordinatesWatcher(element: any): void;
53
+ _parendDragNode: any;
54
+ _forceCursorCapture(parentElement: any, position: 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() {
@@ -287,9 +288,58 @@ 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
+ _forceCursorCapture(parentElement, position) {
298
+ const div = document.createElement('div');
299
+ const blockSize = 50;
300
+ const offset = blockSize / 2;
301
+ div.style.position = 'absolute';
302
+ div.style.display = 'block';
303
+ div.style.zIndex = 10;
304
+ div.style.width = `${blockSize}px`;
305
+ div.style.height = `${blockSize}px`;
306
+ div.style.top = `${position.top - offset}px`;
307
+ div.style.left = `${position.left - offset}px`;
308
+ parentElement.appendChild(div);
309
+ setTimeout(() => {
310
+ div.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._forceCursorCapture(parent, {
329
+ top: clientY - parentRect.top,
330
+ left: clientX - parentRect.left,
331
+ });
332
+ }
333
+ this.setState({ draggedOut });
334
+ }
335
+ _resetDragWatcher() {
336
+ this._parendDragNode = null;
337
+ this.setState({ draggedOut: false });
338
+ }
290
339
  _onDragStart(group, _newLayout, layoutItem, _newItem, _placeholder, e, element) {
291
340
  var _a;
292
341
  (_a = this.context.onDragStart) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, _newLayout, layoutItem, _newItem, _placeholder, e, element));
342
+ this._initDragCoordinatesWatcher(element);
293
343
  if (this.context.dragOverPlugin) {
294
344
  this.setState({ isDragging: true });
295
345
  }
@@ -300,10 +350,12 @@ class GridLayout extends react_1.default.PureComponent {
300
350
  }
301
351
  _onDrag(group, layout, oldItem, newItem, placeholder, e, element) {
302
352
  var _a;
353
+ this._updateDragCoordinates(e, element);
303
354
  (_a = this.context.onDrag) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
304
355
  }
305
356
  _onDragStop(group, layout, oldItem, newItem, placeholder, e, element) {
306
357
  var _a;
358
+ this._resetDragWatcher();
307
359
  this._onStop(group, layout);
308
360
  (_a = this.context.onDragStop) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
309
361
  }
@@ -327,6 +379,7 @@ class GridLayout extends react_1.default.PureComponent {
327
379
  if (this.context.temporaryLayout) {
328
380
  return;
329
381
  }
382
+ console.log('_onTargetRestore');
330
383
  const { currentDraggingElement } = this.state;
331
384
  if (currentDraggingElement) {
332
385
  this.setState({
@@ -375,7 +428,7 @@ class GridLayout extends react_1.default.PureComponent {
375
428
  }
376
429
  : null)),
377
430
  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 }));
431
+ 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, draggedOut: this.state.draggedOut, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), onItemMountChange: onItemMountChange, onItemRender: onItemRender }));
379
432
  }),
380
433
  this.renderTemporaryPlaceholder()));
381
434
  }
@@ -61,9 +61,9 @@ declare const _default: {
61
61
  height: PropTypes.Requireable<number>;
62
62
  transform: PropTypes.Requireable<string>;
63
63
  isPlaceholder: PropTypes.Requireable<boolean>;
64
- onBeforeLoad: PropTypes.Requireable<(...args: any[]) => any>;
64
+ onItemRender: PropTypes.Requireable<(...args: any[]) => any>;
65
+ onItemMountChange: PropTypes.Requireable<(...args: any[]) => any>;
65
66
  forwardedPluginRef: PropTypes.Requireable<any>;
66
- onMountChange: PropTypes.Requireable<(...args: any[]) => any>;
67
67
  };
68
68
  contextType: React.Context<any>;
69
69
  };
@@ -7,26 +7,56 @@ const prepareItem_1 = require("../../hocs/prepareItem");
7
7
  const cn_1 = require("../../utils/cn");
8
8
  const b = (0, cn_1.cn)('dashkit-item');
9
9
  // TODO: getDerivedStateFromError и заглушка с ошибкой
10
- const Item = ({ registerManager, rendererProps, type, isPlaceholder, forwardedPluginRef, onMountChange, }) => {
10
+ const Item = ({ registerManager, rendererProps, type, isPlaceholder, forwardedPluginRef, onItemRender, onItemMountChange, item, }) => {
11
11
  var _a, _b;
12
+ // to avoid too frequent re-creation of functions that do not affect the rendering
13
+ const isAsyncItemRef = react_1.default.useRef(false);
14
+ const itemRef = react_1.default.useRef(item);
15
+ const onItemRenderRef = react_1.default.useRef(onItemRender);
16
+ const onItemMountChangeRef = react_1.default.useRef(onItemMountChange);
17
+ itemRef.current = item;
18
+ onItemRenderRef.current = onItemRender;
19
+ onItemMountChangeRef.current = onItemMountChange;
12
20
  const isRegisteredType = registerManager.check(type);
13
21
  react_1.default.useLayoutEffect(() => {
22
+ var _a, _b;
14
23
  if (isRegisteredType && !isPlaceholder) {
15
- onMountChange === null || onMountChange === void 0 ? void 0 : onMountChange(true);
24
+ (_a = onItemMountChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onItemMountChangeRef, itemRef.current, {
25
+ isAsync: isAsyncItemRef.current,
26
+ isMounted: true,
27
+ });
28
+ if (!isAsyncItemRef.current) {
29
+ (_b = onItemRenderRef.current) === null || _b === void 0 ? void 0 : _b.call(onItemRenderRef, itemRef.current);
30
+ }
16
31
  return () => {
17
- onMountChange === null || onMountChange === void 0 ? void 0 : onMountChange(false);
32
+ var _a;
33
+ (_a = onItemMountChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onItemMountChangeRef, itemRef.current, {
34
+ isAsync: isAsyncItemRef.current,
35
+ isMounted: false,
36
+ });
18
37
  };
19
38
  }
20
39
  }, []);
40
+ const onLoad = react_1.default.useCallback(() => {
41
+ var _a;
42
+ (_a = onItemRenderRef.current) === null || _a === void 0 ? void 0 : _a.call(onItemRenderRef, itemRef.current);
43
+ }, []);
44
+ const onBeforeLoad = react_1.default.useCallback(() => {
45
+ isAsyncItemRef.current = true;
46
+ return onLoad;
47
+ }, [onLoad]);
48
+ const itemRendererProps = react_1.default.useMemo(() => {
49
+ return Object.assign(Object.assign({}, rendererProps), { onBeforeLoad });
50
+ }, [rendererProps, onBeforeLoad]);
21
51
  if (!isRegisteredType) {
22
52
  console.warn(`type [${type}] не зарегистрирован`);
23
53
  return null;
24
54
  }
25
55
  if (isPlaceholder) {
26
56
  return (react_1.default.createElement("div", { className: b('placeholder') }, ((_b = (_a = registerManager
27
- .getItem(type)).placeholderRenderer) === null || _b === void 0 ? void 0 : _b.call(_a, rendererProps, forwardedPluginRef)) || null));
57
+ .getItem(type)).placeholderRenderer) === null || _b === void 0 ? void 0 : _b.call(_a, itemRendererProps, forwardedPluginRef)) || null));
28
58
  }
29
- return (react_1.default.createElement("div", { className: b('renderer') }, registerManager.getItem(type).renderer(rendererProps, forwardedPluginRef)));
59
+ return (react_1.default.createElement("div", { className: b('renderer') }, registerManager.getItem(type).renderer(itemRendererProps, forwardedPluginRef)));
30
60
  };
31
61
  Item.propTypes = {
32
62
  forwardedPluginRef: prop_types_1.default.any,
@@ -34,7 +64,8 @@ Item.propTypes = {
34
64
  registerManager: prop_types_1.default.object,
35
65
  type: prop_types_1.default.string,
36
66
  isPlaceholder: prop_types_1.default.bool,
37
- onMountChange: prop_types_1.default.func,
38
- onBeforeLoad: prop_types_1.default.func,
67
+ onItemRender: prop_types_1.default.func,
68
+ onItemMountChange: prop_types_1.default.func,
69
+ item: prop_types_1.default.object,
39
70
  };
40
71
  exports.default = (0, prepareItem_1.prepareItem)(Item);
@@ -18,11 +18,6 @@ export default class MobileLayout extends React.PureComponent<any, any, any> {
18
18
  needSetDefault: any;
19
19
  }) => void;
20
20
  getMemoAdjustWidgetLayout: (index: any) => any;
21
- onMountChange: (isMounted: any) => void;
22
- _inited: boolean | undefined;
23
- onBeforeLoad: () => () => void;
24
- _isAsyncItem: boolean | undefined;
25
- onLoad: () => void;
26
21
  render(): JSX.Element;
27
22
  }
28
23
  import React from 'react';
@@ -44,33 +44,6 @@ class MobileLayout extends react_1.default.PureComponent {
44
44
  }
45
45
  return this._memoAdjustWidgetLayout[index];
46
46
  };
47
- this.onMountChange = (isMounted) => {
48
- var _a, _b, _c, _d, _e, _f;
49
- if (isMounted) {
50
- this._inited = true;
51
- (_b = (_a = this.context).onItemMountChange) === null || _b === void 0 ? void 0 : _b.call(_a, this.props.item, {
52
- isAsync: this._isAsyncItem,
53
- isMounted: isMounted,
54
- });
55
- if (!this._isAsyncItem) {
56
- (_d = (_c = this.context).onItemRender) === null || _d === void 0 ? void 0 : _d.call(_c, this.props.item);
57
- }
58
- }
59
- else {
60
- (_f = (_e = this.context).onItemMountChange) === null || _f === void 0 ? void 0 : _f.call(_e, this.props.item, {
61
- isAsync: this._isAsyncItem,
62
- isMounted: isMounted,
63
- });
64
- }
65
- };
66
- this.onBeforeLoad = () => {
67
- this._isAsyncItem = true;
68
- return this.onLoad;
69
- };
70
- this.onLoad = () => {
71
- var _a, _b;
72
- (_b = (_a = this.context).onItemRender) === null || _b === void 0 ? void 0 : _b.call(_a, this.props.item);
73
- };
74
47
  }
75
48
  componentDidUpdate(prevProps, prevState) {
76
49
  if (prevState.activeTabId !== this.context.config.id) {
@@ -96,7 +69,7 @@ class MobileLayout extends react_1.default.PureComponent {
96
69
  return (react_1.default.createElement("div", { className: b() }, sortedItems.map((item, index) => {
97
70
  const isItemWithActiveAutoheight = index in this.state.indexesOfItemsWithActiveAutoheight;
98
71
  return (react_1.default.createElement("div", { className: b('item', { autoheight: isItemWithActiveAutoheight }), key: item.id },
99
- react_1.default.createElement(Item_1.default, { id: item.id, item: item, layout: layout, shouldItemUpdate: false, adjustWidgetLayout: this.getMemoAdjustWidgetLayout(index), forwardedPluginRef: this.getMemoForwardRefCallback(index), onMountChange: this.onMountChange, onBeforeLoad: this.onBeforeLoad })));
72
+ react_1.default.createElement(Item_1.default, { id: item.id, item: item, layout: layout, shouldItemUpdate: false, adjustWidgetLayout: this.getMemoAdjustWidgetLayout(index), forwardedPluginRef: this.getMemoForwardRefCallback(index), onMountChange: this.onMountChange, onItemMountChange: this.context.onItemMountChange, onItemRender: this.context.onItemRender })));
100
73
  })));
101
74
  }
102
75
  }
@@ -61,9 +61,9 @@ export function prepareItem(Component: any): {
61
61
  height: PropTypes.Requireable<number>;
62
62
  transform: PropTypes.Requireable<string>;
63
63
  isPlaceholder: PropTypes.Requireable<boolean>;
64
- onBeforeLoad: PropTypes.Requireable<(...args: any[]) => any>;
64
+ onItemRender: PropTypes.Requireable<(...args: any[]) => any>;
65
+ onItemMountChange: PropTypes.Requireable<(...args: any[]) => any>;
65
66
  forwardedPluginRef: PropTypes.Requireable<any>;
66
- onMountChange: PropTypes.Requireable<(...args: any[]) => any>;
67
67
  };
68
68
  contextType: React.Context<any>;
69
69
  };
@@ -15,7 +15,7 @@ function prepareItem(Component) {
15
15
  };
16
16
  this._currentRenderProps = {};
17
17
  this.getRenderProps = () => {
18
- const { id, width, height, item, adjustWidgetLayout, layout, isPlaceholder, onBeforeLoad, } = this.props;
18
+ const { id, width, height, item, adjustWidgetLayout, layout, isPlaceholder } = this.props;
19
19
  const { itemsState, itemsParams, registerManager, settings, context, editMode } = this.context;
20
20
  const { data, defaults, namespace } = item;
21
21
  const rendererProps = {
@@ -24,7 +24,6 @@ function prepareItem(Component) {
24
24
  params: itemsParams[id],
25
25
  state: itemsState[id],
26
26
  onStateAndParamsChange: this._onStateAndParamsChange,
27
- onBeforeLoad,
28
27
  width,
29
28
  height,
30
29
  id,
@@ -56,10 +55,10 @@ function prepareItem(Component) {
56
55
  return true;
57
56
  }
58
57
  render() {
59
- const { item, isPlaceholder, forwardedPluginRef, onMountChange } = this.props;
58
+ const { item, isPlaceholder, forwardedPluginRef, onItemMountChange, onItemRender } = this.props;
60
59
  const { registerManager } = this.context;
61
60
  const { type } = item;
62
- return (react_1.default.createElement(Component, { forwardedPluginRef: forwardedPluginRef, rendererProps: this.getRenderProps(), registerManager: registerManager, type: type, isPlaceholder: isPlaceholder, onMountChange: onMountChange }));
61
+ return (react_1.default.createElement(Component, { forwardedPluginRef: forwardedPluginRef, rendererProps: this.getRenderProps(), registerManager: registerManager, type: type, isPlaceholder: isPlaceholder, onItemMountChange: onItemMountChange, onItemRender: onItemRender, item: item }));
63
62
  }
64
63
  },
65
64
  _a.propTypes = {
@@ -72,9 +71,9 @@ function prepareItem(Component) {
72
71
  height: prop_types_1.default.number,
73
72
  transform: prop_types_1.default.string,
74
73
  isPlaceholder: prop_types_1.default.bool,
75
- onBeforeLoad: prop_types_1.default.func,
74
+ onItemRender: prop_types_1.default.func,
75
+ onItemMountChange: prop_types_1.default.func,
76
76
  forwardedPluginRef: prop_types_1.default.any,
77
- onMountChange: prop_types_1.default.func,
78
77
  },
79
78
  _a.contextType = DashKitContext_1.DashKitContext,
80
79
  _a;
@@ -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 {
@@ -79,33 +79,6 @@ class GridItem extends React.PureComponent {
79
79
  this.controller = null;
80
80
  });
81
81
  };
82
- this.onMountChange = (isMounted) => {
83
- var _a, _b, _c, _d, _e, _f;
84
- if (isMounted) {
85
- this._inited = true;
86
- (_b = (_a = this.props).onItemMountChange) === null || _b === void 0 ? void 0 : _b.call(_a, this.props.item, {
87
- isAsync: this._isAsyncItem,
88
- isMounted: isMounted,
89
- });
90
- if (!this._isAsyncItem) {
91
- (_d = (_c = this.props).onItemRender) === null || _d === void 0 ? void 0 : _d.call(_c, this.props.item);
92
- }
93
- }
94
- else {
95
- (_f = (_e = this.props).onItemMountChange) === null || _f === void 0 ? void 0 : _f.call(_e, this.props.item, {
96
- isAsync: this._isAsyncItem,
97
- isMounted: isMounted,
98
- });
99
- }
100
- };
101
- this.onBeforeLoad = () => {
102
- this._isAsyncItem = true;
103
- return this.onLoad;
104
- };
105
- this.onLoad = () => {
106
- var _a, _b;
107
- (_b = (_a = this.props).onItemRender) === null || _b === void 0 ? void 0 : _b.call(_a, this.props.item);
108
- };
109
82
  }
110
83
  renderOverlay() {
111
84
  const { isPlaceholder } = this.props;
@@ -121,7 +94,7 @@ class GridItem extends React.PureComponent {
121
94
  render() {
122
95
  // из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
123
96
  // https://github.com/STRML/react-grid-layout/issues/721
124
- 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, draggedOut, noOverlay, focusable, withCustomHandle, isPlaceholder = false, } = this.props;
125
98
  const { editMode } = this.context;
126
99
  const width = Number.parseInt(style.width, 10);
127
100
  const height = Number.parseInt(style.height, 10);
@@ -140,6 +113,7 @@ class GridItem extends React.PureComponent {
140
113
  const { _editActive } = this.props.item.data;
141
114
  return (React.createElement("div", Object.assign({ className: b({
142
115
  'is-dragging': isDragging,
116
+ 'is-dragged-out': draggedOut,
143
117
  'is-focused': this.state.isFocused,
144
118
  'with-custom-handle': withCustomHandle,
145
119
  }, preparedClassName), "data-qa": "dashkit-grid-item", style: style, ref: this.props.forwardedRef }, reactGridLayoutProps, (focusable
@@ -150,7 +124,7 @@ class GridItem extends React.PureComponent {
150
124
  }
151
125
  : {})),
152
126
  React.createElement("div", { className: b('item', { editMode: editMode && !_editActive && !noOverlay }) },
153
- React.createElement(Item, { id: this.props.id, item: this.props.item, shouldItemUpdate: !isDragging, width: width, height: height, transform: transform, isPlaceholder: isPlaceholder, adjustWidgetLayout: this.props.adjustWidgetLayout, layout: this.props.layout, forwardedPluginRef: this.props.forwardedPluginRef, onMountChange: this.onMountChange, onBeforeLoad: this.onBeforeLoad })),
127
+ React.createElement(Item, { id: this.props.id, item: this.props.item, shouldItemUpdate: !isDragging, width: width, height: height, transform: transform, isPlaceholder: isPlaceholder, adjustWidgetLayout: this.props.adjustWidgetLayout, layout: this.props.layout, forwardedPluginRef: this.props.forwardedPluginRef, onItemMountChange: this.props.onItemMountChange, onItemRender: this.props.onItemRender })),
154
128
  !noOverlay && this.renderOverlay(),
155
129
  preparedChildren));
156
130
  }
@@ -160,10 +134,13 @@ GridItem.propTypes = {
160
134
  id: PropTypes.string,
161
135
  item: PropTypes.object,
162
136
  isDragging: PropTypes.bool,
137
+ draggedOut: PropTypes.bool,
163
138
  layout: PropTypes.array,
164
139
  forwardedRef: PropTypes.any,
165
140
  forwardedPluginRef: PropTypes.any,
166
141
  isPlaceholder: PropTypes.bool,
142
+ onItemMountChange: PropTypes.func,
143
+ onItemRender: PropTypes.func,
167
144
  // from react-grid-layout:
168
145
  children: PropTypes.node,
169
146
  className: PropTypes.string,
@@ -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;
@@ -48,6 +49,11 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
48
49
  element: any;
49
50
  };
50
51
  updateeDraggingElementState(group: any, layoutItem: any, e: any): void;
52
+ _initDragCoordinatesWatcher(element: any): void;
53
+ _parendDragNode: any;
54
+ _forceCursorCapture(parentElement: any, position: 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() {
@@ -284,9 +285,58 @@ 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
+ _forceCursorCapture(parentElement, position) {
295
+ const div = document.createElement('div');
296
+ const blockSize = 50;
297
+ const offset = blockSize / 2;
298
+ div.style.position = 'absolute';
299
+ div.style.display = 'block';
300
+ div.style.zIndex = 10;
301
+ div.style.width = `${blockSize}px`;
302
+ div.style.height = `${blockSize}px`;
303
+ div.style.top = `${position.top - offset}px`;
304
+ div.style.left = `${position.left - offset}px`;
305
+ parentElement.appendChild(div);
306
+ setTimeout(() => {
307
+ div.remove();
308
+ }, 100);
309
+ }
310
+ _updateDragCoordinates(e) {
311
+ const parent = this._parendDragNode;
312
+ const parentRect = parent.getBoundingClientRect();
313
+ const { clientX, clientY } = e;
314
+ let draggedOut = this.state.draggedOut;
315
+ if (clientX < parentRect.left ||
316
+ clientX > parentRect.right ||
317
+ clientY < parentRect.top ||
318
+ clientY > parentRect.bottom) {
319
+ draggedOut = true;
320
+ }
321
+ else {
322
+ draggedOut = false;
323
+ }
324
+ if (draggedOut !== this.state.draggedOut) {
325
+ this._forceCursorCapture(parent, {
326
+ top: clientY - parentRect.top,
327
+ left: clientX - parentRect.left,
328
+ });
329
+ }
330
+ this.setState({ draggedOut });
331
+ }
332
+ _resetDragWatcher() {
333
+ this._parendDragNode = null;
334
+ this.setState({ draggedOut: false });
335
+ }
287
336
  _onDragStart(group, _newLayout, layoutItem, _newItem, _placeholder, e, element) {
288
337
  var _a;
289
338
  (_a = this.context.onDragStart) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, _newLayout, layoutItem, _newItem, _placeholder, e, element));
339
+ this._initDragCoordinatesWatcher(element);
290
340
  if (this.context.dragOverPlugin) {
291
341
  this.setState({ isDragging: true });
292
342
  }
@@ -297,10 +347,12 @@ class GridLayout extends React.PureComponent {
297
347
  }
298
348
  _onDrag(group, layout, oldItem, newItem, placeholder, e, element) {
299
349
  var _a;
350
+ this._updateDragCoordinates(e, element);
300
351
  (_a = this.context.onDrag) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
301
352
  }
302
353
  _onDragStop(group, layout, oldItem, newItem, placeholder, e, element) {
303
354
  var _a;
355
+ this._resetDragWatcher();
304
356
  this._onStop(group, layout);
305
357
  (_a = this.context.onDragStop) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
306
358
  }
@@ -324,6 +376,7 @@ class GridLayout extends React.PureComponent {
324
376
  if (this.context.temporaryLayout) {
325
377
  return;
326
378
  }
379
+ console.log('_onTargetRestore');
327
380
  const { currentDraggingElement } = this.state;
328
381
  if (currentDraggingElement) {
329
382
  this.setState({
@@ -372,7 +425,7 @@ class GridLayout extends React.PureComponent {
372
425
  }
373
426
  : null)),
374
427
  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 }));
428
+ 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, draggedOut: this.state.draggedOut, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), onItemMountChange: onItemMountChange, onItemRender: onItemRender }));
376
429
  }),
377
430
  this.renderTemporaryPlaceholder()));
378
431
  }
@@ -61,9 +61,9 @@ declare const _default: {
61
61
  height: PropTypes.Requireable<number>;
62
62
  transform: PropTypes.Requireable<string>;
63
63
  isPlaceholder: PropTypes.Requireable<boolean>;
64
- onBeforeLoad: PropTypes.Requireable<(...args: any[]) => any>;
64
+ onItemRender: PropTypes.Requireable<(...args: any[]) => any>;
65
+ onItemMountChange: PropTypes.Requireable<(...args: any[]) => any>;
65
66
  forwardedPluginRef: PropTypes.Requireable<any>;
66
- onMountChange: PropTypes.Requireable<(...args: any[]) => any>;
67
67
  };
68
68
  contextType: React.Context<any>;
69
69
  };
@@ -5,26 +5,56 @@ import { cn } from '../../utils/cn';
5
5
  import './Item.css';
6
6
  const b = cn('dashkit-item');
7
7
  // TODO: getDerivedStateFromError и заглушка с ошибкой
8
- const Item = ({ registerManager, rendererProps, type, isPlaceholder, forwardedPluginRef, onMountChange, }) => {
8
+ const Item = ({ registerManager, rendererProps, type, isPlaceholder, forwardedPluginRef, onItemRender, onItemMountChange, item, }) => {
9
9
  var _a, _b;
10
+ // to avoid too frequent re-creation of functions that do not affect the rendering
11
+ const isAsyncItemRef = React.useRef(false);
12
+ const itemRef = React.useRef(item);
13
+ const onItemRenderRef = React.useRef(onItemRender);
14
+ const onItemMountChangeRef = React.useRef(onItemMountChange);
15
+ itemRef.current = item;
16
+ onItemRenderRef.current = onItemRender;
17
+ onItemMountChangeRef.current = onItemMountChange;
10
18
  const isRegisteredType = registerManager.check(type);
11
19
  React.useLayoutEffect(() => {
20
+ var _a, _b;
12
21
  if (isRegisteredType && !isPlaceholder) {
13
- onMountChange === null || onMountChange === void 0 ? void 0 : onMountChange(true);
22
+ (_a = onItemMountChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onItemMountChangeRef, itemRef.current, {
23
+ isAsync: isAsyncItemRef.current,
24
+ isMounted: true,
25
+ });
26
+ if (!isAsyncItemRef.current) {
27
+ (_b = onItemRenderRef.current) === null || _b === void 0 ? void 0 : _b.call(onItemRenderRef, itemRef.current);
28
+ }
14
29
  return () => {
15
- onMountChange === null || onMountChange === void 0 ? void 0 : onMountChange(false);
30
+ var _a;
31
+ (_a = onItemMountChangeRef.current) === null || _a === void 0 ? void 0 : _a.call(onItemMountChangeRef, itemRef.current, {
32
+ isAsync: isAsyncItemRef.current,
33
+ isMounted: false,
34
+ });
16
35
  };
17
36
  }
18
37
  }, []);
38
+ const onLoad = React.useCallback(() => {
39
+ var _a;
40
+ (_a = onItemRenderRef.current) === null || _a === void 0 ? void 0 : _a.call(onItemRenderRef, itemRef.current);
41
+ }, []);
42
+ const onBeforeLoad = React.useCallback(() => {
43
+ isAsyncItemRef.current = true;
44
+ return onLoad;
45
+ }, [onLoad]);
46
+ const itemRendererProps = React.useMemo(() => {
47
+ return Object.assign(Object.assign({}, rendererProps), { onBeforeLoad });
48
+ }, [rendererProps, onBeforeLoad]);
19
49
  if (!isRegisteredType) {
20
50
  console.warn(`type [${type}] не зарегистрирован`);
21
51
  return null;
22
52
  }
23
53
  if (isPlaceholder) {
24
54
  return (React.createElement("div", { className: b('placeholder') }, ((_b = (_a = registerManager
25
- .getItem(type)).placeholderRenderer) === null || _b === void 0 ? void 0 : _b.call(_a, rendererProps, forwardedPluginRef)) || null));
55
+ .getItem(type)).placeholderRenderer) === null || _b === void 0 ? void 0 : _b.call(_a, itemRendererProps, forwardedPluginRef)) || null));
26
56
  }
27
- return (React.createElement("div", { className: b('renderer') }, registerManager.getItem(type).renderer(rendererProps, forwardedPluginRef)));
57
+ return (React.createElement("div", { className: b('renderer') }, registerManager.getItem(type).renderer(itemRendererProps, forwardedPluginRef)));
28
58
  };
29
59
  Item.propTypes = {
30
60
  forwardedPluginRef: PropTypes.any,
@@ -32,7 +62,8 @@ Item.propTypes = {
32
62
  registerManager: PropTypes.object,
33
63
  type: PropTypes.string,
34
64
  isPlaceholder: PropTypes.bool,
35
- onMountChange: PropTypes.func,
36
- onBeforeLoad: PropTypes.func,
65
+ onItemRender: PropTypes.func,
66
+ onItemMountChange: PropTypes.func,
67
+ item: PropTypes.object,
37
68
  };
38
69
  export default prepareItem(Item);
@@ -18,11 +18,6 @@ export default class MobileLayout extends React.PureComponent<any, any, any> {
18
18
  needSetDefault: any;
19
19
  }) => void;
20
20
  getMemoAdjustWidgetLayout: (index: any) => any;
21
- onMountChange: (isMounted: any) => void;
22
- _inited: boolean | undefined;
23
- onBeforeLoad: () => () => void;
24
- _isAsyncItem: boolean | undefined;
25
- onLoad: () => void;
26
21
  render(): JSX.Element;
27
22
  }
28
23
  import React from 'react';
@@ -42,33 +42,6 @@ class MobileLayout extends React.PureComponent {
42
42
  }
43
43
  return this._memoAdjustWidgetLayout[index];
44
44
  };
45
- this.onMountChange = (isMounted) => {
46
- var _a, _b, _c, _d, _e, _f;
47
- if (isMounted) {
48
- this._inited = true;
49
- (_b = (_a = this.context).onItemMountChange) === null || _b === void 0 ? void 0 : _b.call(_a, this.props.item, {
50
- isAsync: this._isAsyncItem,
51
- isMounted: isMounted,
52
- });
53
- if (!this._isAsyncItem) {
54
- (_d = (_c = this.context).onItemRender) === null || _d === void 0 ? void 0 : _d.call(_c, this.props.item);
55
- }
56
- }
57
- else {
58
- (_f = (_e = this.context).onItemMountChange) === null || _f === void 0 ? void 0 : _f.call(_e, this.props.item, {
59
- isAsync: this._isAsyncItem,
60
- isMounted: isMounted,
61
- });
62
- }
63
- };
64
- this.onBeforeLoad = () => {
65
- this._isAsyncItem = true;
66
- return this.onLoad;
67
- };
68
- this.onLoad = () => {
69
- var _a, _b;
70
- (_b = (_a = this.context).onItemRender) === null || _b === void 0 ? void 0 : _b.call(_a, this.props.item);
71
- };
72
45
  }
73
46
  componentDidUpdate(prevProps, prevState) {
74
47
  if (prevState.activeTabId !== this.context.config.id) {
@@ -94,7 +67,7 @@ class MobileLayout extends React.PureComponent {
94
67
  return (React.createElement("div", { className: b() }, sortedItems.map((item, index) => {
95
68
  const isItemWithActiveAutoheight = index in this.state.indexesOfItemsWithActiveAutoheight;
96
69
  return (React.createElement("div", { className: b('item', { autoheight: isItemWithActiveAutoheight }), key: item.id },
97
- React.createElement(Item, { id: item.id, item: item, layout: layout, shouldItemUpdate: false, adjustWidgetLayout: this.getMemoAdjustWidgetLayout(index), forwardedPluginRef: this.getMemoForwardRefCallback(index), onMountChange: this.onMountChange, onBeforeLoad: this.onBeforeLoad })));
70
+ React.createElement(Item, { id: item.id, item: item, layout: layout, shouldItemUpdate: false, adjustWidgetLayout: this.getMemoAdjustWidgetLayout(index), forwardedPluginRef: this.getMemoForwardRefCallback(index), onMountChange: this.onMountChange, onItemMountChange: this.context.onItemMountChange, onItemRender: this.context.onItemRender })));
98
71
  })));
99
72
  }
100
73
  }
@@ -61,9 +61,9 @@ export function prepareItem(Component: any): {
61
61
  height: PropTypes.Requireable<number>;
62
62
  transform: PropTypes.Requireable<string>;
63
63
  isPlaceholder: PropTypes.Requireable<boolean>;
64
- onBeforeLoad: PropTypes.Requireable<(...args: any[]) => any>;
64
+ onItemRender: PropTypes.Requireable<(...args: any[]) => any>;
65
+ onItemMountChange: PropTypes.Requireable<(...args: any[]) => any>;
65
66
  forwardedPluginRef: PropTypes.Requireable<any>;
66
- onMountChange: PropTypes.Requireable<(...args: any[]) => any>;
67
67
  };
68
68
  contextType: React.Context<any>;
69
69
  };
@@ -11,7 +11,7 @@ export function prepareItem(Component) {
11
11
  };
12
12
  this._currentRenderProps = {};
13
13
  this.getRenderProps = () => {
14
- const { id, width, height, item, adjustWidgetLayout, layout, isPlaceholder, onBeforeLoad, } = this.props;
14
+ const { id, width, height, item, adjustWidgetLayout, layout, isPlaceholder } = this.props;
15
15
  const { itemsState, itemsParams, registerManager, settings, context, editMode } = this.context;
16
16
  const { data, defaults, namespace } = item;
17
17
  const rendererProps = {
@@ -20,7 +20,6 @@ export function prepareItem(Component) {
20
20
  params: itemsParams[id],
21
21
  state: itemsState[id],
22
22
  onStateAndParamsChange: this._onStateAndParamsChange,
23
- onBeforeLoad,
24
23
  width,
25
24
  height,
26
25
  id,
@@ -52,10 +51,10 @@ export function prepareItem(Component) {
52
51
  return true;
53
52
  }
54
53
  render() {
55
- const { item, isPlaceholder, forwardedPluginRef, onMountChange } = this.props;
54
+ const { item, isPlaceholder, forwardedPluginRef, onItemMountChange, onItemRender } = this.props;
56
55
  const { registerManager } = this.context;
57
56
  const { type } = item;
58
- return (React.createElement(Component, { forwardedPluginRef: forwardedPluginRef, rendererProps: this.getRenderProps(), registerManager: registerManager, type: type, isPlaceholder: isPlaceholder, onMountChange: onMountChange }));
57
+ return (React.createElement(Component, { forwardedPluginRef: forwardedPluginRef, rendererProps: this.getRenderProps(), registerManager: registerManager, type: type, isPlaceholder: isPlaceholder, onItemMountChange: onItemMountChange, onItemRender: onItemRender, item: item }));
59
58
  }
60
59
  },
61
60
  _a.propTypes = {
@@ -68,9 +67,9 @@ export function prepareItem(Component) {
68
67
  height: PropTypes.number,
69
68
  transform: PropTypes.string,
70
69
  isPlaceholder: PropTypes.bool,
71
- onBeforeLoad: PropTypes.func,
70
+ onItemRender: PropTypes.func,
71
+ onItemMountChange: PropTypes.func,
72
72
  forwardedPluginRef: PropTypes.any,
73
- onMountChange: PropTypes.func,
74
73
  },
75
74
  _a.contextType = DashKitContext,
76
75
  _a;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dashkit",
3
- "version": "8.17.2",
3
+ "version": "8.17.3-beta.0",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {