@gravity-ui/dashkit 8.13.0 → 8.14.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.
package/README.md CHANGED
@@ -24,6 +24,15 @@ Plugins are required to create custom widgets.
24
24
  ### Props
25
25
 
26
26
  ```ts
27
+ type ItemManipulationCallback = (eventData: {
28
+ layout: Layouts;
29
+ oldItem: Layout;
30
+ newItem: Layout;
31
+ placeholder: Layout;
32
+ e: MouseEvent;
33
+ element: HTMLElement;
34
+ }) => void;
35
+
27
36
  interface DashKitProps {
28
37
  config: Config;
29
38
  editMode: boolean;
@@ -32,6 +41,14 @@ interface DashKitProps {
32
41
  onDrop: (dropProps: ItemDropProps) => void;
33
42
  onItemMountChange: (item: ConfigItem, state: {isAsync: boolead; isMounted: boolean}) => void;
34
43
  onItemRender: (item: ConfigItem) => void;
44
+
45
+ onDragStart?: ItemManipulationCallback;
46
+ onDrag?: ItemManipulationCallback;
47
+ onDragStop?: ItemManipulationCallback;
48
+ onResizeStart?: ItemManipulationCallback;
49
+ onResize?: ItemManipulationCallback;
50
+ onResizeStop?: ItemManipulationCallback;
51
+
35
52
  defaultGlobalParams: GlobalParams;
36
53
  globalParams: GlobalParams;
37
54
  itemsStateAndParams: ItemsStateAndParams;
@@ -61,6 +78,12 @@ interface DashKitProps {
61
78
  - **noOverlay**: If `true`, overlay and controls are not displayed while editing.
62
79
  - **focusable**: If `true`, grid items will be focusable.
63
80
  - **draggableHandleClassName** : СSS class name of the element that makes the widget draggable.
81
+ - **onDragStart**: ReactGridLayout called when item drag started
82
+ - **onDrag**: ReactGridLayout called while item drag
83
+ - **onDragStop**: ReactGridLayout called when item drag stopped
84
+ - **onResizeStart**: ReactGridLayout called when item resize started
85
+ - **onResize**: ReactGridLayout called while item resizing
86
+ - **onResizeStop**: ReactGridLayout called when item resize stoped
64
87
 
65
88
  ## Usage
66
89
 
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { Config, ConfigItem, ConfigLayout, GlobalParams, ItemDropProps, ItemsStateAndParams } from '../../shared';
3
- import { AddNewItemOptions, ContextProps, DashKitGroup, MenuItem, Plugin, SetConfigItem, Settings, SettingsProps } from '../../typings';
3
+ import { AddNewItemOptions, ContextProps, DashKitGroup, ItemManipulationCallback, MenuItem, Plugin, SetConfigItem, Settings, SettingsProps } from '../../typings';
4
4
  import GridLayout from '../GridLayout/GridLayout';
5
5
  import { OverlayControlItem } from '../OverlayControls/OverlayControls';
6
6
  interface DashKitGeneralProps {
@@ -17,12 +17,18 @@ interface DashKitDefaultProps {
17
17
  itemsStateAndParams: ItemsStateAndParams;
18
18
  groups?: DashKitGroup[];
19
19
  }) => void;
20
- onDrop: (dropProps: ItemDropProps) => void;
20
+ onDrop?: (dropProps: ItemDropProps) => void;
21
21
  onItemMountChange?: (item: ConfigItem, state: {
22
22
  isAsync: boolean;
23
23
  isMounted: boolean;
24
24
  }) => void;
25
25
  onItemRender?: (item: ConfigItem) => void;
26
+ onDragStart?: ItemManipulationCallback;
27
+ onDrag?: ItemManipulationCallback;
28
+ onDragStop?: ItemManipulationCallback;
29
+ onResizeStart?: ItemManipulationCallback;
30
+ onResize?: ItemManipulationCallback;
31
+ onResizeStop?: ItemManipulationCallback;
26
32
  defaultGlobalParams: GlobalParams;
27
33
  globalParams: GlobalParams;
28
34
  itemsStateAndParams: ItemsStateAndParams;
@@ -25,8 +25,8 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
25
25
  }) => void;
26
26
  getItemsMeta: () => any;
27
27
  getActiveLayout(): any;
28
- getMemoGroupLayout: (group: any, layout: any) => any;
29
- getMemoGroupCallbacks: (group: any) => any;
28
+ getMemoGroupLayout(group: any, layout: any): any;
29
+ getMemoGroupCallbacks(group: any): any;
30
30
  getMemoGroupProps: (group: any, renderLayout: any, properties: any) => {
31
31
  layout: any;
32
32
  callbacks: any;
@@ -38,9 +38,23 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
38
38
  getMemoForwardRefCallback: (refIndex: any) => any;
39
39
  mergeGroupsLayout(group: any, newLayout: any, temporaryItem: any): any;
40
40
  reloadItems(): void;
41
- _onDragStart: (group: any, _newLayout: any, layoutItem: any, _newItem: any, _placeholder: any, e: any) => void;
42
- _onResizeStart: () => void;
43
- _onTargetRestore: () => void;
41
+ prepareDefaultArguments(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): {
42
+ group: any;
43
+ layout: any;
44
+ oldItem: any;
45
+ newItem: any;
46
+ placeholder: any;
47
+ e: any;
48
+ element: any;
49
+ };
50
+ updateeDraggingElementState(group: any, layoutItem: any, e: any): void;
51
+ _onDragStart(group: any, _newLayout: any, layoutItem: any, _newItem: any, _placeholder: any, e: any, element: any): void;
52
+ _onDrag(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
53
+ _onDragStop(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
54
+ _onResizeStart(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
55
+ _onResize(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
56
+ _onResizeStop(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
57
+ _onTargetRestore(): void;
44
58
  _onStop: (group: any, newLayout: any) => void;
45
59
  _onSharedDrop: (targetGroup: any, newLayout: any, tempItem: any) => void;
46
60
  _onExternalDrop: (group: any, newLayout: any, item: any, e: any) => void;
@@ -4,6 +4,7 @@ const tslib_1 = require("tslib");
4
4
  const react_1 = tslib_1.__importDefault(require("react"));
5
5
  const constants_1 = require("../../constants");
6
6
  const DashKitContext_1 = require("../../context/DashKitContext");
7
+ const utils_1 = require("../../utils");
7
8
  const GridItem_1 = tslib_1.__importDefault(require("../GridItem/GridItem"));
8
9
  const ReactGridLayout_1 = require("./ReactGridLayout");
9
10
  class GridLayout extends react_1.default.PureComponent {
@@ -34,44 +35,6 @@ class GridLayout extends react_1.default.PureComponent {
34
35
  const { getItemsMeta } = this.context;
35
36
  return getItemsMeta(this.pluginsRefs);
36
37
  };
37
- this.getMemoGroupLayout = (group, layout) => {
38
- // fastest possible way to match json
39
- const key = JSON.stringify(layout);
40
- if (this._memoGroupsLayouts[group]) {
41
- if (this._memoGroupsLayouts[group].key === key) {
42
- return this._memoGroupsLayouts[group];
43
- }
44
- else {
45
- this._memoGroupsLayouts[group].key = key;
46
- this._memoGroupsLayouts[group].layout = layout;
47
- }
48
- }
49
- else {
50
- this._memoGroupsLayouts[group] = {
51
- key,
52
- layout,
53
- };
54
- }
55
- return this._memoGroupsLayouts[group];
56
- };
57
- this.getMemoGroupCallbacks = (group) => {
58
- if (!this._memoCallbacksForGroups[group]) {
59
- const onDragStart = this._onDragStart.bind(this, group);
60
- const onStop = this._onStop.bind(this, group);
61
- const onDrop = this._onDrop.bind(this, group);
62
- const onDropDragOver = this._onDropDragOver.bind(this, group);
63
- const onDragTargetRestore = this._onTargetRestore.bind(this, group);
64
- this._memoCallbacksForGroups[group] = {
65
- onDragStart,
66
- onDragStop: onStop,
67
- onResizeStop: onStop,
68
- onDrop,
69
- onDropDragOver,
70
- onDragTargetRestore,
71
- };
72
- }
73
- return this._memoCallbacksForGroups[group];
74
- };
75
38
  this.getMemoGroupProps = (group, renderLayout, properties) => {
76
39
  // Needed for _onDropDragOver
77
40
  this._memoGroupsProps[group] = properties;
@@ -94,45 +57,6 @@ class GridLayout extends react_1.default.PureComponent {
94
57
  }
95
58
  return this._memoForwardedPluginRef[refIndex];
96
59
  };
97
- this._onDragStart = (group, _newLayout, layoutItem, _newItem, _placeholder, e) => {
98
- if (this.temporaryLayout)
99
- return;
100
- if (this.context.dragOverPlugin) {
101
- this.setState({ isDragging: true });
102
- }
103
- else {
104
- let currentDraggingElement = this.state.currentDraggingElement;
105
- if (!currentDraggingElement) {
106
- const layoutId = layoutItem.i;
107
- const item = this.context.config.items.find(({ id }) => id === layoutId);
108
- const { offsetX, offsetY } = e.nativeEvent;
109
- currentDraggingElement = {
110
- group,
111
- layoutItem,
112
- item,
113
- cursorPosition: { offsetX, offsetY },
114
- };
115
- }
116
- this.setState({
117
- isDragging: true,
118
- currentDraggingElement,
119
- draggedOverGroup: group,
120
- });
121
- }
122
- };
123
- this._onResizeStart = () => {
124
- this.setState({
125
- isDragging: true,
126
- });
127
- };
128
- this._onTargetRestore = () => {
129
- const { currentDraggingElement } = this.state;
130
- if (currentDraggingElement) {
131
- this.setState({
132
- draggedOverGroup: currentDraggingElement.group,
133
- });
134
- }
135
- };
136
60
  this._onStop = (group, newLayout) => {
137
61
  const { layoutChange, onDrop, temporaryLayout } = this.context;
138
62
  const { draggedOverGroup, currentDraggingElement } = this.state;
@@ -180,6 +104,7 @@ class GridLayout extends react_1.default.PureComponent {
180
104
  currentDraggingElement: null,
181
105
  draggedOverGroup: null,
182
106
  });
107
+ // TODO temporaryLayout
183
108
  layoutChange(groupedLayout);
184
109
  };
185
110
  this._onExternalDrop = (group, newLayout, item, e) => {
@@ -204,8 +129,12 @@ class GridLayout extends react_1.default.PureComponent {
204
129
  }
205
130
  };
206
131
  this._onDropDragOver = (group, e) => {
207
- const { editMode, dragOverPlugin, onDropDragOver } = this.context;
132
+ const { editMode, dragOverPlugin, onDropDragOver, temporaryLayout } = this.context;
208
133
  const { currentDraggingElement } = this.state;
134
+ // TODO If temporary item is trying to change group
135
+ if (temporaryLayout && currentDraggingElement) {
136
+ return false;
137
+ }
209
138
  if (!editMode || (!dragOverPlugin && !currentDraggingElement)) {
210
139
  return false;
211
140
  }
@@ -248,6 +177,51 @@ class GridLayout extends react_1.default.PureComponent {
248
177
  const { layout, temporaryLayout } = this.context;
249
178
  return (temporaryLayout === null || temporaryLayout === void 0 ? void 0 : temporaryLayout.data) || layout;
250
179
  }
180
+ getMemoGroupLayout(group, layout) {
181
+ // fastest possible way to match json
182
+ const key = JSON.stringify(layout);
183
+ if (this._memoGroupsLayouts[group]) {
184
+ if (this._memoGroupsLayouts[group].key === key) {
185
+ return this._memoGroupsLayouts[group];
186
+ }
187
+ else {
188
+ this._memoGroupsLayouts[group].key = key;
189
+ this._memoGroupsLayouts[group].layout = layout;
190
+ }
191
+ }
192
+ else {
193
+ this._memoGroupsLayouts[group] = {
194
+ key,
195
+ layout,
196
+ };
197
+ }
198
+ return this._memoGroupsLayouts[group];
199
+ }
200
+ getMemoGroupCallbacks(group) {
201
+ if (!this._memoCallbacksForGroups[group]) {
202
+ const onDragStart = this._onDragStart.bind(this, group);
203
+ const onDrag = this._onDrag.bind(this, group);
204
+ const onDragStop = this._onDragStop.bind(this, group);
205
+ const onResizeStart = this._onResizeStart.bind(this, group);
206
+ const onResize = this._onResize.bind(this, group);
207
+ const onResizeStop = this._onResizeStop.bind(this, group);
208
+ const onDrop = this._onDrop.bind(this, group);
209
+ const onDropDragOver = this._onDropDragOver.bind(this, group);
210
+ const onDragTargetRestore = this._onTargetRestore.bind(this, group);
211
+ this._memoCallbacksForGroups[group] = {
212
+ onDragStart,
213
+ onDrag,
214
+ onDragStop,
215
+ onResizeStart,
216
+ onResize,
217
+ onResizeStop,
218
+ onDrop,
219
+ onDropDragOver,
220
+ onDragTargetRestore,
221
+ };
222
+ }
223
+ return this._memoCallbacksForGroups[group];
224
+ }
251
225
  mergeGroupsLayout(group, newLayout, temporaryItem) {
252
226
  const renderLayout = this.getActiveLayout();
253
227
  const itemsByGroup = renderLayout.reduce((memo, item) => {
@@ -263,7 +237,7 @@ class GridLayout extends react_1.default.PureComponent {
263
237
  return memo;
264
238
  }, {});
265
239
  return renderLayout.map((currentItem) => {
266
- const itemParent = itemsByGroup[currentItem.i].parent || constants_1.DEFAULT_GROUP;
240
+ const itemParent = (0, utils_1.resolveLayoutGroup)(itemsByGroup[currentItem.i]);
267
241
  if (itemParent === group) {
268
242
  return newItemsLayoutById[currentItem.i];
269
243
  }
@@ -284,6 +258,81 @@ class GridLayout extends react_1.default.PureComponent {
284
258
  this._timeout = setTimeout(() => this.reloadItems(), reloadIntervalRemains <= 0 ? autoupdateIntervalMs : reloadIntervalRemains);
285
259
  }
286
260
  }
261
+ prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element) {
262
+ return {
263
+ group,
264
+ layout,
265
+ oldItem,
266
+ newItem,
267
+ placeholder,
268
+ e,
269
+ element,
270
+ };
271
+ }
272
+ updateeDraggingElementState(group, layoutItem, e) {
273
+ let currentDraggingElement = this.state.currentDraggingElement;
274
+ if (!currentDraggingElement) {
275
+ const { temporaryLayout } = this.context;
276
+ const layoutId = layoutItem.i;
277
+ const item = temporaryLayout
278
+ ? temporaryLayout.dragProps
279
+ : this.context.config.items.find(({ id }) => id === layoutId);
280
+ const { offsetX, offsetY } = e.nativeEvent;
281
+ currentDraggingElement = {
282
+ group,
283
+ layoutItem,
284
+ item,
285
+ cursorPosition: { offsetX, offsetY },
286
+ };
287
+ }
288
+ this.setState({ currentDraggingElement, draggedOverGroup: group });
289
+ }
290
+ _onDragStart(group, _newLayout, layoutItem, _newItem, _placeholder, e, element) {
291
+ var _a;
292
+ (_a = this.context.onDragStart) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, _newLayout, layoutItem, _newItem, _placeholder, e, element));
293
+ if (this.context.dragOverPlugin) {
294
+ this.setState({ isDragging: true });
295
+ }
296
+ else {
297
+ this.updateeDraggingElementState(group, layoutItem, e);
298
+ this.setState({ isDragging: true });
299
+ }
300
+ }
301
+ _onDrag(group, layout, oldItem, newItem, placeholder, e, element) {
302
+ var _a;
303
+ (_a = this.context.onDrag) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
304
+ }
305
+ _onDragStop(group, layout, oldItem, newItem, placeholder, e, element) {
306
+ var _a;
307
+ this._onStop(group, layout);
308
+ (_a = this.context.onDragStop) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
309
+ }
310
+ _onResizeStart(group, layout, oldItem, newItem, placeholder, e, element) {
311
+ var _a;
312
+ this.setState({
313
+ isDragging: true,
314
+ });
315
+ (_a = this.context.onResizeStart) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
316
+ }
317
+ _onResize(group, layout, oldItem, newItem, placeholder, e, element) {
318
+ var _a;
319
+ (_a = this.context.onResize) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
320
+ }
321
+ _onResizeStop(group, layout, oldItem, newItem, placeholder, e, element) {
322
+ var _a;
323
+ (_a = this.context.onResizeStop) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
324
+ }
325
+ _onTargetRestore() {
326
+ if (this.context.temporaryLayout) {
327
+ return;
328
+ }
329
+ const { currentDraggingElement } = this.state;
330
+ if (currentDraggingElement) {
331
+ this.setState({
332
+ draggedOverGroup: currentDraggingElement.group,
333
+ });
334
+ }
335
+ }
287
336
  renderTemporaryPlaceholder() {
288
337
  const { temporaryLayout, noOverlay, draggableHandleClassName } = this.context;
289
338
  if (!temporaryLayout || !temporaryLayout.dragProps) {
@@ -309,13 +358,21 @@ class GridLayout extends react_1.default.PureComponent {
309
358
  group === currentDraggingElement.group &&
310
359
  draggedOverGroup !== null &&
311
360
  draggedOverGroup !== group;
312
- 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, onDragTargetRestore: callbacks.onDragTargetRestore, onDropDragOver: callbacks.onDropDragOver, onDrop: callbacks.onDrop, hasSharedDragItem: hasSharedDragItem, sharedDragPosition: currentDraggingElement === null || currentDraggingElement === void 0 ? void 0 : currentDraggingElement.cursorPosition, isDragCaptured: isDragCaptured }, (draggableHandleClassName
361
+ return (react_1.default.createElement(ReactGridLayout_1.Layout
362
+ // Group properties
363
+ , Object.assign({}, properties, {
364
+ // Layout props
365
+ compactType: compactType, layout: layout, key: `group_${group}`, isDraggable: editMode, isResizable: editMode, draggableCancel: `.${constants_1.DRAGGABLE_CANCEL_CLASS_NAME}` }, (draggableHandleClassName
313
366
  ? { draggableHandle: `.${draggableHandleClassName}` }
314
- : null), (outerDnDEnable
367
+ : null), {
368
+ // Default callbacks
369
+ onDragStart: callbacks.onDragStart, onDrag: callbacks.onDrag, onDragStop: callbacks.onDragStop, onResizeStart: callbacks.onResizeStart, onResize: callbacks.onResize, onResizeStop: callbacks.onResizeStop,
370
+ // External Drag N Drop options
371
+ onDragTargetRestore: callbacks.onDragTargetRestore, onDropDragOver: callbacks.onDropDragOver, onDrop: callbacks.onDrop, hasSharedDragItem: hasSharedDragItem, sharedDragPosition: currentDraggingElement === null || currentDraggingElement === void 0 ? void 0 : currentDraggingElement.cursorPosition, isDragCaptured: isDragCaptured }, (outerDnDEnable
315
372
  ? {
316
373
  isDroppable: true,
317
374
  }
318
- : null), { draggableCancel: `.${constants_1.OVERLAY_CONTROLS_CLASS_NAME}` }),
375
+ : null)),
319
376
  renderItems.map((item, i) => {
320
377
  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 }));
321
378
  }),
@@ -105,7 +105,7 @@ class OverlayControls extends react_1.default.Component {
105
105
  const controls = hasCustomControlsWithWidgets
106
106
  ? this.getCustomControlsWithWidgets()
107
107
  : this.renderControls();
108
- return react_1.default.createElement("div", { className: b({ position }) }, controls);
108
+ return react_1.default.createElement("div", { className: b({ position }, [constants_1.DRAGGABLE_CANCEL_CLASS_NAME]) }, controls);
109
109
  }
110
110
  getDropDownMenuItemConfig(menuName, isDefaultMenu) {
111
111
  switch (menuName) {
@@ -203,7 +203,9 @@ class OverlayControls extends react_1.default.Component {
203
203
  return null;
204
204
  }
205
205
  return (react_1.default.createElement(uikit_1.DropdownMenu, { items: items, renderSwitcher: (props) => (react_1.default.createElement(uikit_1.Button, Object.assign({}, props, { view: view, size: size, pin: isOnlyOneItem ? 'round-round' : 'brick-round', qa: "dashkit-overlay-control-menu" }),
206
- react_1.default.createElement(uikit_1.Icon, { data: icons_1.Ellipsis, size: constants_1.OVERLAY_ICON_SIZE }))) }));
206
+ react_1.default.createElement(uikit_1.Icon, { data: icons_1.Ellipsis, size: constants_1.OVERLAY_ICON_SIZE }))), popupProps: {
207
+ contentClassName: constants_1.DRAGGABLE_CANCEL_CLASS_NAME,
208
+ } }));
207
209
  }
208
210
  getControlItemPinStyle(index, itemsLength) {
209
211
  const isOnlyOneItem = itemsLength === 1;
@@ -13,3 +13,4 @@ export declare const DEFAULT_WIDGET_HEIGHT = 3;
13
13
  export declare const DEFAULT_WIDGET_WIDTH = 3;
14
14
  export declare const DEFAULT_GROUP = "__default";
15
15
  export declare const COMPACT_TYPE_HORIZONTAL_NOWRAP = "horizontal-nowrap";
16
+ export declare const DRAGGABLE_CANCEL_CLASS_NAME = "dashkit_draggable_cancel";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.COMPACT_TYPE_HORIZONTAL_NOWRAP = exports.DEFAULT_GROUP = exports.DEFAULT_WIDGET_WIDTH = exports.DEFAULT_WIDGET_HEIGHT = exports.MenuItems = exports.TEMPORARY_ITEM_ID = exports.OVERLAY_ICON_SIZE = exports.OVERLAY_CLASS_NAME = exports.OVERLAY_CONTROLS_CLASS_NAME = exports.DEFAULT_NAMESPACE = exports.COPIED_WIDGET_STORE_KEY = void 0;
3
+ exports.DRAGGABLE_CANCEL_CLASS_NAME = exports.COMPACT_TYPE_HORIZONTAL_NOWRAP = exports.DEFAULT_GROUP = exports.DEFAULT_WIDGET_WIDTH = exports.DEFAULT_WIDGET_HEIGHT = exports.MenuItems = exports.TEMPORARY_ITEM_ID = exports.OVERLAY_ICON_SIZE = exports.OVERLAY_CLASS_NAME = exports.OVERLAY_CONTROLS_CLASS_NAME = exports.DEFAULT_NAMESPACE = exports.COPIED_WIDGET_STORE_KEY = void 0;
4
4
  exports.COPIED_WIDGET_STORE_KEY = 'dashCopiedItem';
5
5
  exports.DEFAULT_NAMESPACE = 'default';
6
6
  exports.OVERLAY_CONTROLS_CLASS_NAME = 'dashkit-overlay-controls';
@@ -16,3 +16,4 @@ exports.DEFAULT_WIDGET_HEIGHT = 3;
16
16
  exports.DEFAULT_WIDGET_WIDTH = 3;
17
17
  exports.DEFAULT_GROUP = '__default';
18
18
  exports.COMPACT_TYPE_HORIZONTAL_NOWRAP = 'horizontal-nowrap';
19
+ exports.DRAGGABLE_CANCEL_CLASS_NAME = 'dashkit_draggable_cancel';
@@ -154,7 +154,7 @@ function useMemoStateContext(props) {
154
154
  if (hasNowrapGroups) {
155
155
  layout.forEach((item) => {
156
156
  const widgetId = item.i;
157
- const parentId = item.parent || common_1.DEFAULT_GROUP;
157
+ const parentId = (0, utils_1.resolveLayoutGroup)(item);
158
158
  if (nowrapGroups[parentId]) {
159
159
  // Collecting nowrap elements
160
160
  nowrapGroups[parentId].items.push(item);
@@ -287,7 +287,7 @@ function useMemoStateContext(props) {
287
287
  return;
288
288
  }
289
289
  setTemporaryLayout({
290
- data: newLayout,
290
+ data: [...newLayout, item],
291
291
  dragProps,
292
292
  });
293
293
  onDropProp({
@@ -331,6 +331,13 @@ function useMemoStateContext(props) {
331
331
  draggableHandleClassName: props.draggableHandleClassName,
332
332
  outerDnDEnable,
333
333
  dragOverPlugin,
334
+ /* default bypassing handlers */
335
+ onDragStart: props.onDragStart,
336
+ onDrag: props.onDrag,
337
+ onDragStop: props.onDragStop,
338
+ onResizeStart: props.onResizeStart,
339
+ onResize: props.onResize,
340
+ onResizeStop: props.onResizeStop,
334
341
  }), [
335
342
  resultLayout,
336
343
  temporaryLayout,
@@ -359,6 +366,12 @@ function useMemoStateContext(props) {
359
366
  props.draggableHandleClassName,
360
367
  outerDnDEnable,
361
368
  dragOverPlugin,
369
+ props.onDragStart,
370
+ props.onDrag,
371
+ props.onDragStop,
372
+ props.onResizeStart,
373
+ props.onResize,
374
+ props.onResizeStop,
362
375
  ]);
363
376
  const overlayMenuItems = props.overlayMenuItems || props.registerManager.settings.menu;
364
377
  const controlsContextValue = react_1.default.useMemo(() => ({
@@ -1,5 +1,5 @@
1
- /// <reference types="react-grid-layout" />
2
1
  /// <reference types="react" />
2
+ import type { Layout, Layouts } from 'react-grid-layout';
3
3
  import type { Config, ConfigItem, ConfigLayout } from '../shared';
4
4
  export interface AddConfigItem extends Omit<ConfigItem, 'id' | 'namespace'> {
5
5
  id?: null;
@@ -38,3 +38,11 @@ export interface DashKitGroup {
38
38
  render?: (id: string, children: React.ReactNode, props: DashkitGroupRenderProps) => React.ReactNode;
39
39
  gridProperties?: (props: ReactGridLayoutProps) => ReactGridLayoutProps;
40
40
  }
41
+ export type ItemManipulationCallback = (eventData: {
42
+ layout: Layouts;
43
+ oldItem: Layout;
44
+ newItem: Layout;
45
+ placeholder: Layout;
46
+ e: MouseEvent;
47
+ element: HTMLElement;
48
+ }) => void;
@@ -0,0 +1,3 @@
1
+ import type { ConfigLayout } from '../shared/types';
2
+ export declare const resolveLayoutGroup: (item: ConfigLayout) => string;
3
+ export declare const isDefaultLayoutGroup: (item: ConfigLayout) => boolean;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isDefaultLayoutGroup = exports.resolveLayoutGroup = void 0;
4
+ const constants_1 = require("../constants");
5
+ const resolveLayoutGroup = (item) => {
6
+ if (!item.parent) {
7
+ return constants_1.DEFAULT_GROUP;
8
+ }
9
+ return item.parent;
10
+ };
11
+ exports.resolveLayoutGroup = resolveLayoutGroup;
12
+ const isDefaultLayoutGroup = (item) => {
13
+ return item.parent === constants_1.DEFAULT_GROUP || item.parent === undefined;
14
+ };
15
+ exports.isDefaultLayoutGroup = isDefaultLayoutGroup;
@@ -1,2 +1,3 @@
1
1
  export * from './register-manager';
2
2
  export * from './update-manager';
3
+ export * from './group-helpers';
@@ -3,3 +3,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./register-manager"), exports);
5
5
  tslib_1.__exportStar(require("./update-manager"), exports);
6
+ tslib_1.__exportStar(require("./group-helpers"), exports);
@@ -9,6 +9,7 @@ const constants_1 = require("../constants");
9
9
  const shared_1 = require("../shared");
10
10
  const get_new_id_1 = require("./get-new-id");
11
11
  const grid_layout_1 = require("./grid-layout");
12
+ const group_helpers_1 = require("./group-helpers");
12
13
  (0, immutability_helper_1.extend)('$auto', (value, object) => (object ? (0, immutability_helper_1.default)(object, value) : (0, immutability_helper_1.default)({}, value)));
13
14
  function removeItemVersion1({ id, config, itemsStateAndParams }) {
14
15
  const itemIndex = config.items.findIndex((item) => item.id === id);
@@ -231,7 +232,7 @@ function reflowLayout({ newLayoutItem, layout, reflowLayoutOptions, }) {
231
232
  const byGroup = {};
232
233
  const reducer = (memo, item, i, _items, isNewItem) => {
233
234
  memo[item.i] = i;
234
- const parent = item.parent || constants_1.DEFAULT_GROUP;
235
+ const parent = (0, group_helpers_1.resolveLayoutGroup)(item);
235
236
  if (byGroup[parent]) {
236
237
  if (isNewItem) {
237
238
  byGroup[parent].unshift(item);
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { Config, ConfigItem, ConfigLayout, GlobalParams, ItemDropProps, ItemsStateAndParams } from '../../shared';
3
- import { AddNewItemOptions, ContextProps, DashKitGroup, MenuItem, Plugin, SetConfigItem, Settings, SettingsProps } from '../../typings';
3
+ import { AddNewItemOptions, ContextProps, DashKitGroup, ItemManipulationCallback, MenuItem, Plugin, SetConfigItem, Settings, SettingsProps } from '../../typings';
4
4
  import GridLayout from '../GridLayout/GridLayout';
5
5
  import { OverlayControlItem } from '../OverlayControls/OverlayControls';
6
6
  interface DashKitGeneralProps {
@@ -17,12 +17,18 @@ interface DashKitDefaultProps {
17
17
  itemsStateAndParams: ItemsStateAndParams;
18
18
  groups?: DashKitGroup[];
19
19
  }) => void;
20
- onDrop: (dropProps: ItemDropProps) => void;
20
+ onDrop?: (dropProps: ItemDropProps) => void;
21
21
  onItemMountChange?: (item: ConfigItem, state: {
22
22
  isAsync: boolean;
23
23
  isMounted: boolean;
24
24
  }) => void;
25
25
  onItemRender?: (item: ConfigItem) => void;
26
+ onDragStart?: ItemManipulationCallback;
27
+ onDrag?: ItemManipulationCallback;
28
+ onDragStop?: ItemManipulationCallback;
29
+ onResizeStart?: ItemManipulationCallback;
30
+ onResize?: ItemManipulationCallback;
31
+ onResizeStop?: ItemManipulationCallback;
26
32
  defaultGlobalParams: GlobalParams;
27
33
  globalParams: GlobalParams;
28
34
  itemsStateAndParams: ItemsStateAndParams;
@@ -25,8 +25,8 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
25
25
  }) => void;
26
26
  getItemsMeta: () => any;
27
27
  getActiveLayout(): any;
28
- getMemoGroupLayout: (group: any, layout: any) => any;
29
- getMemoGroupCallbacks: (group: any) => any;
28
+ getMemoGroupLayout(group: any, layout: any): any;
29
+ getMemoGroupCallbacks(group: any): any;
30
30
  getMemoGroupProps: (group: any, renderLayout: any, properties: any) => {
31
31
  layout: any;
32
32
  callbacks: any;
@@ -38,9 +38,23 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
38
38
  getMemoForwardRefCallback: (refIndex: any) => any;
39
39
  mergeGroupsLayout(group: any, newLayout: any, temporaryItem: any): any;
40
40
  reloadItems(): void;
41
- _onDragStart: (group: any, _newLayout: any, layoutItem: any, _newItem: any, _placeholder: any, e: any) => void;
42
- _onResizeStart: () => void;
43
- _onTargetRestore: () => void;
41
+ prepareDefaultArguments(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): {
42
+ group: any;
43
+ layout: any;
44
+ oldItem: any;
45
+ newItem: any;
46
+ placeholder: any;
47
+ e: any;
48
+ element: any;
49
+ };
50
+ updateeDraggingElementState(group: any, layoutItem: any, e: any): void;
51
+ _onDragStart(group: any, _newLayout: any, layoutItem: any, _newItem: any, _placeholder: any, e: any, element: any): void;
52
+ _onDrag(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
53
+ _onDragStop(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
54
+ _onResizeStart(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
55
+ _onResize(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
56
+ _onResizeStop(group: any, layout: any, oldItem: any, newItem: any, placeholder: any, e: any, element: any): void;
57
+ _onTargetRestore(): void;
44
58
  _onStop: (group: any, newLayout: any) => void;
45
59
  _onSharedDrop: (targetGroup: any, newLayout: any, tempItem: any) => void;
46
60
  _onExternalDrop: (group: any, newLayout: any, item: any, e: any) => void;
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
- import { COMPACT_TYPE_HORIZONTAL_NOWRAP, DEFAULT_GROUP, OVERLAY_CONTROLS_CLASS_NAME, TEMPORARY_ITEM_ID, } from '../../constants';
2
+ import { COMPACT_TYPE_HORIZONTAL_NOWRAP, DEFAULT_GROUP, DRAGGABLE_CANCEL_CLASS_NAME, TEMPORARY_ITEM_ID, } from '../../constants';
3
3
  import { DashKitContext } from '../../context/DashKitContext';
4
+ import { resolveLayoutGroup } from '../../utils';
4
5
  import GridItem from '../GridItem/GridItem';
5
6
  import { Layout } from './ReactGridLayout';
6
7
  class GridLayout extends React.PureComponent {
@@ -31,44 +32,6 @@ class GridLayout extends React.PureComponent {
31
32
  const { getItemsMeta } = this.context;
32
33
  return getItemsMeta(this.pluginsRefs);
33
34
  };
34
- this.getMemoGroupLayout = (group, layout) => {
35
- // fastest possible way to match json
36
- const key = JSON.stringify(layout);
37
- if (this._memoGroupsLayouts[group]) {
38
- if (this._memoGroupsLayouts[group].key === key) {
39
- return this._memoGroupsLayouts[group];
40
- }
41
- else {
42
- this._memoGroupsLayouts[group].key = key;
43
- this._memoGroupsLayouts[group].layout = layout;
44
- }
45
- }
46
- else {
47
- this._memoGroupsLayouts[group] = {
48
- key,
49
- layout,
50
- };
51
- }
52
- return this._memoGroupsLayouts[group];
53
- };
54
- this.getMemoGroupCallbacks = (group) => {
55
- if (!this._memoCallbacksForGroups[group]) {
56
- const onDragStart = this._onDragStart.bind(this, group);
57
- const onStop = this._onStop.bind(this, group);
58
- const onDrop = this._onDrop.bind(this, group);
59
- const onDropDragOver = this._onDropDragOver.bind(this, group);
60
- const onDragTargetRestore = this._onTargetRestore.bind(this, group);
61
- this._memoCallbacksForGroups[group] = {
62
- onDragStart,
63
- onDragStop: onStop,
64
- onResizeStop: onStop,
65
- onDrop,
66
- onDropDragOver,
67
- onDragTargetRestore,
68
- };
69
- }
70
- return this._memoCallbacksForGroups[group];
71
- };
72
35
  this.getMemoGroupProps = (group, renderLayout, properties) => {
73
36
  // Needed for _onDropDragOver
74
37
  this._memoGroupsProps[group] = properties;
@@ -91,45 +54,6 @@ class GridLayout extends React.PureComponent {
91
54
  }
92
55
  return this._memoForwardedPluginRef[refIndex];
93
56
  };
94
- this._onDragStart = (group, _newLayout, layoutItem, _newItem, _placeholder, e) => {
95
- if (this.temporaryLayout)
96
- return;
97
- if (this.context.dragOverPlugin) {
98
- this.setState({ isDragging: true });
99
- }
100
- else {
101
- let currentDraggingElement = this.state.currentDraggingElement;
102
- if (!currentDraggingElement) {
103
- const layoutId = layoutItem.i;
104
- const item = this.context.config.items.find(({ id }) => id === layoutId);
105
- const { offsetX, offsetY } = e.nativeEvent;
106
- currentDraggingElement = {
107
- group,
108
- layoutItem,
109
- item,
110
- cursorPosition: { offsetX, offsetY },
111
- };
112
- }
113
- this.setState({
114
- isDragging: true,
115
- currentDraggingElement,
116
- draggedOverGroup: group,
117
- });
118
- }
119
- };
120
- this._onResizeStart = () => {
121
- this.setState({
122
- isDragging: true,
123
- });
124
- };
125
- this._onTargetRestore = () => {
126
- const { currentDraggingElement } = this.state;
127
- if (currentDraggingElement) {
128
- this.setState({
129
- draggedOverGroup: currentDraggingElement.group,
130
- });
131
- }
132
- };
133
57
  this._onStop = (group, newLayout) => {
134
58
  const { layoutChange, onDrop, temporaryLayout } = this.context;
135
59
  const { draggedOverGroup, currentDraggingElement } = this.state;
@@ -177,6 +101,7 @@ class GridLayout extends React.PureComponent {
177
101
  currentDraggingElement: null,
178
102
  draggedOverGroup: null,
179
103
  });
104
+ // TODO temporaryLayout
180
105
  layoutChange(groupedLayout);
181
106
  };
182
107
  this._onExternalDrop = (group, newLayout, item, e) => {
@@ -201,8 +126,12 @@ class GridLayout extends React.PureComponent {
201
126
  }
202
127
  };
203
128
  this._onDropDragOver = (group, e) => {
204
- const { editMode, dragOverPlugin, onDropDragOver } = this.context;
129
+ const { editMode, dragOverPlugin, onDropDragOver, temporaryLayout } = this.context;
205
130
  const { currentDraggingElement } = this.state;
131
+ // TODO If temporary item is trying to change group
132
+ if (temporaryLayout && currentDraggingElement) {
133
+ return false;
134
+ }
206
135
  if (!editMode || (!dragOverPlugin && !currentDraggingElement)) {
207
136
  return false;
208
137
  }
@@ -245,6 +174,51 @@ class GridLayout extends React.PureComponent {
245
174
  const { layout, temporaryLayout } = this.context;
246
175
  return (temporaryLayout === null || temporaryLayout === void 0 ? void 0 : temporaryLayout.data) || layout;
247
176
  }
177
+ getMemoGroupLayout(group, layout) {
178
+ // fastest possible way to match json
179
+ const key = JSON.stringify(layout);
180
+ if (this._memoGroupsLayouts[group]) {
181
+ if (this._memoGroupsLayouts[group].key === key) {
182
+ return this._memoGroupsLayouts[group];
183
+ }
184
+ else {
185
+ this._memoGroupsLayouts[group].key = key;
186
+ this._memoGroupsLayouts[group].layout = layout;
187
+ }
188
+ }
189
+ else {
190
+ this._memoGroupsLayouts[group] = {
191
+ key,
192
+ layout,
193
+ };
194
+ }
195
+ return this._memoGroupsLayouts[group];
196
+ }
197
+ getMemoGroupCallbacks(group) {
198
+ if (!this._memoCallbacksForGroups[group]) {
199
+ const onDragStart = this._onDragStart.bind(this, group);
200
+ const onDrag = this._onDrag.bind(this, group);
201
+ const onDragStop = this._onDragStop.bind(this, group);
202
+ const onResizeStart = this._onResizeStart.bind(this, group);
203
+ const onResize = this._onResize.bind(this, group);
204
+ const onResizeStop = this._onResizeStop.bind(this, group);
205
+ const onDrop = this._onDrop.bind(this, group);
206
+ const onDropDragOver = this._onDropDragOver.bind(this, group);
207
+ const onDragTargetRestore = this._onTargetRestore.bind(this, group);
208
+ this._memoCallbacksForGroups[group] = {
209
+ onDragStart,
210
+ onDrag,
211
+ onDragStop,
212
+ onResizeStart,
213
+ onResize,
214
+ onResizeStop,
215
+ onDrop,
216
+ onDropDragOver,
217
+ onDragTargetRestore,
218
+ };
219
+ }
220
+ return this._memoCallbacksForGroups[group];
221
+ }
248
222
  mergeGroupsLayout(group, newLayout, temporaryItem) {
249
223
  const renderLayout = this.getActiveLayout();
250
224
  const itemsByGroup = renderLayout.reduce((memo, item) => {
@@ -260,7 +234,7 @@ class GridLayout extends React.PureComponent {
260
234
  return memo;
261
235
  }, {});
262
236
  return renderLayout.map((currentItem) => {
263
- const itemParent = itemsByGroup[currentItem.i].parent || DEFAULT_GROUP;
237
+ const itemParent = resolveLayoutGroup(itemsByGroup[currentItem.i]);
264
238
  if (itemParent === group) {
265
239
  return newItemsLayoutById[currentItem.i];
266
240
  }
@@ -281,6 +255,81 @@ class GridLayout extends React.PureComponent {
281
255
  this._timeout = setTimeout(() => this.reloadItems(), reloadIntervalRemains <= 0 ? autoupdateIntervalMs : reloadIntervalRemains);
282
256
  }
283
257
  }
258
+ prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element) {
259
+ return {
260
+ group,
261
+ layout,
262
+ oldItem,
263
+ newItem,
264
+ placeholder,
265
+ e,
266
+ element,
267
+ };
268
+ }
269
+ updateeDraggingElementState(group, layoutItem, e) {
270
+ let currentDraggingElement = this.state.currentDraggingElement;
271
+ if (!currentDraggingElement) {
272
+ const { temporaryLayout } = this.context;
273
+ const layoutId = layoutItem.i;
274
+ const item = temporaryLayout
275
+ ? temporaryLayout.dragProps
276
+ : this.context.config.items.find(({ id }) => id === layoutId);
277
+ const { offsetX, offsetY } = e.nativeEvent;
278
+ currentDraggingElement = {
279
+ group,
280
+ layoutItem,
281
+ item,
282
+ cursorPosition: { offsetX, offsetY },
283
+ };
284
+ }
285
+ this.setState({ currentDraggingElement, draggedOverGroup: group });
286
+ }
287
+ _onDragStart(group, _newLayout, layoutItem, _newItem, _placeholder, e, element) {
288
+ var _a;
289
+ (_a = this.context.onDragStart) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, _newLayout, layoutItem, _newItem, _placeholder, e, element));
290
+ if (this.context.dragOverPlugin) {
291
+ this.setState({ isDragging: true });
292
+ }
293
+ else {
294
+ this.updateeDraggingElementState(group, layoutItem, e);
295
+ this.setState({ isDragging: true });
296
+ }
297
+ }
298
+ _onDrag(group, layout, oldItem, newItem, placeholder, e, element) {
299
+ var _a;
300
+ (_a = this.context.onDrag) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
301
+ }
302
+ _onDragStop(group, layout, oldItem, newItem, placeholder, e, element) {
303
+ var _a;
304
+ this._onStop(group, layout);
305
+ (_a = this.context.onDragStop) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
306
+ }
307
+ _onResizeStart(group, layout, oldItem, newItem, placeholder, e, element) {
308
+ var _a;
309
+ this.setState({
310
+ isDragging: true,
311
+ });
312
+ (_a = this.context.onResizeStart) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
313
+ }
314
+ _onResize(group, layout, oldItem, newItem, placeholder, e, element) {
315
+ var _a;
316
+ (_a = this.context.onResize) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
317
+ }
318
+ _onResizeStop(group, layout, oldItem, newItem, placeholder, e, element) {
319
+ var _a;
320
+ (_a = this.context.onResizeStop) === null || _a === void 0 ? void 0 : _a.call(this, this.prepareDefaultArguments(group, layout, oldItem, newItem, placeholder, e, element));
321
+ }
322
+ _onTargetRestore() {
323
+ if (this.context.temporaryLayout) {
324
+ return;
325
+ }
326
+ const { currentDraggingElement } = this.state;
327
+ if (currentDraggingElement) {
328
+ this.setState({
329
+ draggedOverGroup: currentDraggingElement.group,
330
+ });
331
+ }
332
+ }
284
333
  renderTemporaryPlaceholder() {
285
334
  const { temporaryLayout, noOverlay, draggableHandleClassName } = this.context;
286
335
  if (!temporaryLayout || !temporaryLayout.dragProps) {
@@ -306,13 +355,21 @@ class GridLayout extends React.PureComponent {
306
355
  group === currentDraggingElement.group &&
307
356
  draggedOverGroup !== null &&
308
357
  draggedOverGroup !== group;
309
- 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, onDragTargetRestore: callbacks.onDragTargetRestore, onDropDragOver: callbacks.onDropDragOver, onDrop: callbacks.onDrop, hasSharedDragItem: hasSharedDragItem, sharedDragPosition: currentDraggingElement === null || currentDraggingElement === void 0 ? void 0 : currentDraggingElement.cursorPosition, isDragCaptured: isDragCaptured }, (draggableHandleClassName
358
+ return (React.createElement(Layout
359
+ // Group properties
360
+ , Object.assign({}, properties, {
361
+ // Layout props
362
+ compactType: compactType, layout: layout, key: `group_${group}`, isDraggable: editMode, isResizable: editMode, draggableCancel: `.${DRAGGABLE_CANCEL_CLASS_NAME}` }, (draggableHandleClassName
310
363
  ? { draggableHandle: `.${draggableHandleClassName}` }
311
- : null), (outerDnDEnable
364
+ : null), {
365
+ // Default callbacks
366
+ onDragStart: callbacks.onDragStart, onDrag: callbacks.onDrag, onDragStop: callbacks.onDragStop, onResizeStart: callbacks.onResizeStart, onResize: callbacks.onResize, onResizeStop: callbacks.onResizeStop,
367
+ // External Drag N Drop options
368
+ onDragTargetRestore: callbacks.onDragTargetRestore, onDropDragOver: callbacks.onDropDragOver, onDrop: callbacks.onDrop, hasSharedDragItem: hasSharedDragItem, sharedDragPosition: currentDraggingElement === null || currentDraggingElement === void 0 ? void 0 : currentDraggingElement.cursorPosition, isDragCaptured: isDragCaptured }, (outerDnDEnable
312
369
  ? {
313
370
  isDroppable: true,
314
371
  }
315
- : null), { draggableCancel: `.${OVERLAY_CONTROLS_CLASS_NAME}` }),
372
+ : null)),
316
373
  renderItems.map((item, i) => {
317
374
  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 }));
318
375
  }),
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { Ellipsis, Gear, Xmark } from '@gravity-ui/icons';
3
3
  import { Button, DropdownMenu, Icon, } from '@gravity-ui/uikit';
4
4
  import noop from 'lodash/noop';
5
- import { COPIED_WIDGET_STORE_KEY, MenuItems, OVERLAY_CONTROLS_CLASS_NAME, OVERLAY_ICON_SIZE, } from '../../constants';
5
+ import { COPIED_WIDGET_STORE_KEY, DRAGGABLE_CANCEL_CLASS_NAME, MenuItems, OVERLAY_CONTROLS_CLASS_NAME, OVERLAY_ICON_SIZE, } from '../../constants';
6
6
  import { DashkitOvelayControlsContext } from '../../context/DashKitContext';
7
7
  import { i18n } from '../../i18n';
8
8
  import { cn } from '../../utils/cn';
@@ -102,7 +102,7 @@ class OverlayControls extends React.Component {
102
102
  const controls = hasCustomControlsWithWidgets
103
103
  ? this.getCustomControlsWithWidgets()
104
104
  : this.renderControls();
105
- return React.createElement("div", { className: b({ position }) }, controls);
105
+ return React.createElement("div", { className: b({ position }, [DRAGGABLE_CANCEL_CLASS_NAME]) }, controls);
106
106
  }
107
107
  getDropDownMenuItemConfig(menuName, isDefaultMenu) {
108
108
  switch (menuName) {
@@ -200,7 +200,9 @@ class OverlayControls extends React.Component {
200
200
  return null;
201
201
  }
202
202
  return (React.createElement(DropdownMenu, { items: items, renderSwitcher: (props) => (React.createElement(Button, Object.assign({}, props, { view: view, size: size, pin: isOnlyOneItem ? 'round-round' : 'brick-round', qa: "dashkit-overlay-control-menu" }),
203
- React.createElement(Icon, { data: Ellipsis, size: OVERLAY_ICON_SIZE }))) }));
203
+ React.createElement(Icon, { data: Ellipsis, size: OVERLAY_ICON_SIZE }))), popupProps: {
204
+ contentClassName: DRAGGABLE_CANCEL_CLASS_NAME,
205
+ } }));
204
206
  }
205
207
  getControlItemPinStyle(index, itemsLength) {
206
208
  const isOnlyOneItem = itemsLength === 1;
@@ -13,3 +13,4 @@ export declare const DEFAULT_WIDGET_HEIGHT = 3;
13
13
  export declare const DEFAULT_WIDGET_WIDTH = 3;
14
14
  export declare const DEFAULT_GROUP = "__default";
15
15
  export declare const COMPACT_TYPE_HORIZONTAL_NOWRAP = "horizontal-nowrap";
16
+ export declare const DRAGGABLE_CANCEL_CLASS_NAME = "dashkit_draggable_cancel";
@@ -13,3 +13,4 @@ export const DEFAULT_WIDGET_HEIGHT = 3;
13
13
  export const DEFAULT_WIDGET_WIDTH = 3;
14
14
  export const DEFAULT_GROUP = '__default';
15
15
  export const COMPACT_TYPE_HORIZONTAL_NOWRAP = 'horizontal-nowrap';
16
+ export const DRAGGABLE_CANCEL_CLASS_NAME = 'dashkit_draggable_cancel';
@@ -6,7 +6,7 @@ import { COMPACT_TYPE_HORIZONTAL_NOWRAP, DEFAULT_GROUP, DEFAULT_WIDGET_HEIGHT, D
6
6
  import { DashKitContext, DashKitDnDContext, DashkitOvelayControlsContext, } from '../context/DashKitContext';
7
7
  import { useDeepEqualMemo } from '../hooks/useDeepEqualMemo';
8
8
  import { getItemsParams, getItemsState } from '../shared';
9
- import { UpdateManager } from '../utils';
9
+ import { UpdateManager, resolveLayoutGroup } from '../utils';
10
10
  const ITEM_PROPS = ['i', 'h', 'w', 'x', 'y', 'parent'];
11
11
  function useMemoStateContext(props) {
12
12
  // так как мы не хотим хранить параметры виджета с активированной автовысотой в сторе и на сервере, актуальный
@@ -151,7 +151,7 @@ function useMemoStateContext(props) {
151
151
  if (hasNowrapGroups) {
152
152
  layout.forEach((item) => {
153
153
  const widgetId = item.i;
154
- const parentId = item.parent || DEFAULT_GROUP;
154
+ const parentId = resolveLayoutGroup(item);
155
155
  if (nowrapGroups[parentId]) {
156
156
  // Collecting nowrap elements
157
157
  nowrapGroups[parentId].items.push(item);
@@ -284,7 +284,7 @@ function useMemoStateContext(props) {
284
284
  return;
285
285
  }
286
286
  setTemporaryLayout({
287
- data: newLayout,
287
+ data: [...newLayout, item],
288
288
  dragProps,
289
289
  });
290
290
  onDropProp({
@@ -328,6 +328,13 @@ function useMemoStateContext(props) {
328
328
  draggableHandleClassName: props.draggableHandleClassName,
329
329
  outerDnDEnable,
330
330
  dragOverPlugin,
331
+ /* default bypassing handlers */
332
+ onDragStart: props.onDragStart,
333
+ onDrag: props.onDrag,
334
+ onDragStop: props.onDragStop,
335
+ onResizeStart: props.onResizeStart,
336
+ onResize: props.onResize,
337
+ onResizeStop: props.onResizeStop,
331
338
  }), [
332
339
  resultLayout,
333
340
  temporaryLayout,
@@ -356,6 +363,12 @@ function useMemoStateContext(props) {
356
363
  props.draggableHandleClassName,
357
364
  outerDnDEnable,
358
365
  dragOverPlugin,
366
+ props.onDragStart,
367
+ props.onDrag,
368
+ props.onDragStop,
369
+ props.onResizeStart,
370
+ props.onResize,
371
+ props.onResizeStop,
359
372
  ]);
360
373
  const overlayMenuItems = props.overlayMenuItems || props.registerManager.settings.menu;
361
374
  const controlsContextValue = React.useMemo(() => ({
@@ -1,5 +1,5 @@
1
- /// <reference types="react-grid-layout" />
2
1
  /// <reference types="react" />
2
+ import type { Layout, Layouts } from 'react-grid-layout';
3
3
  import type { Config, ConfigItem, ConfigLayout } from '../shared';
4
4
  export interface AddConfigItem extends Omit<ConfigItem, 'id' | 'namespace'> {
5
5
  id?: null;
@@ -38,3 +38,11 @@ export interface DashKitGroup {
38
38
  render?: (id: string, children: React.ReactNode, props: DashkitGroupRenderProps) => React.ReactNode;
39
39
  gridProperties?: (props: ReactGridLayoutProps) => ReactGridLayoutProps;
40
40
  }
41
+ export type ItemManipulationCallback = (eventData: {
42
+ layout: Layouts;
43
+ oldItem: Layout;
44
+ newItem: Layout;
45
+ placeholder: Layout;
46
+ e: MouseEvent;
47
+ element: HTMLElement;
48
+ }) => void;
@@ -0,0 +1,3 @@
1
+ import type { ConfigLayout } from '../shared/types';
2
+ export declare const resolveLayoutGroup: (item: ConfigLayout) => string;
3
+ export declare const isDefaultLayoutGroup: (item: ConfigLayout) => boolean;
@@ -0,0 +1,10 @@
1
+ import { DEFAULT_GROUP } from '../constants';
2
+ export const resolveLayoutGroup = (item) => {
3
+ if (!item.parent) {
4
+ return DEFAULT_GROUP;
5
+ }
6
+ return item.parent;
7
+ };
8
+ export const isDefaultLayoutGroup = (item) => {
9
+ return item.parent === DEFAULT_GROUP || item.parent === undefined;
10
+ };
@@ -1,2 +1,3 @@
1
1
  export * from './register-manager';
2
2
  export * from './update-manager';
3
+ export * from './group-helpers';
@@ -1,2 +1,3 @@
1
1
  export * from './register-manager';
2
2
  export * from './update-manager';
3
+ export * from './group-helpers';
@@ -5,6 +5,7 @@ import { DEFAULT_GROUP, DEFAULT_NAMESPACE } from '../constants';
5
5
  import { META_KEY, addGroupToQueue, addToQueue, deleteFromQueue, getCurrentVersion, getInitialItemsStateAndParamsMeta, getItemsStateAndParamsMeta, isItemWithGroup, isItemWithTabs, mergeParamsWithAliases, pickActionParamsFromParams, resolveItemInnerId, transformParamsToActionParams, } from '../shared';
6
6
  import { getNewId } from './get-new-id';
7
7
  import { bottom, compact } from './grid-layout';
8
+ import { resolveLayoutGroup } from './group-helpers';
8
9
  extend('$auto', (value, object) => (object ? update(object, value) : update({}, value)));
9
10
  function removeItemVersion1({ id, config, itemsStateAndParams }) {
10
11
  const itemIndex = config.items.findIndex((item) => item.id === id);
@@ -226,7 +227,7 @@ export function reflowLayout({ newLayoutItem, layout, reflowLayoutOptions, }) {
226
227
  const byGroup = {};
227
228
  const reducer = (memo, item, i, _items, isNewItem) => {
228
229
  memo[item.i] = i;
229
- const parent = item.parent || DEFAULT_GROUP;
230
+ const parent = resolveLayoutGroup(item);
230
231
  if (byGroup[parent]) {
231
232
  if (isNewItem) {
232
233
  byGroup[parent].unshift(item);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dashkit",
3
- "version": "8.13.0",
3
+ "version": "8.14.1",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {