@gravity-ui/dashkit 8.1.0 → 8.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +95 -0
  2. package/build/cjs/components/ActionPanel/ActionPanel.d.ts +4 -1
  3. package/build/cjs/components/ActionPanel/ActionPanel.js +10 -6
  4. package/build/cjs/components/ActionPanel/types.d.ts +3 -1
  5. package/build/cjs/components/DashKit/DashKit.d.ts +4 -3
  6. package/build/cjs/components/DashKit/DashKit.js +1 -0
  7. package/build/cjs/components/DashKitDnDWrapper/DashKitDnDWrapper.d.ts +10 -0
  8. package/build/cjs/components/DashKitDnDWrapper/DashKitDnDWrapper.js +35 -0
  9. package/build/cjs/components/GridItem/GridItem.d.ts +2 -2
  10. package/build/cjs/components/GridItem/GridItem.js +8 -5
  11. package/build/cjs/components/GridLayout/GridLayout.d.ts +3 -0
  12. package/build/cjs/components/GridLayout/GridLayout.js +51 -11
  13. package/build/cjs/components/GridLayout/ReactGridLayout.d.ts +3 -0
  14. package/build/cjs/components/GridLayout/ReactGridLayout.js +49 -0
  15. package/build/cjs/components/Item/Item.css +1 -1
  16. package/build/cjs/components/Item/Item.d.ts +1 -0
  17. package/build/cjs/components/Item/Item.js +7 -1
  18. package/build/cjs/components/OverlayControls/OverlayControls.js +2 -2
  19. package/build/cjs/components/index.d.ts +1 -0
  20. package/build/cjs/components/index.js +1 -0
  21. package/build/cjs/constants/common.d.ts +4 -0
  22. package/build/cjs/constants/common.js +5 -1
  23. package/build/cjs/context/DashKitContext.d.ts +1 -0
  24. package/build/cjs/context/DashKitContext.js +3 -1
  25. package/build/cjs/hocs/prepareItem.d.ts +1 -0
  26. package/build/cjs/hocs/prepareItem.js +4 -2
  27. package/build/cjs/hocs/withContext.js +84 -6
  28. package/build/cjs/hooks/useDnDItemProps.d.ts +10 -0
  29. package/build/cjs/hooks/useDnDItemProps.js +30 -0
  30. package/build/cjs/shared/constants/common.d.ts +1 -0
  31. package/build/cjs/shared/constants/common.js +2 -1
  32. package/build/cjs/shared/types/common.d.ts +15 -0
  33. package/build/cjs/typings/config.d.ts +3 -0
  34. package/build/cjs/typings/plugin.d.ts +1 -0
  35. package/build/cjs/utils/update-manager.d.ts +2 -2
  36. package/build/cjs/utils/update-manager.js +25 -7
  37. package/build/esm/components/ActionPanel/ActionPanel.d.ts +4 -1
  38. package/build/esm/components/ActionPanel/ActionPanel.js +8 -5
  39. package/build/esm/components/ActionPanel/types.d.ts +3 -1
  40. package/build/esm/components/DashKit/DashKit.d.ts +4 -3
  41. package/build/esm/components/DashKit/DashKit.js +1 -0
  42. package/build/esm/components/DashKitDnDWrapper/DashKitDnDWrapper.d.ts +10 -0
  43. package/build/esm/components/DashKitDnDWrapper/DashKitDnDWrapper.js +30 -0
  44. package/build/esm/components/GridItem/GridItem.d.ts +2 -2
  45. package/build/esm/components/GridItem/GridItem.js +8 -5
  46. package/build/esm/components/GridLayout/GridLayout.d.ts +3 -0
  47. package/build/esm/components/GridLayout/GridLayout.js +52 -12
  48. package/build/esm/components/GridLayout/ReactGridLayout.d.ts +3 -0
  49. package/build/esm/components/GridLayout/ReactGridLayout.js +45 -0
  50. package/build/esm/components/Item/Item.css +1 -1
  51. package/build/esm/components/Item/Item.d.ts +1 -0
  52. package/build/esm/components/Item/Item.js +7 -1
  53. package/build/esm/components/OverlayControls/OverlayControls.js +2 -2
  54. package/build/esm/components/index.d.ts +1 -0
  55. package/build/esm/components/index.js +1 -0
  56. package/build/esm/constants/common.d.ts +4 -0
  57. package/build/esm/constants/common.js +4 -0
  58. package/build/esm/context/DashKitContext.d.ts +1 -0
  59. package/build/esm/context/DashKitContext.js +2 -1
  60. package/build/esm/hocs/prepareItem.d.ts +1 -0
  61. package/build/esm/hocs/prepareItem.js +4 -2
  62. package/build/esm/hocs/withContext.js +85 -7
  63. package/build/esm/hooks/useDnDItemProps.d.ts +10 -0
  64. package/build/esm/hooks/useDnDItemProps.js +25 -0
  65. package/build/esm/shared/constants/common.d.ts +1 -0
  66. package/build/esm/shared/constants/common.js +1 -0
  67. package/build/esm/shared/types/common.d.ts +15 -0
  68. package/build/esm/typings/config.d.ts +3 -0
  69. package/build/esm/typings/plugin.d.ts +1 -0
  70. package/build/esm/utils/update-manager.d.ts +2 -2
  71. package/build/esm/utils/update-manager.js +25 -7
  72. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- .dashkit-item__renderer {
1
+ .dashkit-item__placeholder, .dashkit-item__renderer {
2
2
  position: absolute;
3
3
  inset: 0;
4
4
  }
@@ -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);
@@ -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;
@@ -2,3 +2,4 @@ export * from './DashKit';
2
2
  export type { OverlayControlItem, PreparedCopyItemOptions } from './OverlayControls/OverlayControls';
3
3
  export * from './ActionPanel/ActionPanel';
4
4
  export type { ActionPanelItem, ActionPanelProps } from './ActionPanel/types';
5
+ export * from './DashKitDnDWrapper/DashKitDnDWrapper';
@@ -1,2 +1,3 @@
1
1
  export * from './DashKit';
2
2
  export * from './ActionPanel/ActionPanel';
3
+ export * from './DashKitDnDWrapper/DashKitDnDWrapper';
@@ -1,8 +1,12 @@
1
1
  export declare const COPIED_WIDGET_STORE_KEY = "dashCopiedItem";
2
2
  export declare const DEFAULT_NAMESPACE = "default";
3
3
  export declare const OVERLAY_CONTROLS_CLASS_NAME = "dashkit-overlay-controls";
4
+ export declare const OVERLAY_CLASS_NAME = "dashkit-grid-item__overlay";
5
+ export declare const TEMPORARY_ITEM_ID = "__dropping-elem__";
4
6
  export declare const MenuItems: {
5
7
  readonly Copy: "copy";
6
8
  readonly Delete: "delete";
7
9
  readonly Settings: "settings";
8
10
  };
11
+ export declare const DEFAULT_WIDGET_HEIGHT = 3;
12
+ export declare const DEFAULT_WIDGET_WIDTH = 3;
@@ -1,8 +1,12 @@
1
1
  export const COPIED_WIDGET_STORE_KEY = 'dashCopiedItem';
2
2
  export const DEFAULT_NAMESPACE = 'default';
3
3
  export const OVERLAY_CONTROLS_CLASS_NAME = 'dashkit-overlay-controls';
4
+ export const OVERLAY_CLASS_NAME = 'dashkit-grid-item__overlay';
5
+ export const TEMPORARY_ITEM_ID = '__dropping-elem__';
4
6
  export const MenuItems = {
5
7
  Copy: 'copy',
6
8
  Delete: 'delete',
7
9
  Settings: 'settings',
8
10
  };
11
+ export const DEFAULT_WIDGET_HEIGHT = 3;
12
+ export const DEFAULT_WIDGET_WIDTH = 3;
@@ -1,2 +1,3 @@
1
1
  export const DashKitContext: React.Context<any>;
2
+ export const DashKitDnDContext: React.Context<any>;
2
3
  import React from 'react';
@@ -1,3 +1,4 @@
1
1
  import React from 'react';
2
2
  const DashKitContext = React.createContext();
3
- export { DashKitContext };
3
+ const DashKitDnDContext = React.createContext();
4
+ export { DashKitContext, DashKitDnDContext };
@@ -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,
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import isEqual from 'lodash/isEqual';
3
- import { DashKitContext } from '../context/DashKitContext';
3
+ import { DEFAULT_WIDGET_HEIGHT, DEFAULT_WIDGET_WIDTH, TEMPORARY_ITEM_ID } from '../constants/common';
4
+ import { DashKitContext, DashKitDnDContext } from '../context/DashKitContext';
4
5
  import { getItemsParams, getItemsState } from '../shared';
5
6
  import { UpdateManager } from '../utils';
6
7
  function useMemoStateContext(props) {
@@ -11,6 +12,10 @@ function useMemoStateContext(props) {
11
12
  // (высота) из конфига будет запоминаться в originalLayouts, новое значение высоты в adjustedLayouts
12
13
  const originalLayouts = React.useRef({});
13
14
  const adjustedLayouts = React.useRef({});
15
+ const [temporaryLayout, setTemporaryLayout] = React.useState(null);
16
+ const resetTemporaryLayout = React.useCallback(() => setTemporaryLayout(null), [setTemporaryLayout]);
17
+ const dndContext = React.useContext(DashKitDnDContext);
18
+ const outerDnDEnable = Boolean(dndContext);
14
19
  // TODO: need move originalLayouts, adjustedLayouts to state
15
20
  const [layoutUpdateCounter, forceUpdateLayout] = React.useState(0);
16
21
  const onChange = React.useCallback(({ config = props.config, itemsStateAndParams = props.itemsStateAndParams }) => {
@@ -41,12 +46,27 @@ function useMemoStateContext(props) {
41
46
  }
42
47
  }, [props.config, onChange]);
43
48
  const onItemRemove = React.useCallback((id) => {
44
- onChange(UpdateManager.removeItem({
45
- id,
46
- config: props.config,
47
- itemsStateAndParams: props.itemsStateAndParams,
48
- }));
49
- }, [props.config, props.itemsStateAndParams, onChange]);
49
+ if (id === TEMPORARY_ITEM_ID) {
50
+ resetTemporaryLayout();
51
+ }
52
+ else {
53
+ if (temporaryLayout) {
54
+ setTemporaryLayout(Object.assign(Object.assign({}, temporaryLayout), { data: temporaryLayout.data.filter(({ i }) => i !== id) }));
55
+ }
56
+ onChange(UpdateManager.removeItem({
57
+ id,
58
+ config: props.config,
59
+ itemsStateAndParams: props.itemsStateAndParams,
60
+ }));
61
+ }
62
+ }, [
63
+ props.config,
64
+ props.itemsStateAndParams,
65
+ temporaryLayout,
66
+ onChange,
67
+ setTemporaryLayout,
68
+ resetTemporaryLayout,
69
+ ]);
50
70
  const onItemStateAndParamsChange = React.useCallback((id, stateAndParams, options) => {
51
71
  onChange({
52
72
  itemsStateAndParams: UpdateManager.changeStateAndParams({
@@ -120,8 +140,57 @@ function useMemoStateContext(props) {
120
140
  const reloadItems = React.useCallback((pluginsRefs, data) => {
121
141
  pluginsRefs.forEach((ref) => ref && ref.reload && ref.reload(data));
122
142
  }, []);
143
+ const dragProps = dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragProps;
144
+ const dragOverPlugin = React.useMemo(() => {
145
+ if (!dragProps) {
146
+ return null;
147
+ }
148
+ const pluginType = dragProps.type;
149
+ if (props.registerManager.check(pluginType)) {
150
+ return props.registerManager.getItem(pluginType);
151
+ }
152
+ else {
153
+ // eslint-disable-next-line no-console
154
+ console.error(`Uknown pluginType: ${pluginType}`);
155
+ return null;
156
+ }
157
+ }, [dragProps, props.registerManager]);
158
+ const onDropDragOver = React.useCallback(() => {
159
+ if (temporaryLayout) {
160
+ resetTemporaryLayout();
161
+ return false;
162
+ }
163
+ if (dragOverPlugin) {
164
+ const { defaultLayout } = dragOverPlugin;
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 || {};
166
+ return { h, w };
167
+ }
168
+ return false;
169
+ }, [resetTemporaryLayout, temporaryLayout, dragOverPlugin, dragProps]);
170
+ const onDrop = React.useCallback((newLayout, item) => {
171
+ if (!dragProps) {
172
+ return;
173
+ }
174
+ setTemporaryLayout({
175
+ data: newLayout,
176
+ dragProps,
177
+ });
178
+ const { i, w, h, x, y } = item;
179
+ props.onDrop({
180
+ newLayout: newLayout.reduce((memo, l) => {
181
+ if (l.i !== i) {
182
+ memo.push({ i: l.i, w: l.w, h: l.h, x: l.x, y: l.y });
183
+ }
184
+ return memo;
185
+ }, []),
186
+ itemLayout: { w, h, x, y },
187
+ commit: resetTemporaryLayout,
188
+ dragProps,
189
+ });
190
+ }, [dragProps, props.onDrop, setTemporaryLayout, resetTemporaryLayout]);
123
191
  return React.useMemo(() => ({
124
192
  layout: resultLayout,
193
+ temporaryLayout,
125
194
  config: props.config,
126
195
  context: props.context,
127
196
  noOverlay: props.noOverlay,
@@ -135,6 +204,8 @@ function useMemoStateContext(props) {
135
204
  registerManager: props.registerManager,
136
205
  onItemStateAndParamsChange,
137
206
  removeItem: onItemRemove,
207
+ onDrop,
208
+ onDropDragOver,
138
209
  editItem: props.onItemEdit,
139
210
  layoutChange: onLayoutChange,
140
211
  getItemsMeta,
@@ -143,8 +214,11 @@ function useMemoStateContext(props) {
143
214
  revertToOriginalLayout,
144
215
  forwardedMetaRef: props.forwardedMetaRef,
145
216
  draggableHandleClassName: props.draggableHandleClassName,
217
+ outerDnDEnable,
218
+ dragOverPlugin,
146
219
  }), [
147
220
  resultLayout,
221
+ temporaryLayout,
148
222
  props.config,
149
223
  props.context,
150
224
  props.noOverlay,
@@ -157,6 +231,8 @@ function useMemoStateContext(props) {
157
231
  props.registerManager,
158
232
  onItemStateAndParamsChange,
159
233
  onItemRemove,
234
+ onDrop,
235
+ onDropDragOver,
160
236
  props.onItemEdit,
161
237
  onLayoutChange,
162
238
  getItemsMeta,
@@ -165,6 +241,8 @@ function useMemoStateContext(props) {
165
241
  revertToOriginalLayout,
166
242
  props.forwardedMetaRef,
167
243
  props.draggableHandleClassName,
244
+ outerDnDEnable,
245
+ dragOverPlugin,
168
246
  ]);
169
247
  }
170
248
  export function withContext(Component) {
@@ -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
+ };
@@ -1,3 +1,4 @@
1
1
  export declare const CURRENT_VERSION = 2;
2
2
  export declare const META_KEY = "__meta__";
3
3
  export declare const ACTION_PARAM_PREFIX = "_ap_";
4
+ export declare const TERMORARY_ITEM_ID = "__dropping-elem__";
@@ -1,3 +1,4 @@
1
1
  export const CURRENT_VERSION = 2;
2
2
  export const META_KEY = '__meta__';
3
3
  export const ACTION_PARAM_PREFIX = '_ap_';
4
+ export const TERMORARY_ITEM_ID = '__dropping-elem__';
@@ -1,5 +1,20 @@
1
+ import { ConfigLayout } from './config';
1
2
  export type Dictionary<T = unknown> = Record<string, T>;
2
3
  export interface StringParams extends Dictionary<string | string[]> {
3
4
  }
4
5
  export interface GlobalParams extends StringParams {
5
6
  }
7
+ export type ItemDragProps = {
8
+ type: string;
9
+ layout?: {
10
+ w?: number;
11
+ h?: number;
12
+ };
13
+ extra?: any;
14
+ };
15
+ export type ItemDropProps = {
16
+ commit: () => void;
17
+ dragProps: ItemDragProps;
18
+ itemLayout: ConfigLayout;
19
+ newLayout: ConfigLayout[];
20
+ };
@@ -8,3 +8,6 @@ export type SetConfigItem = ConfigItem | AddConfigItem;
8
8
  export type SetItemOptions = {
9
9
  excludeIds?: string[];
10
10
  };
11
+ export type SetNewItemOptions = SetItemOptions & {
12
+ updateLayout?: ConfigLayout[];
13
+ };
@@ -36,4 +36,5 @@ export interface PluginDefaultLayout {
36
36
  export interface Plugin<P extends PluginWidgetProps<T> = any, T = StringParams> extends PluginBase {
37
37
  defaultLayout?: PluginDefaultLayout;
38
38
  renderer: (props: P, forwardedRef: React.RefObject<any>) => React.ReactNode;
39
+ placeholderRenderer?: (props: P, forwardedRef: React.RefObject<any>) => React.ReactNode;
39
40
  }
@@ -1,5 +1,5 @@
1
1
  import type { Config, ConfigItem, ItemStateAndParams, ItemStateAndParamsChangeOptions, ItemsStateAndParams } from '../shared';
2
- import type { AddConfigItem, SetItemOptions, WidgetLayout } from '../typings';
2
+ import type { AddConfigItem, SetItemOptions, SetNewItemOptions, WidgetLayout } from '../typings';
3
3
  import { RegisterManagerPluginLayout } from './register-manager';
4
4
  interface RemoveItemArg {
5
5
  id: string;
@@ -19,7 +19,7 @@ export declare class UpdateManager {
19
19
  namespace: string;
20
20
  layout: RegisterManagerPluginLayout;
21
21
  config: Config;
22
- options: SetItemOptions;
22
+ options: SetNewItemOptions;
23
23
  }): Config;
24
24
  static editItem({ item, namespace, config, options, }: {
25
25
  item: ConfigItem;
@@ -212,19 +212,37 @@ function changeGroupParams({ groupItemIds, initiatorId, initiatorItem, itemsStat
212
212
  }
213
213
  export class UpdateManager {
214
214
  static addItem({ item, namespace = DEFAULT_NAMESPACE, layout, config, options, }) {
215
- const layoutY = Math.max(0, ...config.layout.map(({ h, y }) => h + y));
216
- const saveDefaultLayout = pick(layout, ['h', 'w', 'x', 'y']);
217
215
  const salt = config.salt;
218
216
  const newItemData = getNewItemData({ item, config, salt, counter: config.counter, options });
219
217
  let counter = newItemData.counter;
220
218
  const newIdData = getNewId({ config, salt, counter, excludeIds: newItemData.excludeIds });
221
219
  counter = newIdData.counter;
222
220
  const newItem = Object.assign(Object.assign({}, item), { id: newIdData.id, data: newItemData.data, namespace });
223
- return update(config, {
224
- items: { $push: [newItem] },
225
- layout: { $push: [Object.assign(Object.assign({}, saveDefaultLayout), { y: layoutY, i: newItem.id })] },
226
- counter: { $set: counter },
227
- });
221
+ const saveDefaultLayout = pick(layout, ['h', 'w', 'x', 'y']);
222
+ if (options.updateLayout) {
223
+ const byId = options.updateLayout.reduce((memo, t) => {
224
+ memo[t.i] = t;
225
+ return memo;
226
+ }, {});
227
+ const newLayout = [
228
+ ...config.layout.map((t) => (Object.assign(Object.assign({}, t), (byId[t.i] || {})))),
229
+ Object.assign(Object.assign({}, saveDefaultLayout), { i: newItem.id }),
230
+ ];
231
+ return update(config, {
232
+ items: { $push: [newItem] },
233
+ layout: { $set: newLayout },
234
+ counter: { $set: counter },
235
+ });
236
+ }
237
+ else {
238
+ const layoutY = Math.max(0, ...config.layout.map(({ h, y }) => h + y));
239
+ const newLayoutItem = Object.assign(Object.assign({}, saveDefaultLayout), { y: layoutY, i: newItem.id });
240
+ return update(config, {
241
+ items: { $push: [newItem] },
242
+ layout: { $push: [newLayoutItem] },
243
+ counter: { $set: counter },
244
+ });
245
+ }
228
246
  }
229
247
  static editItem({ item, namespace = DEFAULT_NAMESPACE, config, options, }) {
230
248
  const itemIndex = config.items.findIndex(({ id }) => item.id === id);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dashkit",
3
- "version": "8.1.0",
3
+ "version": "8.2.0",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {