@gravity-ui/dashkit 8.1.0-beta.0 → 8.1.0-beta.2

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.
Files changed (31) hide show
  1. package/build/cjs/components/ActionPanel/ActionPanel.d.ts +2 -11
  2. package/build/cjs/components/ActionPanel/ActionPanel.js +4 -4
  3. package/build/cjs/components/ActionPanel/types.d.ts +2 -0
  4. package/build/cjs/components/DashKit/DashKit.d.ts +2 -2
  5. package/build/cjs/components/DashKitDnDWrapper/DashKitDnDWrapper.js +8 -8
  6. package/build/cjs/components/GridItem/GridItem.js +5 -4
  7. package/build/cjs/components/GridLayout/GridLayout.d.ts +1 -0
  8. package/build/cjs/components/GridLayout/GridLayout.js +24 -14
  9. package/build/cjs/components/Item/Item.d.ts +1 -0
  10. package/build/cjs/components/Item/Item.js +7 -1
  11. package/build/cjs/hocs/prepareItem.d.ts +1 -0
  12. package/build/cjs/hocs/prepareItem.js +4 -2
  13. package/build/cjs/hocs/withContext.js +17 -19
  14. package/build/cjs/plugins/Text/Text.js +0 -3
  15. package/build/cjs/shared/types/config.d.ts +5 -0
  16. package/build/esm/components/ActionPanel/ActionPanel.d.ts +2 -11
  17. package/build/esm/components/ActionPanel/ActionPanel.js +4 -4
  18. package/build/esm/components/ActionPanel/types.d.ts +2 -0
  19. package/build/esm/components/DashKit/DashKit.d.ts +2 -2
  20. package/build/esm/components/DashKitDnDWrapper/DashKitDnDWrapper.js +8 -8
  21. package/build/esm/components/GridItem/GridItem.js +5 -4
  22. package/build/esm/components/GridLayout/GridLayout.d.ts +1 -0
  23. package/build/esm/components/GridLayout/GridLayout.js +24 -14
  24. package/build/esm/components/Item/Item.d.ts +1 -0
  25. package/build/esm/components/Item/Item.js +7 -1
  26. package/build/esm/hocs/prepareItem.d.ts +1 -0
  27. package/build/esm/hocs/prepareItem.js +4 -2
  28. package/build/esm/hocs/withContext.js +17 -19
  29. package/build/esm/plugins/Text/Text.js +0 -3
  30. package/build/esm/shared/types/config.d.ts +5 -0
  31. package/package.json +1 -1
@@ -1,14 +1,5 @@
1
- import React from 'react';
2
- import { ActionPanelProps } from './types';
3
- export type ActionPanelItem = {
4
- id: string;
5
- icon: React.ReactNode;
6
- title: string;
7
- onClick?: () => void;
8
- className?: string;
9
- qa?: string;
10
- pluginType?: string;
11
- };
1
+ /// <reference types="react" />
2
+ import { ActionPanelItem, ActionPanelProps } from './types';
12
3
  export declare const ActionPanelItemContainer: ({ item }: {
13
4
  item: ActionPanelItem;
14
5
  }) => JSX.Element;
@@ -10,13 +10,13 @@ const b = (0, cn_1.cn)('dashkit-action-panel');
10
10
  const ActionPanelItemContainer = ({ item }) => {
11
11
  const dragContext = react_1.default.useContext(DashKitContext_1.DashKitDnDContext);
12
12
  const onDragStart = react_1.default.useCallback((e) => {
13
- dragContext.onDragStart(e, item.pluginType);
14
- }, [dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragStart, item.pluginType]);
13
+ dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragStart(e, item.dragProps);
14
+ }, [dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragStart, item.dragProps]);
15
15
  const onDragEnd = react_1.default.useCallback((e) => {
16
- dragContext.onDragEnd(e);
16
+ dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragEnd(e);
17
17
  }, [dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragEnd]);
18
18
  let dndProps = {};
19
- if (item.pluginType) {
19
+ if (item.dragProps) {
20
20
  dndProps = {
21
21
  draggable: true,
22
22
  unselectable: 'on',
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import type { DragProps } from '../../shared';
2
3
  export type ActionPanelItem = {
3
4
  id: string;
4
5
  icon: React.ReactNode;
@@ -6,6 +7,7 @@ export type ActionPanelItem = {
6
7
  onClick?: () => void;
7
8
  className?: string;
8
9
  qa?: string;
10
+ dragProps?: DragProps;
9
11
  };
10
12
  export type ActionPanelProps = {
11
13
  items: ActionPanelItem[];
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { Config, ConfigItem, ConfigLayout, GlobalParams, ItemsStateAndParams } from '../../shared';
2
+ import type { Config, ConfigItem, ConfigLayout, DragProps, GlobalParams, ItemsStateAndParams } from '../../shared';
3
3
  import { ContextProps, Plugin, SetConfigItem, SetNewItemOptions, Settings, SettingsProps } from '../../typings';
4
4
  import GridLayout from '../GridLayout/GridLayout';
5
5
  import { OverlayControlItem } from '../OverlayControls/OverlayControls';
@@ -17,7 +17,7 @@ interface DashKitDefaultProps {
17
17
  }) => void;
18
18
  onDrop: (dropProps: {
19
19
  commit: () => void;
20
- pluginType: string;
20
+ dragProps: DragProps;
21
21
  itemLayout: ConfigLayout;
22
22
  newLayout: ConfigLayout[];
23
23
  }) => void;
@@ -5,20 +5,20 @@ const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const DashKitContext_1 = require("../../context/DashKitContext");
7
7
  const DashKitDnDWrapper = (props) => {
8
- const [dragPluginType, setDragPluginType] = react_1.default.useState(null);
9
- const onDragStart = react_1.default.useCallback((_, type) => {
10
- setDragPluginType(type);
11
- }, [setDragPluginType]);
8
+ const [dragProps, setDragProps] = react_1.default.useState(null);
9
+ const onDragStart = react_1.default.useCallback((_, currentProps) => {
10
+ setDragProps(currentProps);
11
+ }, [setDragProps]);
12
12
  const onDragEnd = react_1.default.useCallback((_) => {
13
- setDragPluginType(null);
14
- }, [setDragPluginType]);
13
+ setDragProps(null);
14
+ }, [setDragProps]);
15
15
  const contextValue = react_1.default.useMemo(() => {
16
16
  return {
17
- dragPluginType,
17
+ dragProps,
18
18
  onDragStart,
19
19
  onDragEnd,
20
20
  };
21
- }, [dragPluginType, onDragStart, onDragEnd]);
21
+ }, [dragProps, onDragStart, onDragEnd]);
22
22
  return (react_1.default.createElement(DashKitContext_1.DashKitDnDContext.Provider, { value: contextValue }, props.children));
23
23
  };
24
24
  exports.DashKitDnDWrapper = DashKitDnDWrapper;
@@ -58,9 +58,9 @@ class GridItem extends react_1.default.PureComponent {
58
58
  };
59
59
  }
60
60
  renderOverlay() {
61
- const { overlayControls } = this.props;
61
+ const { overlayControls, isPlaceholder } = this.props;
62
62
  const { editMode } = this.context;
63
- if (!editMode || this.props.item.data._editActive) {
63
+ if (!editMode || this.props.item.data._editActive || isPlaceholder) {
64
64
  return null;
65
65
  }
66
66
  const { item } = this.props;
@@ -72,7 +72,7 @@ class GridItem extends react_1.default.PureComponent {
72
72
  render() {
73
73
  // из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
74
74
  // https://github.com/STRML/react-grid-layout/issues/721
75
- const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, } = this.props;
75
+ const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, isPlaceholder, } = this.props;
76
76
  const { editMode } = this.context;
77
77
  const width = Number.parseInt(style.width, 10);
78
78
  const height = Number.parseInt(style.height, 10);
@@ -97,7 +97,7 @@ class GridItem extends react_1.default.PureComponent {
97
97
  }
98
98
  : {})),
99
99
  react_1.default.createElement("div", { className: b('item', { editMode: editMode && !_editActive && !noOverlay }) },
100
- react_1.default.createElement(Item_1.default, { id: this.props.id, item: this.props.item, shouldItemUpdate: !isDragging, width: width, height: height, transform: transform, adjustWidgetLayout: this.props.adjustWidgetLayout, layout: this.props.layout, forwardedPluginRef: this.props.forwardedPluginRef })),
100
+ 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 })),
101
101
  !noOverlay && this.renderOverlay(),
102
102
  preparedChildren));
103
103
  }
@@ -111,6 +111,7 @@ GridItem.propTypes = {
111
111
  overlayControls: prop_types_1.default.object,
112
112
  forwardedRef: prop_types_1.default.any,
113
113
  forwardedPluginRef: prop_types_1.default.any,
114
+ isPlaceholder: prop_types_1.default.bool,
114
115
  // from react-grid-layout:
115
116
  children: prop_types_1.default.node,
116
117
  className: prop_types_1.default.string,
@@ -23,6 +23,7 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
23
23
  _onStop: (newLayout: any) => void;
24
24
  _onDropDragOver: (e: any) => any;
25
25
  _onDrop: (layout: any, item: any, e: any) => false | undefined;
26
+ renderTemporaryPlaceholder(): JSX.Element | null;
26
27
  render(): JSX.Element;
27
28
  }
28
29
  import React from 'react';
@@ -24,12 +24,12 @@ class DragOverLayout extends react_grid_layout_1.default {
24
24
  window.removeEventListener('dragend', this.dragReset);
25
25
  }
26
26
  processGridItem(child, isDroppingItem) {
27
+ const gridItem = super.processGridItem(child, isDroppingItem);
27
28
  if (isDroppingItem) {
28
29
  // Drop item from outside gets 0,0 droppingPosition
29
30
  // centering cursor on newly creted grid item
30
31
  // And cause grid-layout using it's own GridItem to make it look
31
32
  // like overlay adding className
32
- const gridItem = super.processGridItem(child, isDroppingItem);
33
33
  if (!gridItem)
34
34
  return null;
35
35
  const { props } = gridItem;
@@ -41,7 +41,7 @@ class DragOverLayout extends react_grid_layout_1.default {
41
41
  droppingPosition: Object.assign(Object.assign({}, props.droppingPosition), { left: props.droppingPosition.left - leftOffset, top: props.droppingPosition.top - topOffset }),
42
42
  });
43
43
  }
44
- return super.processGridItem(child, isDroppingItem);
44
+ return gridItem;
45
45
  }
46
46
  }
47
47
  const Layout = (0, react_grid_layout_1.WidthProvider)(DragOverLayout); // eslint-disable-line new-cap
@@ -85,17 +85,16 @@ class GridLayout extends react_1.default.PureComponent {
85
85
  this.setState({ isDragging: false });
86
86
  };
87
87
  this._onDropDragOver = (e) => {
88
- const { editMode, onDropDragOver, temporaryLayout } = this.context;
89
- if (!editMode) {
88
+ const { editMode, dragOverPlugin, onDropDragOver, temporaryLayout } = this.context;
89
+ if (!editMode || !dragOverPlugin || temporaryLayout) {
90
90
  return false;
91
91
  }
92
- const result = onDropDragOver(e);
93
- if (temporaryLayout) {
94
- return false;
95
- }
96
- return result;
92
+ return onDropDragOver(e);
97
93
  };
98
94
  this._onDrop = (layout, item, e) => {
95
+ if (!item) {
96
+ return false;
97
+ }
99
98
  const { editMode, temporaryLayout, onDrop } = this.context;
100
99
  if (!editMode && temporaryLayout) {
101
100
  return false;
@@ -134,6 +133,15 @@ class GridLayout extends react_1.default.PureComponent {
134
133
  this._timeout = setTimeout(() => this.reloadItems(), reloadIntervalRemains <= 0 ? autoupdateIntervalMs : reloadIntervalRemains);
135
134
  }
136
135
  }
136
+ renderTemporaryPlaceholder() {
137
+ const { temporaryLayout, dragOverPlugin, noOverlay, draggableHandleClassName } = this.context;
138
+ if (!temporaryLayout) {
139
+ return null;
140
+ }
141
+ const id = constants_1.TEMPORARY_ITEM_ID;
142
+ const type = dragOverPlugin.type;
143
+ return (react_1.default.createElement(GridItem_1.default, { key: id, id: id, item: { id, type, data: {} }, layout: temporaryLayout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, isPlaceholder: true, noOverlay: noOverlay, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
144
+ }
137
145
  render() {
138
146
  const { layout, temporaryLayout, config, registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
139
147
  this.pluginsRefs.length = config.items.length;
@@ -145,11 +153,13 @@ class GridLayout extends react_1.default.PureComponent {
145
153
  onDropDragOver: this._onDropDragOver,
146
154
  onDrop: this._onDrop,
147
155
  }
148
- : null), { draggableCancel: `.${constants_1.OVERLAY_CONTROLS_CLASS_NAME}` }), config.items.map((item, i) => {
149
- return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: (pluginRef) => {
150
- this.pluginsRefs[i] = pluginRef;
151
- }, key: item.id, id: item.id, item: item, layout: temporaryLayout || layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
152
- })));
156
+ : null), { draggableCancel: `.${constants_1.OVERLAY_CONTROLS_CLASS_NAME}` }),
157
+ config.items.map((item, i) => {
158
+ return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: (pluginRef) => {
159
+ this.pluginsRefs[i] = pluginRef;
160
+ }, key: item.id, id: item.id, item: item, layout: temporaryLayout || layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
161
+ }),
162
+ this.renderTemporaryPlaceholder()));
153
163
  }
154
164
  }
155
165
  GridLayout.contextType = DashKitContext_1.DashKitContext;
@@ -56,6 +56,7 @@ declare const _default: {
56
56
  width: PropTypes.Requireable<number>;
57
57
  height: PropTypes.Requireable<number>;
58
58
  transform: PropTypes.Requireable<string>;
59
+ isPlaceholder: PropTypes.Requireable<boolean>;
59
60
  forwardedPluginRef: PropTypes.Requireable<any>;
60
61
  };
61
62
  contextType: React.Context<any>;
@@ -7,11 +7,16 @@ 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, forwardedPluginRef }) => {
10
+ const Item = ({ registerManager, rendererProps, type, isPlaceholder, forwardedPluginRef }) => {
11
+ var _a, _b;
11
12
  if (!registerManager.check(type)) {
12
13
  console.warn(`type [${type}] не зарегистрирован`);
13
14
  return null;
14
15
  }
16
+ if (isPlaceholder) {
17
+ return (react_1.default.createElement("div", { className: b('placeholder') }, ((_b = (_a = registerManager
18
+ .getItem(type)).placeholderRenderer) === null || _b === void 0 ? void 0 : _b.call(_a, rendererProps, forwardedPluginRef)) || null));
19
+ }
15
20
  return (react_1.default.createElement("div", { className: b('renderer') }, registerManager.getItem(type).renderer(rendererProps, forwardedPluginRef)));
16
21
  };
17
22
  Item.propTypes = {
@@ -19,5 +24,6 @@ Item.propTypes = {
19
24
  rendererProps: prop_types_1.default.object,
20
25
  registerManager: prop_types_1.default.object,
21
26
  type: prop_types_1.default.string,
27
+ isPlaceholder: prop_types_1.default.bool,
22
28
  };
23
29
  exports.default = (0, prepareItem_1.prepareItem)(Item);
@@ -56,6 +56,7 @@ export function prepareItem(Component: any): {
56
56
  width: PropTypes.Requireable<number>;
57
57
  height: PropTypes.Requireable<number>;
58
58
  transform: PropTypes.Requireable<string>;
59
+ isPlaceholder: PropTypes.Requireable<boolean>;
59
60
  forwardedPluginRef: PropTypes.Requireable<any>;
60
61
  };
61
62
  contextType: React.Context<any>;
@@ -26,7 +26,7 @@ function prepareItem(Component) {
26
26
  return true;
27
27
  }
28
28
  render() {
29
- const { id, width, height, item, adjustWidgetLayout, layout } = this.props;
29
+ const { id, width, height, item, adjustWidgetLayout, layout, isPlaceholder } = this.props;
30
30
  const { itemsState, itemsParams, registerManager, settings, context, editMode } = this.context;
31
31
  const { type, data, defaults, namespace } = item;
32
32
  const rendererProps = {
@@ -45,8 +45,9 @@ function prepareItem(Component) {
45
45
  layout,
46
46
  gridLayout: registerManager.gridLayout,
47
47
  adjustWidgetLayout,
48
+ isPlaceholder,
48
49
  };
49
- return (react_1.default.createElement(Component, { forwardedPluginRef: this.props.forwardedPluginRef, rendererProps: rendererProps, registerManager: registerManager, type: type }));
50
+ return (react_1.default.createElement(Component, { forwardedPluginRef: this.props.forwardedPluginRef, rendererProps: rendererProps, registerManager: registerManager, type: type, isPlaceholder: isPlaceholder }));
50
51
  }
51
52
  },
52
53
  _a.propTypes = {
@@ -58,6 +59,7 @@ function prepareItem(Component) {
58
59
  width: prop_types_1.default.number,
59
60
  height: prop_types_1.default.number,
60
61
  transform: prop_types_1.default.string,
62
+ isPlaceholder: prop_types_1.default.bool,
61
63
  forwardedPluginRef: prop_types_1.default.any,
62
64
  },
63
65
  _a.contextType = DashKitContext_1.DashKitContext,
@@ -8,6 +8,8 @@ const common_1 = require("../constants/common");
8
8
  const DashKitContext_1 = require("../context/DashKitContext");
9
9
  const shared_1 = require("../shared");
10
10
  const utils_1 = require("../utils");
11
+ const DEFAULT_HEIGHT = 3;
12
+ const DEFAULT_WIDTH = 3;
11
13
  function useMemoStateContext(props) {
12
14
  // так как мы не хотим хранить параметры виджета с активированной автовысотой в сторе и на сервере, актуальный
13
15
  // (видимый юзером в конкретный момент времени) лэйаут (массив объектов с данными о ширине, высоте,
@@ -144,20 +146,11 @@ function useMemoStateContext(props) {
144
146
  const reloadItems = react_1.default.useCallback((pluginsRefs, data) => {
145
147
  pluginsRefs.forEach((ref) => ref && ref.reload && ref.reload(data));
146
148
  }, []);
147
- const draggedPluginRef = react_1.default.useRef(dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType);
148
- react_1.default.useEffect(() => {
149
- if (!(dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType) && !temporaryLayout) {
150
- draggedPluginRef.current = null;
151
- }
152
- else if (dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType) {
153
- draggedPluginRef.current = dndContext.dragPluginType;
154
- }
155
- }, [draggedPluginRef, dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType, temporaryLayout]);
156
- const dndPluginType = draggedPluginRef.current || (dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType);
149
+ const dragProps = dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragProps;
157
150
  const dragOverPlugin = react_1.default.useMemo(() => {
158
- const pluginType = dndPluginType;
159
- if (pluginType === null && temporaryLayout === null)
151
+ if (!dragProps && temporaryLayout === null)
160
152
  return null;
153
+ const pluginType = dragProps.type;
161
154
  if (props.registerManager.check(pluginType)) {
162
155
  return props.registerManager.getItem(pluginType);
163
156
  }
@@ -166,22 +159,27 @@ function useMemoStateContext(props) {
166
159
  console.error(`Uknown pluginType: ${pluginType}`);
167
160
  return null;
168
161
  }
169
- }, [dndPluginType, props.registerManager, temporaryLayout]);
162
+ }, [dragProps, temporaryLayout, props.registerManager]);
170
163
  const onDropDragOver = react_1.default.useCallback(() => {
171
164
  if (temporaryLayout) {
172
165
  resetTemporaryLayout();
173
166
  return false;
174
167
  }
175
- if (dragOverPlugin === null || dragOverPlugin === void 0 ? void 0 : dragOverPlugin.defaultLayout) {
176
- const { h = 3, w = 3 } = dragOverPlugin.defaultLayout;
168
+ if (dragOverPlugin) {
169
+ const { defaultLayout } = dragOverPlugin;
170
+ const { h = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.h) || DEFAULT_HEIGHT, w = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.w) || DEFAULT_WIDTH } = dragProps;
177
171
  return { h, w };
178
172
  }
179
173
  return false;
180
- }, [resetTemporaryLayout, temporaryLayout, dragOverPlugin]);
174
+ }, [resetTemporaryLayout, temporaryLayout, dragOverPlugin, dragProps]);
175
+ const onDropProp = props.onDrop;
181
176
  const onDrop = react_1.default.useCallback((newLayout, item) => {
177
+ if (!dragProps) {
178
+ return;
179
+ }
182
180
  setTemporaryLayout(newLayout);
183
181
  const { i, w, h, x, y } = item;
184
- props.onDrop({
182
+ onDropProp({
185
183
  newLayout: newLayout.reduce((memo, l) => {
186
184
  if (l.i !== i) {
187
185
  memo.push({ i: l.i, w: l.w, h: l.h, x: l.x, y: l.y });
@@ -189,10 +187,10 @@ function useMemoStateContext(props) {
189
187
  return memo;
190
188
  }, []),
191
189
  itemLayout: { w, h, x, y },
192
- pluginType: dndPluginType,
193
190
  commit: resetTemporaryLayout,
191
+ dragProps,
194
192
  });
195
- }, [dndPluginType, props.onDrop]);
193
+ }, [dragProps, onDropProp, resetTemporaryLayout]);
196
194
  return react_1.default.useMemo(() => ({
197
195
  layout: resultLayout,
198
196
  temporaryLayout,
@@ -117,8 +117,5 @@ const plugin = {
117
117
  renderer(props, forwardedRef) {
118
118
  return react_1.default.createElement(PluginText, Object.assign({}, props, { apiHandler: plugin._apiHandler, ref: forwardedRef }));
119
119
  },
120
- placeholderRenderer(_, forwardedRef) {
121
- return react_1.default.createElement("div", { ref: forwardedRef }, "Text placeholder");
122
- },
123
120
  };
124
121
  exports.default = plugin;
@@ -1,4 +1,9 @@
1
1
  import { StringParams } from './common';
2
+ export type DragProps = {
3
+ type: string;
4
+ w?: number;
5
+ h?: number;
6
+ };
2
7
  export interface ConfigLayout {
3
8
  i: string;
4
9
  h: number;
@@ -1,15 +1,6 @@
1
- import React from 'react';
2
- import { ActionPanelProps } from './types';
1
+ /// <reference types="react" />
2
+ import { ActionPanelItem, ActionPanelProps } from './types';
3
3
  import './ActionPanel.css';
4
- export type ActionPanelItem = {
5
- id: string;
6
- icon: React.ReactNode;
7
- title: string;
8
- onClick?: () => void;
9
- className?: string;
10
- qa?: string;
11
- pluginType?: string;
12
- };
13
4
  export declare const ActionPanelItemContainer: ({ item }: {
14
5
  item: ActionPanelItem;
15
6
  }) => JSX.Element;
@@ -7,13 +7,13 @@ const b = cn('dashkit-action-panel');
7
7
  export const ActionPanelItemContainer = ({ item }) => {
8
8
  const dragContext = React.useContext(DashKitDnDContext);
9
9
  const onDragStart = React.useCallback((e) => {
10
- dragContext.onDragStart(e, item.pluginType);
11
- }, [dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragStart, item.pluginType]);
10
+ dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragStart(e, item.dragProps);
11
+ }, [dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragStart, item.dragProps]);
12
12
  const onDragEnd = React.useCallback((e) => {
13
- dragContext.onDragEnd(e);
13
+ dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragEnd(e);
14
14
  }, [dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragEnd]);
15
15
  let dndProps = {};
16
- if (item.pluginType) {
16
+ if (item.dragProps) {
17
17
  dndProps = {
18
18
  draggable: true,
19
19
  unselectable: 'on',
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ import type { DragProps } from '../../shared';
2
3
  export type ActionPanelItem = {
3
4
  id: string;
4
5
  icon: React.ReactNode;
@@ -6,6 +7,7 @@ export type ActionPanelItem = {
6
7
  onClick?: () => void;
7
8
  className?: string;
8
9
  qa?: string;
10
+ dragProps?: DragProps;
9
11
  };
10
12
  export type ActionPanelProps = {
11
13
  items: ActionPanelItem[];
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { Config, ConfigItem, ConfigLayout, GlobalParams, ItemsStateAndParams } from '../../shared';
2
+ import type { Config, ConfigItem, ConfigLayout, DragProps, GlobalParams, ItemsStateAndParams } from '../../shared';
3
3
  import { ContextProps, Plugin, SetConfigItem, SetNewItemOptions, Settings, SettingsProps } from '../../typings';
4
4
  import GridLayout from '../GridLayout/GridLayout';
5
5
  import { OverlayControlItem } from '../OverlayControls/OverlayControls';
@@ -17,7 +17,7 @@ interface DashKitDefaultProps {
17
17
  }) => void;
18
18
  onDrop: (dropProps: {
19
19
  commit: () => void;
20
- pluginType: string;
20
+ dragProps: DragProps;
21
21
  itemLayout: ConfigLayout;
22
22
  newLayout: ConfigLayout[];
23
23
  }) => void;
@@ -1,19 +1,19 @@
1
1
  import React from 'react';
2
2
  import { DashKitDnDContext } from '../../context/DashKitContext';
3
3
  export const DashKitDnDWrapper = (props) => {
4
- const [dragPluginType, setDragPluginType] = React.useState(null);
5
- const onDragStart = React.useCallback((_, type) => {
6
- setDragPluginType(type);
7
- }, [setDragPluginType]);
4
+ const [dragProps, setDragProps] = React.useState(null);
5
+ const onDragStart = React.useCallback((_, currentProps) => {
6
+ setDragProps(currentProps);
7
+ }, [setDragProps]);
8
8
  const onDragEnd = React.useCallback((_) => {
9
- setDragPluginType(null);
10
- }, [setDragPluginType]);
9
+ setDragProps(null);
10
+ }, [setDragProps]);
11
11
  const contextValue = React.useMemo(() => {
12
12
  return {
13
- dragPluginType,
13
+ dragProps,
14
14
  onDragStart,
15
15
  onDragEnd,
16
16
  };
17
- }, [dragPluginType, onDragStart, onDragEnd]);
17
+ }, [dragProps, onDragStart, onDragEnd]);
18
18
  return (React.createElement(DashKitDnDContext.Provider, { value: contextValue }, props.children));
19
19
  };
@@ -56,9 +56,9 @@ class GridItem extends React.PureComponent {
56
56
  };
57
57
  }
58
58
  renderOverlay() {
59
- const { overlayControls } = this.props;
59
+ const { overlayControls, isPlaceholder } = this.props;
60
60
  const { editMode } = this.context;
61
- if (!editMode || this.props.item.data._editActive) {
61
+ if (!editMode || this.props.item.data._editActive || isPlaceholder) {
62
62
  return null;
63
63
  }
64
64
  const { item } = this.props;
@@ -70,7 +70,7 @@ class GridItem extends React.PureComponent {
70
70
  render() {
71
71
  // из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
72
72
  // https://github.com/STRML/react-grid-layout/issues/721
73
- const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, } = this.props;
73
+ const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, isPlaceholder, } = this.props;
74
74
  const { editMode } = this.context;
75
75
  const width = Number.parseInt(style.width, 10);
76
76
  const height = Number.parseInt(style.height, 10);
@@ -95,7 +95,7 @@ class GridItem extends React.PureComponent {
95
95
  }
96
96
  : {})),
97
97
  React.createElement("div", { className: b('item', { editMode: editMode && !_editActive && !noOverlay }) },
98
- React.createElement(Item, { id: this.props.id, item: this.props.item, shouldItemUpdate: !isDragging, width: width, height: height, transform: transform, adjustWidgetLayout: this.props.adjustWidgetLayout, layout: this.props.layout, forwardedPluginRef: this.props.forwardedPluginRef })),
98
+ 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 })),
99
99
  !noOverlay && this.renderOverlay(),
100
100
  preparedChildren));
101
101
  }
@@ -109,6 +109,7 @@ GridItem.propTypes = {
109
109
  overlayControls: PropTypes.object,
110
110
  forwardedRef: PropTypes.any,
111
111
  forwardedPluginRef: PropTypes.any,
112
+ isPlaceholder: PropTypes.bool,
112
113
  // from react-grid-layout:
113
114
  children: PropTypes.node,
114
115
  className: PropTypes.string,
@@ -23,6 +23,7 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
23
23
  _onStop: (newLayout: any) => void;
24
24
  _onDropDragOver: (e: any) => any;
25
25
  _onDrop: (layout: any, item: any, e: any) => false | undefined;
26
+ renderTemporaryPlaceholder(): JSX.Element | null;
26
27
  render(): JSX.Element;
27
28
  }
28
29
  import React from 'react';
@@ -21,12 +21,12 @@ class DragOverLayout extends ReactGridLayout {
21
21
  window.removeEventListener('dragend', this.dragReset);
22
22
  }
23
23
  processGridItem(child, isDroppingItem) {
24
+ const gridItem = super.processGridItem(child, isDroppingItem);
24
25
  if (isDroppingItem) {
25
26
  // Drop item from outside gets 0,0 droppingPosition
26
27
  // centering cursor on newly creted grid item
27
28
  // And cause grid-layout using it's own GridItem to make it look
28
29
  // like overlay adding className
29
- const gridItem = super.processGridItem(child, isDroppingItem);
30
30
  if (!gridItem)
31
31
  return null;
32
32
  const { props } = gridItem;
@@ -38,7 +38,7 @@ class DragOverLayout extends ReactGridLayout {
38
38
  droppingPosition: Object.assign(Object.assign({}, props.droppingPosition), { left: props.droppingPosition.left - leftOffset, top: props.droppingPosition.top - topOffset }),
39
39
  });
40
40
  }
41
- return super.processGridItem(child, isDroppingItem);
41
+ return gridItem;
42
42
  }
43
43
  }
44
44
  const Layout = WidthProvider(DragOverLayout); // eslint-disable-line new-cap
@@ -82,17 +82,16 @@ class GridLayout extends React.PureComponent {
82
82
  this.setState({ isDragging: false });
83
83
  };
84
84
  this._onDropDragOver = (e) => {
85
- const { editMode, onDropDragOver, temporaryLayout } = this.context;
86
- if (!editMode) {
85
+ const { editMode, dragOverPlugin, onDropDragOver, temporaryLayout } = this.context;
86
+ if (!editMode || !dragOverPlugin || temporaryLayout) {
87
87
  return false;
88
88
  }
89
- const result = onDropDragOver(e);
90
- if (temporaryLayout) {
91
- return false;
92
- }
93
- return result;
89
+ return onDropDragOver(e);
94
90
  };
95
91
  this._onDrop = (layout, item, e) => {
92
+ if (!item) {
93
+ return false;
94
+ }
96
95
  const { editMode, temporaryLayout, onDrop } = this.context;
97
96
  if (!editMode && temporaryLayout) {
98
97
  return false;
@@ -131,6 +130,15 @@ class GridLayout extends React.PureComponent {
131
130
  this._timeout = setTimeout(() => this.reloadItems(), reloadIntervalRemains <= 0 ? autoupdateIntervalMs : reloadIntervalRemains);
132
131
  }
133
132
  }
133
+ renderTemporaryPlaceholder() {
134
+ const { temporaryLayout, dragOverPlugin, noOverlay, draggableHandleClassName } = this.context;
135
+ if (!temporaryLayout) {
136
+ return null;
137
+ }
138
+ const id = TEMPORARY_ITEM_ID;
139
+ const type = dragOverPlugin.type;
140
+ return (React.createElement(GridItem, { key: id, id: id, item: { id, type, data: {} }, layout: temporaryLayout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, isPlaceholder: true, noOverlay: noOverlay, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
141
+ }
134
142
  render() {
135
143
  const { layout, temporaryLayout, config, registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
136
144
  this.pluginsRefs.length = config.items.length;
@@ -142,11 +150,13 @@ class GridLayout extends React.PureComponent {
142
150
  onDropDragOver: this._onDropDragOver,
143
151
  onDrop: this._onDrop,
144
152
  }
145
- : null), { draggableCancel: `.${OVERLAY_CONTROLS_CLASS_NAME}` }), config.items.map((item, i) => {
146
- return (React.createElement(GridItem, { forwardedPluginRef: (pluginRef) => {
147
- this.pluginsRefs[i] = pluginRef;
148
- }, key: item.id, id: item.id, item: item, layout: temporaryLayout || layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
149
- })));
153
+ : null), { draggableCancel: `.${OVERLAY_CONTROLS_CLASS_NAME}` }),
154
+ config.items.map((item, i) => {
155
+ return (React.createElement(GridItem, { forwardedPluginRef: (pluginRef) => {
156
+ this.pluginsRefs[i] = pluginRef;
157
+ }, key: item.id, id: item.id, item: item, layout: temporaryLayout || layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
158
+ }),
159
+ this.renderTemporaryPlaceholder()));
150
160
  }
151
161
  }
152
162
  GridLayout.contextType = DashKitContext;
@@ -56,6 +56,7 @@ declare const _default: {
56
56
  width: PropTypes.Requireable<number>;
57
57
  height: PropTypes.Requireable<number>;
58
58
  transform: PropTypes.Requireable<string>;
59
+ isPlaceholder: PropTypes.Requireable<boolean>;
59
60
  forwardedPluginRef: PropTypes.Requireable<any>;
60
61
  };
61
62
  contextType: React.Context<any>;
@@ -5,11 +5,16 @@ 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, forwardedPluginRef }) => {
8
+ const Item = ({ registerManager, rendererProps, type, isPlaceholder, forwardedPluginRef }) => {
9
+ var _a, _b;
9
10
  if (!registerManager.check(type)) {
10
11
  console.warn(`type [${type}] не зарегистрирован`);
11
12
  return null;
12
13
  }
14
+ if (isPlaceholder) {
15
+ return (React.createElement("div", { className: b('placeholder') }, ((_b = (_a = registerManager
16
+ .getItem(type)).placeholderRenderer) === null || _b === void 0 ? void 0 : _b.call(_a, rendererProps, forwardedPluginRef)) || null));
17
+ }
13
18
  return (React.createElement("div", { className: b('renderer') }, registerManager.getItem(type).renderer(rendererProps, forwardedPluginRef)));
14
19
  };
15
20
  Item.propTypes = {
@@ -17,5 +22,6 @@ Item.propTypes = {
17
22
  rendererProps: PropTypes.object,
18
23
  registerManager: PropTypes.object,
19
24
  type: PropTypes.string,
25
+ isPlaceholder: PropTypes.bool,
20
26
  };
21
27
  export default prepareItem(Item);
@@ -56,6 +56,7 @@ export function prepareItem(Component: any): {
56
56
  width: PropTypes.Requireable<number>;
57
57
  height: PropTypes.Requireable<number>;
58
58
  transform: PropTypes.Requireable<string>;
59
+ isPlaceholder: PropTypes.Requireable<boolean>;
59
60
  forwardedPluginRef: PropTypes.Requireable<any>;
60
61
  };
61
62
  contextType: React.Context<any>;
@@ -22,7 +22,7 @@ export function prepareItem(Component) {
22
22
  return true;
23
23
  }
24
24
  render() {
25
- const { id, width, height, item, adjustWidgetLayout, layout } = this.props;
25
+ const { id, width, height, item, adjustWidgetLayout, layout, isPlaceholder } = this.props;
26
26
  const { itemsState, itemsParams, registerManager, settings, context, editMode } = this.context;
27
27
  const { type, data, defaults, namespace } = item;
28
28
  const rendererProps = {
@@ -41,8 +41,9 @@ export function prepareItem(Component) {
41
41
  layout,
42
42
  gridLayout: registerManager.gridLayout,
43
43
  adjustWidgetLayout,
44
+ isPlaceholder,
44
45
  };
45
- return (React.createElement(Component, { forwardedPluginRef: this.props.forwardedPluginRef, rendererProps: rendererProps, registerManager: registerManager, type: type }));
46
+ return (React.createElement(Component, { forwardedPluginRef: this.props.forwardedPluginRef, rendererProps: rendererProps, registerManager: registerManager, type: type, isPlaceholder: isPlaceholder }));
46
47
  }
47
48
  },
48
49
  _a.propTypes = {
@@ -54,6 +55,7 @@ export function prepareItem(Component) {
54
55
  width: PropTypes.number,
55
56
  height: PropTypes.number,
56
57
  transform: PropTypes.string,
58
+ isPlaceholder: PropTypes.bool,
57
59
  forwardedPluginRef: PropTypes.any,
58
60
  },
59
61
  _a.contextType = DashKitContext,
@@ -4,6 +4,8 @@ import { TEMPORARY_ITEM_ID } from '../constants/common';
4
4
  import { DashKitContext, DashKitDnDContext } from '../context/DashKitContext';
5
5
  import { getItemsParams, getItemsState } from '../shared';
6
6
  import { UpdateManager } from '../utils';
7
+ const DEFAULT_HEIGHT = 3;
8
+ const DEFAULT_WIDTH = 3;
7
9
  function useMemoStateContext(props) {
8
10
  // так как мы не хотим хранить параметры виджета с активированной автовысотой в сторе и на сервере, актуальный
9
11
  // (видимый юзером в конкретный момент времени) лэйаут (массив объектов с данными о ширине, высоте,
@@ -140,20 +142,11 @@ function useMemoStateContext(props) {
140
142
  const reloadItems = React.useCallback((pluginsRefs, data) => {
141
143
  pluginsRefs.forEach((ref) => ref && ref.reload && ref.reload(data));
142
144
  }, []);
143
- const draggedPluginRef = React.useRef(dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType);
144
- React.useEffect(() => {
145
- if (!(dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType) && !temporaryLayout) {
146
- draggedPluginRef.current = null;
147
- }
148
- else if (dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType) {
149
- draggedPluginRef.current = dndContext.dragPluginType;
150
- }
151
- }, [draggedPluginRef, dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType, temporaryLayout]);
152
- const dndPluginType = draggedPluginRef.current || (dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType);
145
+ const dragProps = dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragProps;
153
146
  const dragOverPlugin = React.useMemo(() => {
154
- const pluginType = dndPluginType;
155
- if (pluginType === null && temporaryLayout === null)
147
+ if (!dragProps && temporaryLayout === null)
156
148
  return null;
149
+ const pluginType = dragProps.type;
157
150
  if (props.registerManager.check(pluginType)) {
158
151
  return props.registerManager.getItem(pluginType);
159
152
  }
@@ -162,22 +155,27 @@ function useMemoStateContext(props) {
162
155
  console.error(`Uknown pluginType: ${pluginType}`);
163
156
  return null;
164
157
  }
165
- }, [dndPluginType, props.registerManager, temporaryLayout]);
158
+ }, [dragProps, temporaryLayout, props.registerManager]);
166
159
  const onDropDragOver = React.useCallback(() => {
167
160
  if (temporaryLayout) {
168
161
  resetTemporaryLayout();
169
162
  return false;
170
163
  }
171
- if (dragOverPlugin === null || dragOverPlugin === void 0 ? void 0 : dragOverPlugin.defaultLayout) {
172
- const { h = 3, w = 3 } = dragOverPlugin.defaultLayout;
164
+ if (dragOverPlugin) {
165
+ const { defaultLayout } = dragOverPlugin;
166
+ const { h = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.h) || DEFAULT_HEIGHT, w = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.w) || DEFAULT_WIDTH } = dragProps;
173
167
  return { h, w };
174
168
  }
175
169
  return false;
176
- }, [resetTemporaryLayout, temporaryLayout, dragOverPlugin]);
170
+ }, [resetTemporaryLayout, temporaryLayout, dragOverPlugin, dragProps]);
171
+ const onDropProp = props.onDrop;
177
172
  const onDrop = React.useCallback((newLayout, item) => {
173
+ if (!dragProps) {
174
+ return;
175
+ }
178
176
  setTemporaryLayout(newLayout);
179
177
  const { i, w, h, x, y } = item;
180
- props.onDrop({
178
+ onDropProp({
181
179
  newLayout: newLayout.reduce((memo, l) => {
182
180
  if (l.i !== i) {
183
181
  memo.push({ i: l.i, w: l.w, h: l.h, x: l.x, y: l.y });
@@ -185,10 +183,10 @@ function useMemoStateContext(props) {
185
183
  return memo;
186
184
  }, []),
187
185
  itemLayout: { w, h, x, y },
188
- pluginType: dndPluginType,
189
186
  commit: resetTemporaryLayout,
187
+ dragProps,
190
188
  });
191
- }, [dndPluginType, props.onDrop]);
189
+ }, [dragProps, onDropProp, resetTemporaryLayout]);
192
190
  return React.useMemo(() => ({
193
191
  layout: resultLayout,
194
192
  temporaryLayout,
@@ -113,8 +113,5 @@ const plugin = {
113
113
  renderer(props, forwardedRef) {
114
114
  return React.createElement(PluginText, Object.assign({}, props, { apiHandler: plugin._apiHandler, ref: forwardedRef }));
115
115
  },
116
- placeholderRenderer(_, forwardedRef) {
117
- return React.createElement("div", { ref: forwardedRef }, "Text placeholder");
118
- },
119
116
  };
120
117
  export default plugin;
@@ -1,4 +1,9 @@
1
1
  import { StringParams } from './common';
2
+ export type DragProps = {
3
+ type: string;
4
+ w?: number;
5
+ h?: number;
6
+ };
2
7
  export interface ConfigLayout {
3
8
  i: string;
4
9
  h: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dashkit",
3
- "version": "8.1.0-beta.0",
3
+ "version": "8.1.0-beta.2",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {