@gravity-ui/dashkit 8.1.0-beta.4 → 8.1.0-beta.6

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 (33) hide show
  1. package/build/cjs/components/ActionPanel/ActionPanel.js +3 -18
  2. package/build/cjs/components/ActionPanel/types.d.ts +3 -3
  3. package/build/cjs/components/DashKit/DashKit.d.ts +2 -2
  4. package/build/cjs/components/DashKitDnDWrapper/DashKitDnDWrapper.d.ts +1 -0
  5. package/build/cjs/components/DashKitDnDWrapper/DashKitDnDWrapper.js +8 -1
  6. package/build/cjs/components/GridLayout/GridLayout.js +2 -41
  7. package/build/cjs/components/GridLayout/ReactGridLayout.d.ts +3 -0
  8. package/build/cjs/components/GridLayout/ReactGridLayout.js +49 -0
  9. package/build/cjs/components/OverlayControls/OverlayControls.js +2 -2
  10. package/build/cjs/constants/common.d.ts +2 -0
  11. package/build/cjs/constants/common.js +3 -1
  12. package/build/cjs/hocs/withContext.js +2 -4
  13. package/build/cjs/hooks/useDnDItemProps.d.ts +10 -0
  14. package/build/cjs/hooks/useDnDItemProps.js +30 -0
  15. package/build/cjs/shared/types/common.d.ts +8 -0
  16. package/build/cjs/shared/types/config.d.ts +0 -5
  17. package/build/esm/components/ActionPanel/ActionPanel.js +3 -18
  18. package/build/esm/components/ActionPanel/types.d.ts +3 -3
  19. package/build/esm/components/DashKit/DashKit.d.ts +2 -2
  20. package/build/esm/components/DashKitDnDWrapper/DashKitDnDWrapper.d.ts +1 -0
  21. package/build/esm/components/DashKitDnDWrapper/DashKitDnDWrapper.js +8 -1
  22. package/build/esm/components/GridLayout/GridLayout.js +2 -41
  23. package/build/esm/components/GridLayout/ReactGridLayout.d.ts +3 -0
  24. package/build/esm/components/GridLayout/ReactGridLayout.js +45 -0
  25. package/build/esm/components/OverlayControls/OverlayControls.js +2 -2
  26. package/build/esm/constants/common.d.ts +2 -0
  27. package/build/esm/constants/common.js +2 -0
  28. package/build/esm/hocs/withContext.js +3 -5
  29. package/build/esm/hooks/useDnDItemProps.d.ts +10 -0
  30. package/build/esm/hooks/useDnDItemProps.js +25 -0
  31. package/build/esm/shared/types/common.d.ts +8 -0
  32. package/build/esm/shared/types/config.d.ts +0 -5
  33. package/package.json +1 -1
@@ -4,27 +4,12 @@ exports.ActionPanel = exports.ActionPanelItemContainer = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const react_transition_group_1 = require("react-transition-group");
7
- const DashKitContext_1 = require("../../context/DashKitContext");
7
+ const useDnDItemProps_1 = require("../../hooks/useDnDItemProps");
8
8
  const cn_1 = require("../../utils/cn");
9
9
  const b = (0, cn_1.cn)('dashkit-action-panel');
10
10
  const ActionPanelItemContainer = ({ item }) => {
11
- const dragContext = react_1.default.useContext(DashKitContext_1.DashKitDnDContext);
12
- const onDragStart = react_1.default.useCallback((e) => {
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
- const onDragEnd = react_1.default.useCallback((e) => {
16
- dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragEnd(e);
17
- }, [dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragEnd]);
18
- let dndProps = {};
19
- if (item.dragProps) {
20
- dndProps = {
21
- draggable: true,
22
- unselectable: 'on',
23
- onDragStart,
24
- onDragEnd,
25
- };
26
- }
27
- return (react_1.default.createElement("div", Object.assign({ role: "button", className: b('item', item.className), key: `dk-action-panel-${item.id}`, onClick: item.onClick, "data-qa": item.qa }, dndProps),
11
+ const dndProps = (0, useDnDItemProps_1.useDnDItemProps)(item);
12
+ return (react_1.default.createElement("div", Object.assign({ role: "button", className: b('item', { draggable: Boolean(dndProps) }, item.className), key: `dk-action-panel-${item.id}`, onClick: item.onClick, "data-qa": item.qa }, dndProps),
28
13
  react_1.default.createElement("div", { className: b('icon') }, item.icon),
29
14
  react_1.default.createElement("div", { className: b('title'), title: item.title }, item.title)));
30
15
  };
@@ -1,13 +1,13 @@
1
1
  import React from 'react';
2
- import type { DragProps } from '../../shared';
2
+ import type { ItemDragProps } from '../../shared';
3
3
  export type ActionPanelItem = {
4
4
  id: string;
5
5
  icon: React.ReactNode;
6
6
  title: string;
7
- onClick?: () => void;
8
7
  className?: string;
9
8
  qa?: string;
10
- dragProps?: DragProps;
9
+ onClick?: () => void;
10
+ dragProps?: ItemDragProps;
11
11
  };
12
12
  export type ActionPanelProps = {
13
13
  items: ActionPanelItem[];
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { Config, ConfigItem, ConfigLayout, DragProps, GlobalParams, ItemsStateAndParams } from '../../shared';
2
+ import type { Config, ConfigItem, ConfigLayout, GlobalParams, ItemDragProps, 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
- dragProps: DragProps;
20
+ dragProps: ItemDragProps;
21
21
  itemLayout: ConfigLayout;
22
22
  newLayout: ConfigLayout[];
23
23
  }) => void;
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  type DashKitDnDWrapperProps = {
3
+ dragImageSrc?: string;
3
4
  children: React.ReactElement;
4
5
  };
5
6
  export declare const DashKitDnDWrapper: React.FC<DashKitDnDWrapperProps>;
@@ -4,8 +4,14 @@ exports.DashKitDnDWrapper = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const react_1 = tslib_1.__importDefault(require("react"));
6
6
  const DashKitContext_1 = require("../../context/DashKitContext");
7
+ const defaultImageSrc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';
7
8
  const DashKitDnDWrapper = (props) => {
8
9
  const [dragProps, setDragProps] = react_1.default.useState(null);
10
+ const dragImagePreview = react_1.default.useMemo(() => {
11
+ const img = new Image(1, 1);
12
+ img.src = props.dragImageSrc || defaultImageSrc;
13
+ return img;
14
+ }, [props]);
9
15
  const onDragStart = react_1.default.useCallback((_, currentProps) => {
10
16
  setDragProps(currentProps);
11
17
  }, [setDragProps]);
@@ -15,10 +21,11 @@ const DashKitDnDWrapper = (props) => {
15
21
  const contextValue = react_1.default.useMemo(() => {
16
22
  return {
17
23
  dragProps,
24
+ dragImagePreview,
18
25
  onDragStart,
19
26
  onDragEnd,
20
27
  };
21
- }, [dragProps, onDragStart, onDragEnd]);
28
+ }, [dragProps, dragImagePreview, onDragStart, onDragEnd]);
22
29
  return (react_1.default.createElement(DashKitContext_1.DashKitDnDContext.Provider, { value: contextValue }, props.children));
23
30
  };
24
31
  exports.DashKitDnDWrapper = DashKitDnDWrapper;
@@ -2,49 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const react_1 = tslib_1.__importDefault(require("react"));
5
- const react_grid_layout_1 = tslib_1.__importStar(require("react-grid-layout"));
6
5
  const constants_1 = require("../../constants");
7
6
  const DashKitContext_1 = require("../../context/DashKitContext");
8
7
  const GridItem_1 = tslib_1.__importDefault(require("../GridItem/GridItem"));
9
- class DragOverLayout extends react_grid_layout_1.default {
10
- constructor() {
11
- super(...arguments);
12
- this.dragReset = () => {
13
- if (this.dragEnterCounter) {
14
- this.dragEnterCounter = 0;
15
- this.removeDroppingPlaceholder();
16
- }
17
- };
18
- }
19
- componentDidMount() {
20
- super.componentDidMount();
21
- window.addEventListener('dragend', this.dragReset);
22
- }
23
- componentWillUnmount() {
24
- window.removeEventListener('dragend', this.dragReset);
25
- }
26
- processGridItem(child, isDroppingItem) {
27
- const gridItem = super.processGridItem(child, isDroppingItem);
28
- if (isDroppingItem) {
29
- // Drop item from outside gets 0,0 droppingPosition
30
- // centering cursor on newly creted grid item
31
- // And cause grid-layout using it's own GridItem to make it look
32
- // like overlay adding className
33
- if (!gridItem)
34
- return null;
35
- const { props } = gridItem;
36
- const { containerWidth, cols, w, h, rowHeight, margin, transformScale } = props;
37
- const leftOffset = (((containerWidth / cols) * w) / 2 || 0) * transformScale;
38
- const topOffset = ((h * rowHeight + (h - 1) * margin[1]) / 2 || 0) * transformScale;
39
- return react_1.default.cloneElement(gridItem, {
40
- className: constants_1.OVERLAY_CLASS_NAME,
41
- droppingPosition: Object.assign(Object.assign({}, props.droppingPosition), { left: props.droppingPosition.left - leftOffset, top: props.droppingPosition.top - topOffset }),
42
- });
43
- }
44
- return gridItem;
45
- }
46
- }
47
- const Layout = (0, react_grid_layout_1.WidthProvider)(DragOverLayout); // eslint-disable-line new-cap
8
+ const ReactGridLayout_1 = require("./ReactGridLayout");
48
9
  class GridLayout extends react_1.default.PureComponent {
49
10
  constructor(props, context) {
50
11
  super(props, context);
@@ -145,7 +106,7 @@ class GridLayout extends react_1.default.PureComponent {
145
106
  render() {
146
107
  const { layout, temporaryLayout, config, registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
147
108
  this.pluginsRefs.length = config.items.length;
148
- return (react_1.default.createElement(Layout, Object.assign({}, registerManager.gridLayout, { layout: temporaryLayout || layout, isDraggable: editMode, isResizable: editMode, onDragStart: this._onStart, onDragStop: this._onStop, onResizeStart: this._onStart, onResizeStop: this._onStop }, (draggableHandleClassName
109
+ return (react_1.default.createElement(ReactGridLayout_1.Layout, Object.assign({}, registerManager.gridLayout, { layout: temporaryLayout || layout, isDraggable: editMode, isResizable: editMode, onDragStart: this._onStart, onDragStop: this._onStop, onResizeStart: this._onStart, onResizeStop: this._onStop }, (draggableHandleClassName
149
110
  ? { draggableHandle: `.${draggableHandleClassName}` }
150
111
  : null), (outerDnDEnable
151
112
  ? {
@@ -0,0 +1,3 @@
1
+ export const Layout: React.ComponentClass<ReactGridLayout.ReactGridLayoutProps & ReactGridLayout.WidthProviderProps, any>;
2
+ import ReactGridLayout from 'react-grid-layout';
3
+ import React from 'react';
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Layout = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importDefault(require("react"));
6
+ const react_grid_layout_1 = tslib_1.__importStar(require("react-grid-layout"));
7
+ const constants_1 = require("../../constants");
8
+ class DragOverLayout extends react_grid_layout_1.default {
9
+ constructor() {
10
+ super(...arguments);
11
+ this.dragReset = () => {
12
+ if (this.dragEnterCounter) {
13
+ this.dragEnterCounter = 0;
14
+ this.removeDroppingPlaceholder();
15
+ }
16
+ };
17
+ }
18
+ componentDidMount() {
19
+ var _a;
20
+ (_a = super.componentDidMount) === null || _a === void 0 ? void 0 : _a.call(this);
21
+ window.addEventListener('dragend', this.dragReset);
22
+ }
23
+ componentWillUnmount() {
24
+ window.removeEventListener('dragend', this.dragReset);
25
+ }
26
+ processGridItem(child, isDroppingItem) {
27
+ var _a;
28
+ const gridItem = (_a = super.processGridItem) === null || _a === void 0 ? void 0 : _a.call(this, child, isDroppingItem);
29
+ if (isDroppingItem) {
30
+ // Drop item from outside gets 0,0 droppingPosition
31
+ // centering cursor on newly creted grid item
32
+ // And cause grid-layout using it's own GridItem to make it look
33
+ // like overlay adding className
34
+ if (!gridItem)
35
+ return null;
36
+ const { props } = gridItem;
37
+ const { containerWidth, cols, w, h, rowHeight, margin, transformScale } = props;
38
+ const leftOffset = (((containerWidth / cols) * w) / 2 || 0) * transformScale;
39
+ const topOffset = ((h * rowHeight + (h - 1) * margin[1]) / 2 || 0) * transformScale;
40
+ return react_1.default.cloneElement(gridItem, {
41
+ className: constants_1.OVERLAY_CLASS_NAME,
42
+ droppingPosition: Object.assign(Object.assign({}, props.droppingPosition), { left: props.droppingPosition.left - leftOffset, top: props.droppingPosition.top - topOffset }),
43
+ });
44
+ }
45
+ return gridItem;
46
+ }
47
+ }
48
+ // eslint-disable-next-line new-cap
49
+ exports.Layout = (0, react_grid_layout_1.WidthProvider)(DragOverLayout);
@@ -183,8 +183,8 @@ class OverlayControls extends react_1.default.Component {
183
183
  };
184
184
  });
185
185
  items = items.filter(Boolean);
186
- return (react_1.default.createElement(uikit_1.DropdownMenu, { items: items, switcher: react_1.default.createElement(uikit_1.Button, { view: view, size: size, pin: "brick-round", qa: "dashkit-overlay-control-menu" },
187
- react_1.default.createElement(uikit_1.Icon, { data: DotsIcon_1.DotsIcon, size: "16" })) }));
186
+ 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: "brick-round", qa: "dashkit-overlay-control-menu" }),
187
+ react_1.default.createElement(uikit_1.Icon, { data: DotsIcon_1.DotsIcon, size: "16" }))) }));
188
188
  }
189
189
  getControlItemPinStyle(index, itemsLength) {
190
190
  const isOnlyOneItem = itemsLength === 1;
@@ -8,3 +8,5 @@ export declare const MenuItems: {
8
8
  readonly Delete: "delete";
9
9
  readonly Settings: "settings";
10
10
  };
11
+ export declare const DEFAULT_WIDGET_HEIGHT = 3;
12
+ export declare const DEFAULT_WIDGET_WIDTH = 3;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MenuItems = exports.TEMPORARY_ITEM_ID = exports.OVERLAY_CLASS_NAME = exports.OVERLAY_CONTROLS_CLASS_NAME = exports.DEFAULT_NAMESPACE = exports.COPIED_WIDGET_STORE_KEY = void 0;
3
+ exports.DEFAULT_WIDGET_WIDTH = exports.DEFAULT_WIDGET_HEIGHT = exports.MenuItems = exports.TEMPORARY_ITEM_ID = 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';
@@ -11,3 +11,5 @@ exports.MenuItems = {
11
11
  Delete: 'delete',
12
12
  Settings: 'settings',
13
13
  };
14
+ exports.DEFAULT_WIDGET_HEIGHT = 3;
15
+ exports.DEFAULT_WIDGET_WIDTH = 3;
@@ -8,8 +8,6 @@ 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;
13
11
  function useMemoStateContext(props) {
14
12
  // так как мы не хотим хранить параметры виджета с активированной автовысотой в сторе и на сервере, актуальный
15
13
  // (видимый юзером в конкретный момент времени) лэйаут (массив объектов с данными о ширине, высоте,
@@ -148,7 +146,7 @@ function useMemoStateContext(props) {
148
146
  }, []);
149
147
  const dragProps = dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragProps;
150
148
  const dragOverPlugin = react_1.default.useMemo(() => {
151
- if (dragProps === null) {
149
+ if (!dragProps) {
152
150
  return null;
153
151
  }
154
152
  const pluginType = dragProps.type;
@@ -168,7 +166,7 @@ function useMemoStateContext(props) {
168
166
  }
169
167
  if (dragOverPlugin) {
170
168
  const { defaultLayout } = dragOverPlugin;
171
- 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;
169
+ const { h = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.h) || common_1.DEFAULT_WIDGET_HEIGHT, w = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.w) || common_1.DEFAULT_WIDGET_WIDTH, } = dragProps.layout || {};
172
170
  return { h, w };
173
171
  }
174
172
  return false;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { ActionPanelItem } from '../components';
3
+ type DndProps = null | {
4
+ draggable: true;
5
+ unselectable: 'on';
6
+ onDragStart: React.DragEventHandler<HTMLDivElement>;
7
+ onDragEnd: React.DragEventHandler<HTMLDivElement>;
8
+ };
9
+ export declare const useDnDItemProps: (item: ActionPanelItem) => DndProps;
10
+ export {};
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useDnDItemProps = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const react_1 = tslib_1.__importDefault(require("react"));
6
+ const DashKitContext_1 = require("../context/DashKitContext");
7
+ const useDnDItemProps = (item) => {
8
+ const dragContext = react_1.default.useContext(DashKitContext_1.DashKitDnDContext);
9
+ const onDragStart = react_1.default.useCallback((e) => {
10
+ if (dragContext && item.dragProps) {
11
+ dragContext.onDragStart(e, item.dragProps);
12
+ e.dataTransfer.setDragImage(dragContext.dragImagePreview, 0, 0);
13
+ }
14
+ }, [dragContext, item.dragProps]);
15
+ const onDragEnd = react_1.default.useCallback((e) => {
16
+ if (dragContext) {
17
+ dragContext.onDragEnd(e);
18
+ }
19
+ }, [dragContext]);
20
+ if (dragContext && item.dragProps) {
21
+ return {
22
+ draggable: true,
23
+ unselectable: 'on',
24
+ onDragStart,
25
+ onDragEnd,
26
+ };
27
+ }
28
+ return null;
29
+ };
30
+ exports.useDnDItemProps = useDnDItemProps;
@@ -3,3 +3,11 @@ export interface StringParams extends Dictionary<string | string[]> {
3
3
  }
4
4
  export interface GlobalParams extends StringParams {
5
5
  }
6
+ export type ItemDragProps = {
7
+ type: string;
8
+ layout?: {
9
+ w?: number;
10
+ h?: number;
11
+ };
12
+ extra?: any;
13
+ };
@@ -1,9 +1,4 @@
1
1
  import { StringParams } from './common';
2
- export type DragProps = {
3
- type: string;
4
- w?: number;
5
- h?: number;
6
- };
7
2
  export interface ConfigLayout {
8
3
  i: string;
9
4
  h: number;
@@ -1,27 +1,12 @@
1
1
  import React from 'react';
2
2
  import { CSSTransition } from 'react-transition-group';
3
- import { DashKitDnDContext } from '../../context/DashKitContext';
3
+ import { useDnDItemProps } from '../../hooks/useDnDItemProps';
4
4
  import { cn } from '../../utils/cn';
5
5
  import './ActionPanel.css';
6
6
  const b = cn('dashkit-action-panel');
7
7
  export const ActionPanelItemContainer = ({ item }) => {
8
- const dragContext = React.useContext(DashKitDnDContext);
9
- const onDragStart = React.useCallback((e) => {
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
- const onDragEnd = React.useCallback((e) => {
13
- dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragEnd(e);
14
- }, [dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragEnd]);
15
- let dndProps = {};
16
- if (item.dragProps) {
17
- dndProps = {
18
- draggable: true,
19
- unselectable: 'on',
20
- onDragStart,
21
- onDragEnd,
22
- };
23
- }
24
- return (React.createElement("div", Object.assign({ role: "button", className: b('item', item.className), key: `dk-action-panel-${item.id}`, onClick: item.onClick, "data-qa": item.qa }, dndProps),
8
+ const dndProps = useDnDItemProps(item);
9
+ return (React.createElement("div", Object.assign({ role: "button", className: b('item', { draggable: Boolean(dndProps) }, item.className), key: `dk-action-panel-${item.id}`, onClick: item.onClick, "data-qa": item.qa }, dndProps),
25
10
  React.createElement("div", { className: b('icon') }, item.icon),
26
11
  React.createElement("div", { className: b('title'), title: item.title }, item.title)));
27
12
  };
@@ -1,13 +1,13 @@
1
1
  import React from 'react';
2
- import type { DragProps } from '../../shared';
2
+ import type { ItemDragProps } from '../../shared';
3
3
  export type ActionPanelItem = {
4
4
  id: string;
5
5
  icon: React.ReactNode;
6
6
  title: string;
7
- onClick?: () => void;
8
7
  className?: string;
9
8
  qa?: string;
10
- dragProps?: DragProps;
9
+ onClick?: () => void;
10
+ dragProps?: ItemDragProps;
11
11
  };
12
12
  export type ActionPanelProps = {
13
13
  items: ActionPanelItem[];
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { Config, ConfigItem, ConfigLayout, DragProps, GlobalParams, ItemsStateAndParams } from '../../shared';
2
+ import type { Config, ConfigItem, ConfigLayout, GlobalParams, ItemDragProps, 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
- dragProps: DragProps;
20
+ dragProps: ItemDragProps;
21
21
  itemLayout: ConfigLayout;
22
22
  newLayout: ConfigLayout[];
23
23
  }) => void;
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  type DashKitDnDWrapperProps = {
3
+ dragImageSrc?: string;
3
4
  children: React.ReactElement;
4
5
  };
5
6
  export declare const DashKitDnDWrapper: React.FC<DashKitDnDWrapperProps>;
@@ -1,7 +1,13 @@
1
1
  import React from 'react';
2
2
  import { DashKitDnDContext } from '../../context/DashKitContext';
3
+ const defaultImageSrc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';
3
4
  export const DashKitDnDWrapper = (props) => {
4
5
  const [dragProps, setDragProps] = React.useState(null);
6
+ const dragImagePreview = React.useMemo(() => {
7
+ const img = new Image(1, 1);
8
+ img.src = props.dragImageSrc || defaultImageSrc;
9
+ return img;
10
+ }, [props]);
5
11
  const onDragStart = React.useCallback((_, currentProps) => {
6
12
  setDragProps(currentProps);
7
13
  }, [setDragProps]);
@@ -11,9 +17,10 @@ export const DashKitDnDWrapper = (props) => {
11
17
  const contextValue = React.useMemo(() => {
12
18
  return {
13
19
  dragProps,
20
+ dragImagePreview,
14
21
  onDragStart,
15
22
  onDragEnd,
16
23
  };
17
- }, [dragProps, onDragStart, onDragEnd]);
24
+ }, [dragProps, dragImagePreview, onDragStart, onDragEnd]);
18
25
  return (React.createElement(DashKitDnDContext.Provider, { value: contextValue }, props.children));
19
26
  };
@@ -1,47 +1,8 @@
1
1
  import React from 'react';
2
- import ReactGridLayout, { WidthProvider } from 'react-grid-layout';
3
- import { OVERLAY_CLASS_NAME, OVERLAY_CONTROLS_CLASS_NAME, TEMPORARY_ITEM_ID } from '../../constants';
2
+ import { OVERLAY_CONTROLS_CLASS_NAME, TEMPORARY_ITEM_ID } from '../../constants';
4
3
  import { DashKitContext } from '../../context/DashKitContext';
5
4
  import GridItem from '../GridItem/GridItem';
6
- class DragOverLayout extends ReactGridLayout {
7
- constructor() {
8
- super(...arguments);
9
- this.dragReset = () => {
10
- if (this.dragEnterCounter) {
11
- this.dragEnterCounter = 0;
12
- this.removeDroppingPlaceholder();
13
- }
14
- };
15
- }
16
- componentDidMount() {
17
- super.componentDidMount();
18
- window.addEventListener('dragend', this.dragReset);
19
- }
20
- componentWillUnmount() {
21
- window.removeEventListener('dragend', this.dragReset);
22
- }
23
- processGridItem(child, isDroppingItem) {
24
- const gridItem = super.processGridItem(child, isDroppingItem);
25
- if (isDroppingItem) {
26
- // Drop item from outside gets 0,0 droppingPosition
27
- // centering cursor on newly creted grid item
28
- // And cause grid-layout using it's own GridItem to make it look
29
- // like overlay adding className
30
- if (!gridItem)
31
- return null;
32
- const { props } = gridItem;
33
- const { containerWidth, cols, w, h, rowHeight, margin, transformScale } = props;
34
- const leftOffset = (((containerWidth / cols) * w) / 2 || 0) * transformScale;
35
- const topOffset = ((h * rowHeight + (h - 1) * margin[1]) / 2 || 0) * transformScale;
36
- return React.cloneElement(gridItem, {
37
- className: OVERLAY_CLASS_NAME,
38
- droppingPosition: Object.assign(Object.assign({}, props.droppingPosition), { left: props.droppingPosition.left - leftOffset, top: props.droppingPosition.top - topOffset }),
39
- });
40
- }
41
- return gridItem;
42
- }
43
- }
44
- const Layout = WidthProvider(DragOverLayout); // eslint-disable-line new-cap
5
+ import { Layout } from './ReactGridLayout';
45
6
  class GridLayout extends React.PureComponent {
46
7
  constructor(props, context) {
47
8
  super(props, context);
@@ -0,0 +1,3 @@
1
+ export const Layout: React.ComponentClass<ReactGridLayout.ReactGridLayoutProps & ReactGridLayout.WidthProviderProps, any>;
2
+ import ReactGridLayout from 'react-grid-layout';
3
+ import React from 'react';
@@ -0,0 +1,45 @@
1
+ import React from 'react';
2
+ import ReactGridLayout, { WidthProvider } from 'react-grid-layout';
3
+ import { OVERLAY_CLASS_NAME } from '../../constants';
4
+ class DragOverLayout extends ReactGridLayout {
5
+ constructor() {
6
+ super(...arguments);
7
+ this.dragReset = () => {
8
+ if (this.dragEnterCounter) {
9
+ this.dragEnterCounter = 0;
10
+ this.removeDroppingPlaceholder();
11
+ }
12
+ };
13
+ }
14
+ componentDidMount() {
15
+ var _a;
16
+ (_a = super.componentDidMount) === null || _a === void 0 ? void 0 : _a.call(this);
17
+ window.addEventListener('dragend', this.dragReset);
18
+ }
19
+ componentWillUnmount() {
20
+ window.removeEventListener('dragend', this.dragReset);
21
+ }
22
+ processGridItem(child, isDroppingItem) {
23
+ var _a;
24
+ const gridItem = (_a = super.processGridItem) === null || _a === void 0 ? void 0 : _a.call(this, child, isDroppingItem);
25
+ if (isDroppingItem) {
26
+ // Drop item from outside gets 0,0 droppingPosition
27
+ // centering cursor on newly creted grid item
28
+ // And cause grid-layout using it's own GridItem to make it look
29
+ // like overlay adding className
30
+ if (!gridItem)
31
+ return null;
32
+ const { props } = gridItem;
33
+ const { containerWidth, cols, w, h, rowHeight, margin, transformScale } = props;
34
+ const leftOffset = (((containerWidth / cols) * w) / 2 || 0) * transformScale;
35
+ const topOffset = ((h * rowHeight + (h - 1) * margin[1]) / 2 || 0) * transformScale;
36
+ return React.cloneElement(gridItem, {
37
+ className: OVERLAY_CLASS_NAME,
38
+ droppingPosition: Object.assign(Object.assign({}, props.droppingPosition), { left: props.droppingPosition.left - leftOffset, top: props.droppingPosition.top - topOffset }),
39
+ });
40
+ }
41
+ return gridItem;
42
+ }
43
+ }
44
+ // eslint-disable-next-line new-cap
45
+ export const Layout = WidthProvider(DragOverLayout);
@@ -180,8 +180,8 @@ class OverlayControls extends React.Component {
180
180
  };
181
181
  });
182
182
  items = items.filter(Boolean);
183
- return (React.createElement(DropdownMenu, { items: items, switcher: React.createElement(Button, { view: view, size: size, pin: "brick-round", qa: "dashkit-overlay-control-menu" },
184
- React.createElement(Icon, { data: DotsIcon, size: "16" })) }));
183
+ return (React.createElement(DropdownMenu, { items: items, renderSwitcher: (props) => (React.createElement(Button, Object.assign({}, props, { view: view, size: size, pin: "brick-round", qa: "dashkit-overlay-control-menu" }),
184
+ React.createElement(Icon, { data: DotsIcon, size: "16" }))) }));
185
185
  }
186
186
  getControlItemPinStyle(index, itemsLength) {
187
187
  const isOnlyOneItem = itemsLength === 1;
@@ -8,3 +8,5 @@ export declare const MenuItems: {
8
8
  readonly Delete: "delete";
9
9
  readonly Settings: "settings";
10
10
  };
11
+ export declare const DEFAULT_WIDGET_HEIGHT = 3;
12
+ export declare const DEFAULT_WIDGET_WIDTH = 3;
@@ -8,3 +8,5 @@ export const MenuItems = {
8
8
  Delete: 'delete',
9
9
  Settings: 'settings',
10
10
  };
11
+ export const DEFAULT_WIDGET_HEIGHT = 3;
12
+ export const DEFAULT_WIDGET_WIDTH = 3;
@@ -1,11 +1,9 @@
1
1
  import React from 'react';
2
2
  import isEqual from 'lodash/isEqual';
3
- import { TEMPORARY_ITEM_ID } from '../constants/common';
3
+ import { DEFAULT_WIDGET_HEIGHT, DEFAULT_WIDGET_WIDTH, 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;
9
7
  function useMemoStateContext(props) {
10
8
  // так как мы не хотим хранить параметры виджета с активированной автовысотой в сторе и на сервере, актуальный
11
9
  // (видимый юзером в конкретный момент времени) лэйаут (массив объектов с данными о ширине, высоте,
@@ -144,7 +142,7 @@ function useMemoStateContext(props) {
144
142
  }, []);
145
143
  const dragProps = dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragProps;
146
144
  const dragOverPlugin = React.useMemo(() => {
147
- if (dragProps === null) {
145
+ if (!dragProps) {
148
146
  return null;
149
147
  }
150
148
  const pluginType = dragProps.type;
@@ -164,7 +162,7 @@ function useMemoStateContext(props) {
164
162
  }
165
163
  if (dragOverPlugin) {
166
164
  const { defaultLayout } = dragOverPlugin;
167
- 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;
165
+ const { h = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.h) || DEFAULT_WIDGET_HEIGHT, w = (defaultLayout === null || defaultLayout === void 0 ? void 0 : defaultLayout.w) || DEFAULT_WIDGET_WIDTH, } = dragProps.layout || {};
168
166
  return { h, w };
169
167
  }
170
168
  return false;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { ActionPanelItem } from '../components';
3
+ type DndProps = null | {
4
+ draggable: true;
5
+ unselectable: 'on';
6
+ onDragStart: React.DragEventHandler<HTMLDivElement>;
7
+ onDragEnd: React.DragEventHandler<HTMLDivElement>;
8
+ };
9
+ export declare const useDnDItemProps: (item: ActionPanelItem) => DndProps;
10
+ export {};
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ import { DashKitDnDContext } from '../context/DashKitContext';
3
+ export const useDnDItemProps = (item) => {
4
+ const dragContext = React.useContext(DashKitDnDContext);
5
+ const onDragStart = React.useCallback((e) => {
6
+ if (dragContext && item.dragProps) {
7
+ dragContext.onDragStart(e, item.dragProps);
8
+ e.dataTransfer.setDragImage(dragContext.dragImagePreview, 0, 0);
9
+ }
10
+ }, [dragContext, item.dragProps]);
11
+ const onDragEnd = React.useCallback((e) => {
12
+ if (dragContext) {
13
+ dragContext.onDragEnd(e);
14
+ }
15
+ }, [dragContext]);
16
+ if (dragContext && item.dragProps) {
17
+ return {
18
+ draggable: true,
19
+ unselectable: 'on',
20
+ onDragStart,
21
+ onDragEnd,
22
+ };
23
+ }
24
+ return null;
25
+ };
@@ -3,3 +3,11 @@ export interface StringParams extends Dictionary<string | string[]> {
3
3
  }
4
4
  export interface GlobalParams extends StringParams {
5
5
  }
6
+ export type ItemDragProps = {
7
+ type: string;
8
+ layout?: {
9
+ w?: number;
10
+ h?: number;
11
+ };
12
+ extra?: any;
13
+ };
@@ -1,9 +1,4 @@
1
1
  import { StringParams } from './common';
2
- export type DragProps = {
3
- type: string;
4
- w?: number;
5
- h?: number;
6
- };
7
2
  export interface ConfigLayout {
8
3
  i: string;
9
4
  h: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dashkit",
3
- "version": "8.1.0-beta.4",
3
+ "version": "8.1.0-beta.6",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {