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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +1 -0
  2. package/build/cjs/components/ActionPanel/ActionPanel.d.ts +13 -1
  3. package/build/cjs/components/ActionPanel/ActionPanel.js +25 -6
  4. package/build/cjs/components/DashKit/DashKit.d.ts +10 -3
  5. package/build/cjs/components/DashKit/DashKit.js +2 -0
  6. package/build/cjs/components/DashKitDnDWrapper/DashKitDnDWrapper.d.ts +6 -0
  7. package/build/cjs/components/DashKitDnDWrapper/DashKitDnDWrapper.js +24 -0
  8. package/build/cjs/components/GridItem/GridItem.css +7 -0
  9. package/build/cjs/components/GridItem/GridItem.d.ts +2 -2
  10. package/build/cjs/components/GridItem/GridItem.js +61 -3
  11. package/build/cjs/components/GridLayout/GridLayout.d.ts +2 -0
  12. package/build/cjs/components/GridLayout/GridLayout.js +75 -6
  13. package/build/cjs/components/Item/Item.css +1 -1
  14. package/build/cjs/components/index.d.ts +1 -0
  15. package/build/cjs/components/index.js +1 -0
  16. package/build/cjs/constants/common.d.ts +2 -0
  17. package/build/cjs/constants/common.js +3 -1
  18. package/build/cjs/context/DashKitContext.d.ts +1 -0
  19. package/build/cjs/context/DashKitContext.js +3 -1
  20. package/build/cjs/hocs/withContext.js +87 -6
  21. package/build/cjs/plugins/Text/Text.js +3 -0
  22. package/build/cjs/shared/constants/common.d.ts +1 -0
  23. package/build/cjs/shared/constants/common.js +2 -1
  24. package/build/cjs/typings/config.d.ts +3 -0
  25. package/build/cjs/typings/plugin.d.ts +1 -0
  26. package/build/cjs/utils/update-manager.d.ts +2 -2
  27. package/build/cjs/utils/update-manager.js +25 -7
  28. package/build/esm/components/ActionPanel/ActionPanel.d.ts +13 -1
  29. package/build/esm/components/ActionPanel/ActionPanel.js +23 -5
  30. package/build/esm/components/DashKit/DashKit.d.ts +10 -3
  31. package/build/esm/components/DashKit/DashKit.js +2 -0
  32. package/build/esm/components/DashKitDnDWrapper/DashKitDnDWrapper.d.ts +6 -0
  33. package/build/esm/components/DashKitDnDWrapper/DashKitDnDWrapper.js +19 -0
  34. package/build/esm/components/GridItem/GridItem.css +7 -0
  35. package/build/esm/components/GridItem/GridItem.d.ts +2 -2
  36. package/build/esm/components/GridItem/GridItem.js +61 -3
  37. package/build/esm/components/GridLayout/GridLayout.d.ts +2 -0
  38. package/build/esm/components/GridLayout/GridLayout.js +76 -7
  39. package/build/esm/components/Item/Item.css +1 -1
  40. package/build/esm/components/index.d.ts +1 -0
  41. package/build/esm/components/index.js +1 -0
  42. package/build/esm/constants/common.d.ts +2 -0
  43. package/build/esm/constants/common.js +2 -0
  44. package/build/esm/context/DashKitContext.d.ts +1 -0
  45. package/build/esm/context/DashKitContext.js +2 -1
  46. package/build/esm/hocs/withContext.js +88 -7
  47. package/build/esm/plugins/Text/Text.js +3 -0
  48. package/build/esm/shared/constants/common.d.ts +1 -0
  49. package/build/esm/shared/constants/common.js +1 -0
  50. package/build/esm/typings/config.d.ts +3 -0
  51. package/build/esm/typings/plugin.d.ts +1 -0
  52. package/build/esm/utils/update-manager.d.ts +2 -2
  53. package/build/esm/utils/update-manager.js +25 -7
  54. package/package.json +1 -1
@@ -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 { 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(temporaryLayout.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,11 +140,62 @@ 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 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);
153
+ const dragOverPlugin = React.useMemo(() => {
154
+ const pluginType = dndPluginType;
155
+ if (pluginType === null && temporaryLayout === null)
156
+ return null;
157
+ if (props.registerManager.check(pluginType)) {
158
+ return props.registerManager.getItem(pluginType);
159
+ }
160
+ else {
161
+ // eslint-disable-next-line no-console
162
+ console.error(`Uknown pluginType: ${pluginType}`);
163
+ return null;
164
+ }
165
+ }, [dndPluginType, props.registerManager, temporaryLayout]);
166
+ const onDropDragOver = React.useCallback(() => {
167
+ if (temporaryLayout) {
168
+ resetTemporaryLayout();
169
+ return false;
170
+ }
171
+ if (dragOverPlugin === null || dragOverPlugin === void 0 ? void 0 : dragOverPlugin.defaultLayout) {
172
+ const { h = 3, w = 3 } = dragOverPlugin.defaultLayout;
173
+ return { h, w };
174
+ }
175
+ return false;
176
+ }, [resetTemporaryLayout, temporaryLayout, dragOverPlugin]);
177
+ const onDrop = React.useCallback((newLayout, item) => {
178
+ setTemporaryLayout(newLayout);
179
+ const { i, w, h, x, y } = item;
180
+ props.onDrop({
181
+ newLayout: newLayout.reduce((memo, l) => {
182
+ if (l.i !== i) {
183
+ memo.push({ i: l.i, w: l.w, h: l.h, x: l.x, y: l.y });
184
+ }
185
+ return memo;
186
+ }, []),
187
+ itemLayout: { w, h, x, y },
188
+ pluginType: dndPluginType,
189
+ commit: resetTemporaryLayout,
190
+ });
191
+ }, [dndPluginType, props.onDrop]);
123
192
  return React.useMemo(() => ({
124
193
  layout: resultLayout,
194
+ temporaryLayout,
125
195
  config: props.config,
126
196
  context: props.context,
127
197
  noOverlay: props.noOverlay,
198
+ focusable: props.focusable,
128
199
  defaultGlobalParams: props.globalParams,
129
200
  globalParams: props.globalParams,
130
201
  editMode: props.editMode,
@@ -134,6 +205,8 @@ function useMemoStateContext(props) {
134
205
  registerManager: props.registerManager,
135
206
  onItemStateAndParamsChange,
136
207
  removeItem: onItemRemove,
208
+ onDrop,
209
+ onDropDragOver,
137
210
  editItem: props.onItemEdit,
138
211
  layoutChange: onLayoutChange,
139
212
  getItemsMeta,
@@ -142,11 +215,15 @@ function useMemoStateContext(props) {
142
215
  revertToOriginalLayout,
143
216
  forwardedMetaRef: props.forwardedMetaRef,
144
217
  draggableHandleClassName: props.draggableHandleClassName,
218
+ outerDnDEnable,
219
+ dragOverPlugin,
145
220
  }), [
146
221
  resultLayout,
222
+ temporaryLayout,
147
223
  props.config,
148
224
  props.context,
149
225
  props.noOverlay,
226
+ props.focusable,
150
227
  props.globalParams,
151
228
  props.editMode,
152
229
  props.settings,
@@ -155,6 +232,8 @@ function useMemoStateContext(props) {
155
232
  props.registerManager,
156
233
  onItemStateAndParamsChange,
157
234
  onItemRemove,
235
+ onDrop,
236
+ onDropDragOver,
158
237
  props.onItemEdit,
159
238
  onLayoutChange,
160
239
  getItemsMeta,
@@ -163,6 +242,8 @@ function useMemoStateContext(props) {
163
242
  revertToOriginalLayout,
164
243
  props.forwardedMetaRef,
165
244
  props.draggableHandleClassName,
245
+ outerDnDEnable,
246
+ dragOverPlugin,
166
247
  ]);
167
248
  }
168
249
  export function withContext(Component) {
@@ -113,5 +113,8 @@ 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
+ },
116
119
  };
117
120
  export default plugin;
@@ -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__';
@@ -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.0.2",
3
+ "version": "8.1.0-beta.0",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {