@gravity-ui/dashkit 8.5.0 → 8.7.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.
- package/README.md +11 -4
- package/build/cjs/components/DashKit/DashKit.d.ts +3 -2
- package/build/cjs/components/DashKitView/DashKitView.js +2 -2
- package/build/cjs/components/GridItem/GridItem.js +2 -4
- package/build/cjs/components/GridLayout/GridLayout.d.ts +16 -1
- package/build/cjs/components/GridLayout/GridLayout.js +81 -10
- package/build/cjs/components/Item/Item.d.ts +4 -0
- package/build/cjs/components/OverlayControls/OverlayControls.d.ts +8 -6
- package/build/cjs/components/OverlayControls/OverlayControls.js +58 -42
- package/build/cjs/constants/common.d.ts +1 -0
- package/build/cjs/constants/common.js +2 -1
- package/build/cjs/context/DashKitContext.d.ts +1 -0
- package/build/cjs/context/DashKitContext.js +3 -1
- package/build/cjs/hocs/prepareItem.d.ts +4 -0
- package/build/cjs/hocs/prepareItem.js +33 -22
- package/build/cjs/hocs/withContext.js +129 -21
- package/build/cjs/hooks/useDeepEqualMemo.d.ts +2 -0
- package/build/cjs/hooks/useDeepEqualMemo.js +17 -0
- package/build/cjs/typings/config.d.ts +3 -1
- package/build/esm/components/DashKit/DashKit.d.ts +3 -2
- package/build/esm/components/DashKitView/DashKitView.js +2 -2
- package/build/esm/components/GridItem/GridItem.js +2 -4
- package/build/esm/components/GridLayout/GridLayout.d.ts +16 -1
- package/build/esm/components/GridLayout/GridLayout.js +82 -11
- package/build/esm/components/Item/Item.d.ts +4 -0
- package/build/esm/components/OverlayControls/OverlayControls.d.ts +8 -6
- package/build/esm/components/OverlayControls/OverlayControls.js +59 -43
- package/build/esm/constants/common.d.ts +1 -0
- package/build/esm/constants/common.js +1 -0
- package/build/esm/context/DashKitContext.d.ts +1 -0
- package/build/esm/context/DashKitContext.js +2 -1
- package/build/esm/hocs/prepareItem.d.ts +4 -0
- package/build/esm/hocs/prepareItem.js +33 -22
- package/build/esm/hocs/withContext.js +132 -23
- package/build/esm/hooks/useDeepEqualMemo.d.ts +2 -0
- package/build/esm/hooks/useDeepEqualMemo.js +12 -0
- package/build/esm/typings/config.d.ts +3 -1
- package/package.json +1 -1
|
@@ -13,6 +13,35 @@ function prepareItem(Component) {
|
|
|
13
13
|
this._onStateAndParamsChange = (stateAndParams, options) => {
|
|
14
14
|
this.context.onItemStateAndParamsChange(this.props.id, stateAndParams, options);
|
|
15
15
|
};
|
|
16
|
+
this._currentRenderProps = {};
|
|
17
|
+
this.getRenderProps = () => {
|
|
18
|
+
const { id, width, height, item, adjustWidgetLayout, layout, isPlaceholder } = this.props;
|
|
19
|
+
const { itemsState, itemsParams, registerManager, settings, context, editMode } = this.context;
|
|
20
|
+
const { data, defaults, namespace } = item;
|
|
21
|
+
const rendererProps = {
|
|
22
|
+
data,
|
|
23
|
+
editMode,
|
|
24
|
+
params: itemsParams[id],
|
|
25
|
+
state: itemsState[id],
|
|
26
|
+
onStateAndParamsChange: this._onStateAndParamsChange,
|
|
27
|
+
width,
|
|
28
|
+
height,
|
|
29
|
+
id,
|
|
30
|
+
defaults,
|
|
31
|
+
namespace,
|
|
32
|
+
settings,
|
|
33
|
+
context,
|
|
34
|
+
layout,
|
|
35
|
+
gridLayout: registerManager.gridLayout,
|
|
36
|
+
adjustWidgetLayout,
|
|
37
|
+
isPlaceholder,
|
|
38
|
+
};
|
|
39
|
+
const changedProp = Object.entries(rendererProps).find(([key, value]) => this._currentRenderProps[key] !== value);
|
|
40
|
+
if (changedProp) {
|
|
41
|
+
this._currentRenderProps = rendererProps;
|
|
42
|
+
}
|
|
43
|
+
return this._currentRenderProps;
|
|
44
|
+
};
|
|
16
45
|
}
|
|
17
46
|
shouldComponentUpdate(nextProps) {
|
|
18
47
|
const { width, height, transform } = this.props;
|
|
@@ -26,28 +55,10 @@ function prepareItem(Component) {
|
|
|
26
55
|
return true;
|
|
27
56
|
}
|
|
28
57
|
render() {
|
|
29
|
-
const {
|
|
30
|
-
const {
|
|
31
|
-
const { type
|
|
32
|
-
|
|
33
|
-
data,
|
|
34
|
-
editMode,
|
|
35
|
-
params: itemsParams[id],
|
|
36
|
-
state: itemsState[id],
|
|
37
|
-
onStateAndParamsChange: this._onStateAndParamsChange,
|
|
38
|
-
width,
|
|
39
|
-
height,
|
|
40
|
-
id,
|
|
41
|
-
defaults,
|
|
42
|
-
namespace,
|
|
43
|
-
settings,
|
|
44
|
-
context,
|
|
45
|
-
layout,
|
|
46
|
-
gridLayout: registerManager.gridLayout,
|
|
47
|
-
adjustWidgetLayout,
|
|
48
|
-
isPlaceholder,
|
|
49
|
-
};
|
|
50
|
-
return (react_1.default.createElement(Component, { forwardedPluginRef: this.props.forwardedPluginRef, rendererProps: rendererProps, registerManager: registerManager, type: type, isPlaceholder: isPlaceholder }));
|
|
58
|
+
const { item, isPlaceholder } = this.props;
|
|
59
|
+
const { registerManager } = this.context;
|
|
60
|
+
const { type } = item;
|
|
61
|
+
return (react_1.default.createElement(Component, { forwardedPluginRef: this.props.forwardedPluginRef, rendererProps: this.getRenderProps(), registerManager: registerManager, type: type, isPlaceholder: isPlaceholder }));
|
|
51
62
|
}
|
|
52
63
|
},
|
|
53
64
|
_a.propTypes = {
|
|
@@ -7,8 +7,10 @@ const isEqual_1 = tslib_1.__importDefault(require("lodash/isEqual"));
|
|
|
7
7
|
const pick_1 = tslib_1.__importDefault(require("lodash/pick"));
|
|
8
8
|
const common_1 = require("../constants/common");
|
|
9
9
|
const DashKitContext_1 = require("../context/DashKitContext");
|
|
10
|
+
const useDeepEqualMemo_1 = require("../hooks/useDeepEqualMemo");
|
|
10
11
|
const shared_1 = require("../shared");
|
|
11
12
|
const utils_1 = require("../utils");
|
|
13
|
+
const ITEM_PROPS = ['i', 'h', 'w', 'x', 'y', 'parent'];
|
|
12
14
|
function useMemoStateContext(props) {
|
|
13
15
|
// так как мы не хотим хранить параметры виджета с активированной автовысотой в сторе и на сервере, актуальный
|
|
14
16
|
// (видимый юзером в конкретный момент времени) лэйаут (массив объектов с данными о ширине, высоте,
|
|
@@ -17,6 +19,7 @@ function useMemoStateContext(props) {
|
|
|
17
19
|
// (высота) из конфига будет запоминаться в originalLayouts, новое значение высоты в adjustedLayouts
|
|
18
20
|
const originalLayouts = react_1.default.useRef({});
|
|
19
21
|
const adjustedLayouts = react_1.default.useRef({});
|
|
22
|
+
const nowrapAdjustedLayouts = react_1.default.useRef({});
|
|
20
23
|
const [temporaryLayout, setTemporaryLayout] = react_1.default.useState(null);
|
|
21
24
|
const resetTemporaryLayout = react_1.default.useCallback(() => setTemporaryLayout(null), [setTemporaryLayout]);
|
|
22
25
|
const dndContext = react_1.default.useContext(DashKitContext_1.DashKitDnDContext);
|
|
@@ -51,7 +54,13 @@ function useMemoStateContext(props) {
|
|
|
51
54
|
onChange({ config: newConfig });
|
|
52
55
|
}
|
|
53
56
|
}, [props.config, onChange]);
|
|
57
|
+
const getLayoutItem = react_1.default.useCallback((id) => {
|
|
58
|
+
return props.config.layout.find(({ i }) => i === id);
|
|
59
|
+
}, [props.config.layout]);
|
|
54
60
|
const onItemRemove = react_1.default.useCallback((id) => {
|
|
61
|
+
delete nowrapAdjustedLayouts.current[id];
|
|
62
|
+
delete adjustedLayouts.current[id];
|
|
63
|
+
delete originalLayouts.current[id];
|
|
55
64
|
if (id === common_1.TEMPORARY_ITEM_ID) {
|
|
56
65
|
resetTemporaryLayout();
|
|
57
66
|
}
|
|
@@ -106,7 +115,55 @@ function useMemoStateContext(props) {
|
|
|
106
115
|
forceUpdateLayout((prev) => prev + 1);
|
|
107
116
|
}
|
|
108
117
|
}, []);
|
|
109
|
-
|
|
118
|
+
react_1.default.useMemo(() => {
|
|
119
|
+
const groups = props.groups;
|
|
120
|
+
const layout = props.layout;
|
|
121
|
+
const defaultProps = props.registerManager._gridLayout || {};
|
|
122
|
+
const nowrapGroups = {};
|
|
123
|
+
let hasNowrapGroups = false;
|
|
124
|
+
if (defaultProps.compactType === common_1.COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
125
|
+
nowrapGroups[common_1.DEFAULT_GROUP] = {
|
|
126
|
+
items: [],
|
|
127
|
+
leftSpace: defaultProps.cols,
|
|
128
|
+
};
|
|
129
|
+
hasNowrapGroups = true;
|
|
130
|
+
}
|
|
131
|
+
if (groups) {
|
|
132
|
+
groups.forEach((group) => {
|
|
133
|
+
var _a;
|
|
134
|
+
const resultProps = ((_a = group.gridProperties) === null || _a === void 0 ? void 0 : _a.call(group, defaultProps)) || {};
|
|
135
|
+
if (resultProps.compactType === common_1.COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
136
|
+
nowrapGroups[group.id] = {
|
|
137
|
+
items: [],
|
|
138
|
+
leftSpace: resultProps.cols,
|
|
139
|
+
};
|
|
140
|
+
hasNowrapGroups = true;
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
if (hasNowrapGroups) {
|
|
145
|
+
layout.forEach((item) => {
|
|
146
|
+
const widgetId = item.i;
|
|
147
|
+
const parentId = item.parent || common_1.DEFAULT_GROUP;
|
|
148
|
+
if (nowrapGroups[parentId]) {
|
|
149
|
+
// Collecting nowrap elements
|
|
150
|
+
nowrapGroups[parentId].items.push(item);
|
|
151
|
+
nowrapGroups[parentId].leftSpace -= item.w;
|
|
152
|
+
}
|
|
153
|
+
else if (nowrapAdjustedLayouts.current[widgetId]) {
|
|
154
|
+
// If element is not in horizontal-nowrap cleaning up and reverting adjustLayout values
|
|
155
|
+
delete nowrapAdjustedLayouts.current[widgetId];
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
Object.entries(nowrapGroups).forEach(([, { items, leftSpace }]) => {
|
|
159
|
+
items.forEach((item) => {
|
|
160
|
+
// setting maxW with adjustLayout fields and saving previous
|
|
161
|
+
nowrapAdjustedLayouts.current[item.i] = item.w + leftSpace;
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}, [props.registerManager, props.groups, props.layout]);
|
|
166
|
+
const itemsParams = (0, useDeepEqualMemo_1.useDeepEqualMemo)(() => (0, shared_1.getItemsParams)({
|
|
110
167
|
defaultGlobalParams: props.defaultGlobalParams,
|
|
111
168
|
globalParams: props.globalParams,
|
|
112
169
|
config: props.config,
|
|
@@ -119,7 +176,7 @@ function useMemoStateContext(props) {
|
|
|
119
176
|
props.itemsStateAndParams,
|
|
120
177
|
props.registerManager,
|
|
121
178
|
]);
|
|
122
|
-
const itemsState =
|
|
179
|
+
const itemsState = (0, useDeepEqualMemo_1.useDeepEqualMemo)(() => (0, shared_1.getItemsState)({
|
|
123
180
|
config: props.config,
|
|
124
181
|
itemsStateAndParams: props.itemsStateAndParams,
|
|
125
182
|
}), [props.config, props.itemsStateAndParams]);
|
|
@@ -134,12 +191,31 @@ function useMemoStateContext(props) {
|
|
|
134
191
|
.filter(Boolean);
|
|
135
192
|
}, []);
|
|
136
193
|
const resultLayout = react_1.default.useMemo(() => {
|
|
194
|
+
const adjusted = adjustedLayouts.current;
|
|
195
|
+
const original = originalLayouts.current;
|
|
196
|
+
const nowrapAdjust = nowrapAdjustedLayouts.current;
|
|
137
197
|
return props.layout.map((item) => {
|
|
138
|
-
|
|
139
|
-
|
|
198
|
+
const widgetId = item.i;
|
|
199
|
+
if (widgetId in adjusted || widgetId in nowrapAdjust) {
|
|
200
|
+
original[widgetId] = item;
|
|
201
|
+
// eslint-disable-next-line no-unused-vars
|
|
202
|
+
const _a = adjusted[widgetId] || item, { parent } = _a, adjustedItem = tslib_1.__rest(_a, ["parent"]);
|
|
203
|
+
adjustedItem.w = item.w;
|
|
204
|
+
adjustedItem.x = item.x;
|
|
205
|
+
adjustedItem.y = item.y;
|
|
206
|
+
if (item.parent) {
|
|
207
|
+
adjustedItem.parent = item.parent;
|
|
208
|
+
}
|
|
209
|
+
if (widgetId in nowrapAdjust) {
|
|
210
|
+
adjustedItem.maxW = nowrapAdjust[widgetId];
|
|
211
|
+
}
|
|
212
|
+
return adjustedItem;
|
|
140
213
|
}
|
|
141
214
|
else {
|
|
142
|
-
|
|
215
|
+
if (widgetId in original) {
|
|
216
|
+
delete original[widgetId];
|
|
217
|
+
}
|
|
218
|
+
return item;
|
|
143
219
|
}
|
|
144
220
|
});
|
|
145
221
|
}, [props.layout, layoutUpdateCounter]);
|
|
@@ -161,17 +237,31 @@ function useMemoStateContext(props) {
|
|
|
161
237
|
return null;
|
|
162
238
|
}
|
|
163
239
|
}, [dragProps, props.registerManager]);
|
|
164
|
-
const onDropDragOver = react_1.default.useCallback(() => {
|
|
240
|
+
const onDropDragOver = react_1.default.useCallback((_e, gridProps, groupLayout) => {
|
|
165
241
|
if (temporaryLayout) {
|
|
166
242
|
resetTemporaryLayout();
|
|
167
243
|
return false;
|
|
168
244
|
}
|
|
169
|
-
if (dragOverPlugin) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
245
|
+
if (!dragOverPlugin) {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
let maxW = gridProps.cols;
|
|
249
|
+
const { defaultLayout } = dragOverPlugin;
|
|
250
|
+
const maxH = Math.min(gridProps.maxRows || Infinity, defaultLayout.maxH || Infinity);
|
|
251
|
+
if (gridProps.compactType === common_1.COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
252
|
+
maxW = groupLayout.reduce((memo, item) => memo - item.w, gridProps.cols);
|
|
253
|
+
}
|
|
254
|
+
if (maxW === 0 ||
|
|
255
|
+
maxH === 0 ||
|
|
256
|
+
maxW < defaultLayout.minW ||
|
|
257
|
+
maxH < defaultLayout.minH) {
|
|
258
|
+
return false;
|
|
173
259
|
}
|
|
174
|
-
|
|
260
|
+
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 || {};
|
|
261
|
+
return {
|
|
262
|
+
h: maxH ? Math.min(h, maxH) : h,
|
|
263
|
+
w: maxW ? Math.min(w, maxW) : w,
|
|
264
|
+
};
|
|
175
265
|
}, [resetTemporaryLayout, temporaryLayout, dragOverPlugin, dragProps]);
|
|
176
266
|
const onDropProp = props.onDrop;
|
|
177
267
|
const onDrop = react_1.default.useCallback((newLayout, item) => {
|
|
@@ -185,16 +275,16 @@ function useMemoStateContext(props) {
|
|
|
185
275
|
onDropProp({
|
|
186
276
|
newLayout: newLayout.reduce((memo, l) => {
|
|
187
277
|
if (l.i !== item.i) {
|
|
188
|
-
memo.push((0, pick_1.default)(l,
|
|
278
|
+
memo.push((0, pick_1.default)(l, ITEM_PROPS));
|
|
189
279
|
}
|
|
190
280
|
return memo;
|
|
191
281
|
}, []),
|
|
192
|
-
itemLayout: (0, pick_1.default)(item,
|
|
282
|
+
itemLayout: (0, pick_1.default)(item, ITEM_PROPS),
|
|
193
283
|
commit: resetTemporaryLayout,
|
|
194
284
|
dragProps,
|
|
195
285
|
});
|
|
196
286
|
}, [dragProps, onDropProp, setTemporaryLayout, resetTemporaryLayout]);
|
|
197
|
-
|
|
287
|
+
const dashkitContextValue = react_1.default.useMemo(() => ({
|
|
198
288
|
layout: resultLayout,
|
|
199
289
|
temporaryLayout,
|
|
200
290
|
config: props.config,
|
|
@@ -210,10 +300,8 @@ function useMemoStateContext(props) {
|
|
|
210
300
|
itemsParams,
|
|
211
301
|
registerManager: props.registerManager,
|
|
212
302
|
onItemStateAndParamsChange,
|
|
213
|
-
removeItem: onItemRemove,
|
|
214
303
|
onDrop,
|
|
215
304
|
onDropDragOver,
|
|
216
|
-
editItem: props.onItemEdit,
|
|
217
305
|
layoutChange: onLayoutChange,
|
|
218
306
|
getItemsMeta,
|
|
219
307
|
reloadItems,
|
|
@@ -238,10 +326,8 @@ function useMemoStateContext(props) {
|
|
|
238
326
|
itemsParams,
|
|
239
327
|
props.registerManager,
|
|
240
328
|
onItemStateAndParamsChange,
|
|
241
|
-
onItemRemove,
|
|
242
329
|
onDrop,
|
|
243
330
|
onDropDragOver,
|
|
244
|
-
props.onItemEdit,
|
|
245
331
|
onLayoutChange,
|
|
246
332
|
getItemsMeta,
|
|
247
333
|
reloadItems,
|
|
@@ -252,12 +338,34 @@ function useMemoStateContext(props) {
|
|
|
252
338
|
outerDnDEnable,
|
|
253
339
|
dragOverPlugin,
|
|
254
340
|
]);
|
|
341
|
+
const overlayMenuItems = props.overlayMenuItems || props.registerManager.settings.menu;
|
|
342
|
+
const controlsContextValue = react_1.default.useMemo(() => ({
|
|
343
|
+
overlayControls: props.overlayControls,
|
|
344
|
+
context: props.context,
|
|
345
|
+
menu: overlayMenuItems,
|
|
346
|
+
itemsParams: itemsParams,
|
|
347
|
+
itemsState: itemsState,
|
|
348
|
+
editItem: props.onItemEdit,
|
|
349
|
+
removeItem: onItemRemove,
|
|
350
|
+
getLayoutItem: getLayoutItem,
|
|
351
|
+
}), [
|
|
352
|
+
itemsParams,
|
|
353
|
+
itemsState,
|
|
354
|
+
props.context,
|
|
355
|
+
props.onItemEdit,
|
|
356
|
+
onItemRemove,
|
|
357
|
+
props.overlayControls,
|
|
358
|
+
overlayMenuItems,
|
|
359
|
+
getLayoutItem,
|
|
360
|
+
]);
|
|
361
|
+
return { controlsContextValue, dashkitContextValue };
|
|
255
362
|
}
|
|
256
363
|
function withContext(Component) {
|
|
257
364
|
const WithContext = (props) => {
|
|
258
|
-
const
|
|
259
|
-
return (react_1.default.createElement(DashKitContext_1.DashKitContext.Provider, { value:
|
|
260
|
-
react_1.default.createElement(
|
|
365
|
+
const { dashkitContextValue, controlsContextValue } = useMemoStateContext(props);
|
|
366
|
+
return (react_1.default.createElement(DashKitContext_1.DashKitContext.Provider, { value: dashkitContextValue },
|
|
367
|
+
react_1.default.createElement(DashKitContext_1.DashkitOvelayControlsContext.Provider, { value: controlsContextValue },
|
|
368
|
+
react_1.default.createElement(Component, null))));
|
|
261
369
|
};
|
|
262
370
|
WithContext.displayName = `withContext(${Component.displayName || Component.name || 'Component'}`;
|
|
263
371
|
return WithContext;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useDeepEqualMemo = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const react_1 = tslib_1.__importDefault(require("react"));
|
|
6
|
+
const isEqual_1 = tslib_1.__importDefault(require("lodash/isEqual"));
|
|
7
|
+
const useDeepEqualMemo = (predicate, deps) => {
|
|
8
|
+
const previousValueRef = react_1.default.useRef({});
|
|
9
|
+
return react_1.default.useMemo(() => {
|
|
10
|
+
const value = predicate();
|
|
11
|
+
if (!(0, isEqual_1.default)(previousValueRef.current, value)) {
|
|
12
|
+
previousValueRef.current = value;
|
|
13
|
+
}
|
|
14
|
+
return previousValueRef.current;
|
|
15
|
+
}, [previousValueRef, ...deps]);
|
|
16
|
+
};
|
|
17
|
+
exports.useDeepEqualMemo = useDeepEqualMemo;
|
|
@@ -19,7 +19,9 @@ export interface DashkitGroupRenderProps {
|
|
|
19
19
|
items: ConfigItem[];
|
|
20
20
|
layout: ConfigLayout[];
|
|
21
21
|
}
|
|
22
|
-
export type ReactGridLayoutProps = Omit<ReactGridLayout.ReactGridLayoutProps, 'children' | 'innerRef' | 'key' | 'layout' | 'isDraggable' | 'isResizable' | 'onDragStart' | 'onDragStop' | 'onResizeStart' | 'onResizeStop' | 'draggableHandle' | 'isDroppable' | 'onDropDragOver' | 'onDrop' | 'draggableCancel'
|
|
22
|
+
export type ReactGridLayoutProps = Omit<ReactGridLayout.ReactGridLayoutProps, 'children' | 'compactType' | 'innerRef' | 'key' | 'layout' | 'isDraggable' | 'isResizable' | 'onDragStart' | 'onDragStop' | 'onResizeStart' | 'onResizeStop' | 'draggableHandle' | 'isDroppable' | 'onDropDragOver' | 'onDrop' | 'draggableCancel'> & {
|
|
23
|
+
compactType?: ReactGridLayout.ReactGridLayoutProps['compactType'] | 'horizontal-nowrap';
|
|
24
|
+
};
|
|
23
25
|
export interface DashKitGroup {
|
|
24
26
|
id?: string;
|
|
25
27
|
render?: (id: string, children: React.ReactNode, props: DashkitGroupRenderProps) => React.ReactNode;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { Config, ConfigItem, GlobalParams, ItemDropProps, ItemsStateAndParams } from '../../shared';
|
|
3
|
-
import { ContextProps, DashKitGroup, Plugin, SetConfigItem, SetNewItemOptions, Settings, SettingsProps } from '../../typings';
|
|
3
|
+
import { ContextProps, DashKitGroup, MenuItem, Plugin, SetConfigItem, SetNewItemOptions, Settings, SettingsProps } from '../../typings';
|
|
4
4
|
import GridLayout from '../GridLayout/GridLayout';
|
|
5
5
|
import { OverlayControlItem } from '../OverlayControls/OverlayControls';
|
|
6
6
|
interface DashKitGeneralProps {
|
|
7
7
|
config: Config;
|
|
8
8
|
editMode: boolean;
|
|
9
9
|
draggableHandleClassName?: string;
|
|
10
|
-
overlayControls?: Record<string, OverlayControlItem[]
|
|
10
|
+
overlayControls?: Record<string, OverlayControlItem[]> | null;
|
|
11
|
+
overlayMenuItems?: MenuItem[] | null;
|
|
11
12
|
}
|
|
12
13
|
interface DashKitDefaultProps {
|
|
13
14
|
onItemEdit: (item: ConfigItem) => void;
|
|
@@ -7,10 +7,10 @@ import GridLayout from '../GridLayout/GridLayout';
|
|
|
7
7
|
import MobileLayout from '../MobileLayout/MobileLayout';
|
|
8
8
|
import './DashKitView.css';
|
|
9
9
|
const b = cn('dashkit');
|
|
10
|
-
function DashKitView(
|
|
10
|
+
function DashKitView() {
|
|
11
11
|
const context = React.useContext(DashKitContext);
|
|
12
12
|
const { registerManager, forwardedMetaRef } = context;
|
|
13
|
-
return (React.createElement("div", { className: b({ theme: registerManager.settings.theme }) }, registerManager.settings.isMobile ? (React.createElement(MobileLayout, null)) : (React.createElement(GridLayout, { ref: forwardedMetaRef
|
|
13
|
+
return (React.createElement("div", { className: b({ theme: registerManager.settings.theme }) }, registerManager.settings.isMobile ? (React.createElement(MobileLayout, null)) : (React.createElement(GridLayout, { ref: forwardedMetaRef }))));
|
|
14
14
|
}
|
|
15
15
|
const DashKitViewWithContext = withContext(DashKitView);
|
|
16
16
|
const DashKitViewForwardedMeta = React.forwardRef((props, ref) => {
|
|
@@ -56,16 +56,15 @@ class GridItem extends React.PureComponent {
|
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
renderOverlay() {
|
|
59
|
-
const {
|
|
59
|
+
const { isPlaceholder } = this.props;
|
|
60
60
|
const { editMode } = this.context;
|
|
61
61
|
if (!editMode || this.props.item.data._editActive || isPlaceholder) {
|
|
62
62
|
return null;
|
|
63
63
|
}
|
|
64
64
|
const { item } = this.props;
|
|
65
|
-
const controls = overlayControls && overlayControls[item.type];
|
|
66
65
|
return (React.createElement(React.Fragment, null,
|
|
67
66
|
React.createElement("div", { className: b('overlay') }),
|
|
68
|
-
React.createElement(OverlayControls, { configItem: item
|
|
67
|
+
React.createElement(OverlayControls, { configItem: item })));
|
|
69
68
|
}
|
|
70
69
|
render() {
|
|
71
70
|
// из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
|
|
@@ -106,7 +105,6 @@ GridItem.propTypes = {
|
|
|
106
105
|
item: PropTypes.object,
|
|
107
106
|
isDragging: PropTypes.bool,
|
|
108
107
|
layout: PropTypes.array,
|
|
109
|
-
overlayControls: PropTypes.object,
|
|
110
108
|
forwardedRef: PropTypes.any,
|
|
111
109
|
forwardedPluginRef: PropTypes.any,
|
|
112
110
|
isPlaceholder: PropTypes.bool,
|
|
@@ -9,6 +9,10 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
|
|
|
9
9
|
componentDidMount(): void;
|
|
10
10
|
componentDidUpdate(): void;
|
|
11
11
|
componentWillUnmount(): void;
|
|
12
|
+
_memoCallbacksForGroups: {};
|
|
13
|
+
_memoGroupsProps: {};
|
|
14
|
+
_memoGroupsLayouts: {};
|
|
15
|
+
_memoForwardedPluginRef: any[];
|
|
12
16
|
_timeout: any;
|
|
13
17
|
_lastReloadAt: any;
|
|
14
18
|
onVisibilityChange: () => void;
|
|
@@ -19,11 +23,22 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
|
|
|
19
23
|
}) => void;
|
|
20
24
|
getItemsMeta: () => any;
|
|
21
25
|
getActiveLayout(): any;
|
|
26
|
+
getMemoGroupLayout: (group: any, layout: any) => any;
|
|
27
|
+
getMemoGroupCallbacks: (group: any) => any;
|
|
28
|
+
getMemoGroupProps: (group: any, renderLayout: any, properties: any) => {
|
|
29
|
+
layout: any;
|
|
30
|
+
callbacks: any;
|
|
31
|
+
};
|
|
32
|
+
getLayoutAndPropsByGroup: (group: any) => {
|
|
33
|
+
properties: any;
|
|
34
|
+
layout: any;
|
|
35
|
+
};
|
|
36
|
+
getMemoForwardRefCallback: (refIndex: any) => any;
|
|
22
37
|
mergeGroupsLayout(group: any, newLayout: any, temporaryItem: any): any;
|
|
23
38
|
reloadItems(): void;
|
|
24
39
|
_onStart: () => void;
|
|
25
40
|
_onStop: (group: any, newLayout: any) => void;
|
|
26
|
-
_onDropDragOver: (e: any) => any;
|
|
41
|
+
_onDropDragOver: (group: any, e: any) => any;
|
|
27
42
|
_onDrop: (group: any, newLayout: any, item: any, e: any) => false | undefined;
|
|
28
43
|
renderTemporaryPlaceholder(): JSX.Element | null;
|
|
29
44
|
renderGroup(group: any, renderLayout: any, renderItems: any, offset: number | undefined, groupGridProperties: any): JSX.Element;
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { DEFAULT_GROUP, OVERLAY_CONTROLS_CLASS_NAME, TEMPORARY_ITEM_ID } from '../../constants';
|
|
2
|
+
import { COMPACT_TYPE_HORIZONTAL_NOWRAP, DEFAULT_GROUP, OVERLAY_CONTROLS_CLASS_NAME, TEMPORARY_ITEM_ID, } from '../../constants';
|
|
3
3
|
import { DashKitContext } from '../../context/DashKitContext';
|
|
4
4
|
import GridItem from '../GridItem/GridItem';
|
|
5
5
|
import { Layout } from './ReactGridLayout';
|
|
6
6
|
class GridLayout extends React.PureComponent {
|
|
7
7
|
constructor(props, context) {
|
|
8
8
|
super(props, context);
|
|
9
|
+
this._memoForwardedPluginRef = [];
|
|
10
|
+
this._memoGroupsProps = {};
|
|
11
|
+
this._memoGroupsLayouts = {};
|
|
12
|
+
this._memoCallbacksForGroups = {};
|
|
9
13
|
this.onVisibilityChange = () => {
|
|
10
14
|
this.setState({
|
|
11
15
|
isPageHidden: document.hidden,
|
|
@@ -27,6 +31,65 @@ class GridLayout extends React.PureComponent {
|
|
|
27
31
|
const { getItemsMeta } = this.context;
|
|
28
32
|
return getItemsMeta(this.pluginsRefs);
|
|
29
33
|
};
|
|
34
|
+
this.getMemoGroupLayout = (group, layout) => {
|
|
35
|
+
// fastest possible way to match json
|
|
36
|
+
const key = JSON.stringify(layout);
|
|
37
|
+
if (this._memoGroupsLayouts[group]) {
|
|
38
|
+
if (this._memoGroupsLayouts[group].key === key) {
|
|
39
|
+
return this._memoGroupsLayouts[group];
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
this._memoGroupsLayouts[group].key = key;
|
|
43
|
+
this._memoGroupsLayouts[group].layout = layout;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
this._memoGroupsLayouts[group] = {
|
|
48
|
+
key,
|
|
49
|
+
layout,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return this._memoGroupsLayouts[group];
|
|
53
|
+
};
|
|
54
|
+
this.getMemoGroupCallbacks = (group) => {
|
|
55
|
+
if (!this._memoCallbacksForGroups[group]) {
|
|
56
|
+
const onStart = this._onStart;
|
|
57
|
+
const onStop = this._onStop.bind(this, group);
|
|
58
|
+
const onDrop = this._onDrop.bind(this, group);
|
|
59
|
+
const onDropDragOver = this._onDropDragOver.bind(this, group);
|
|
60
|
+
this._memoCallbacksForGroups[group] = {
|
|
61
|
+
onDragStart: onStart,
|
|
62
|
+
onResizeStart: onStart,
|
|
63
|
+
onDragStop: onStop,
|
|
64
|
+
onResizeStop: onStop,
|
|
65
|
+
onDrop: onDrop,
|
|
66
|
+
onDropDragOver,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return this._memoCallbacksForGroups[group];
|
|
70
|
+
};
|
|
71
|
+
this.getMemoGroupProps = (group, renderLayout, properties) => {
|
|
72
|
+
// Needed for _onDropDragOver
|
|
73
|
+
this._memoGroupsProps[group] = properties;
|
|
74
|
+
return {
|
|
75
|
+
layout: this.getMemoGroupLayout(group, renderLayout).layout,
|
|
76
|
+
callbacks: this.getMemoGroupCallbacks(group),
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
this.getLayoutAndPropsByGroup = (group) => {
|
|
80
|
+
return {
|
|
81
|
+
properties: this._memoGroupsProps[group],
|
|
82
|
+
layout: this._memoGroupsLayouts[group].layout,
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
this.getMemoForwardRefCallback = (refIndex) => {
|
|
86
|
+
if (!this._memoForwardedPluginRef[refIndex]) {
|
|
87
|
+
this._memoForwardedPluginRef[refIndex] = (pluginRef) => {
|
|
88
|
+
this.pluginsRefs[refIndex] = pluginRef;
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return this._memoForwardedPluginRef[refIndex];
|
|
92
|
+
};
|
|
30
93
|
this._onStart = () => {
|
|
31
94
|
if (this.temporaryLayout)
|
|
32
95
|
return;
|
|
@@ -43,12 +106,13 @@ class GridLayout extends React.PureComponent {
|
|
|
43
106
|
}
|
|
44
107
|
this.setState({ isDragging: false });
|
|
45
108
|
};
|
|
46
|
-
this._onDropDragOver = (e) => {
|
|
47
|
-
const { editMode, dragOverPlugin
|
|
109
|
+
this._onDropDragOver = (group, e) => {
|
|
110
|
+
const { editMode, dragOverPlugin } = this.context;
|
|
48
111
|
if (!editMode || !dragOverPlugin) {
|
|
49
112
|
return false;
|
|
50
113
|
}
|
|
51
|
-
|
|
114
|
+
const { properties, layout } = this.getLayoutAndPropsByGroup(group);
|
|
115
|
+
return this.context.onDropDragOver(e, properties, layout);
|
|
52
116
|
};
|
|
53
117
|
this._onDrop = (group, newLayout, item, e) => {
|
|
54
118
|
if (!item) {
|
|
@@ -81,6 +145,10 @@ class GridLayout extends React.PureComponent {
|
|
|
81
145
|
componentWillUnmount() {
|
|
82
146
|
clearTimeout(this._timeout);
|
|
83
147
|
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
|
148
|
+
this._memoCallbacksForGroups = {};
|
|
149
|
+
this._memoGroupsProps = {};
|
|
150
|
+
this._memoGroupsLayouts = {};
|
|
151
|
+
this._memoForwardedPluginRef = [];
|
|
84
152
|
}
|
|
85
153
|
getActiveLayout() {
|
|
86
154
|
const { layout, temporaryLayout } = this.context;
|
|
@@ -126,26 +194,29 @@ class GridLayout extends React.PureComponent {
|
|
|
126
194
|
}
|
|
127
195
|
const id = TEMPORARY_ITEM_ID;
|
|
128
196
|
const { type } = temporaryLayout.dragProps;
|
|
129
|
-
return (React.createElement(GridItem, { key: id, id: id, item: { id, type, data: {} }, layout: temporaryLayout.data, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, isPlaceholder: true, noOverlay: noOverlay, withCustomHandle: Boolean(draggableHandleClassName)
|
|
197
|
+
return (React.createElement(GridItem, { key: id, id: id, item: { id, type, data: {} }, layout: temporaryLayout.data, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, isPlaceholder: true, noOverlay: noOverlay, withCustomHandle: Boolean(draggableHandleClassName) }));
|
|
130
198
|
}
|
|
131
199
|
renderGroup(group, renderLayout, renderItems, offset = 0, groupGridProperties) {
|
|
132
200
|
const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
|
|
133
201
|
const properties = groupGridProperties
|
|
134
202
|
? groupGridProperties(Object.assign({}, registerManager.gridLayout))
|
|
135
203
|
: registerManager.gridLayout;
|
|
136
|
-
|
|
204
|
+
let { compactType } = properties;
|
|
205
|
+
if (compactType === COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
206
|
+
compactType = 'horizontal';
|
|
207
|
+
}
|
|
208
|
+
const { callbacks, layout } = this.getMemoGroupProps(group, renderLayout, properties);
|
|
209
|
+
return (React.createElement(Layout, Object.assign({}, properties, { compactType: compactType, layout: layout, key: `group_${group}`, isDraggable: editMode, isResizable: editMode, onDragStart: callbacks.onDragStart, onDragStop: callbacks.onDragStop, onResizeStart: callbacks.onResizeStart, onResizeStop: callbacks.onResizeStop }, (draggableHandleClassName
|
|
137
210
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
138
211
|
: null), (outerDnDEnable
|
|
139
212
|
? {
|
|
140
213
|
isDroppable: true,
|
|
141
|
-
onDropDragOver:
|
|
142
|
-
onDrop:
|
|
214
|
+
onDropDragOver: callbacks.onDropDragOver,
|
|
215
|
+
onDrop: callbacks.onDrop,
|
|
143
216
|
}
|
|
144
217
|
: null), { draggableCancel: `.${OVERLAY_CONTROLS_CLASS_NAME}` }),
|
|
145
218
|
renderItems.map((item, i) => {
|
|
146
|
-
return (React.createElement(GridItem, { forwardedPluginRef: (
|
|
147
|
-
this.pluginsRefs[offset + i] = pluginRef;
|
|
148
|
-
}, key: item.id, id: item.id, item: item, layout: renderLayout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
|
|
219
|
+
return (React.createElement(GridItem, { forwardedPluginRef: this.getMemoForwardRefCallback(offset + i), key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName) }));
|
|
149
220
|
}),
|
|
150
221
|
this.renderTemporaryPlaceholder()));
|
|
151
222
|
}
|
|
@@ -2,6 +2,8 @@ declare const _default: {
|
|
|
2
2
|
new (props: any): {
|
|
3
3
|
shouldComponentUpdate(nextProps: any): boolean;
|
|
4
4
|
_onStateAndParamsChange: (stateAndParams: any, options: any) => void;
|
|
5
|
+
_currentRenderProps: {};
|
|
6
|
+
getRenderProps: () => {};
|
|
5
7
|
render(): JSX.Element;
|
|
6
8
|
context: unknown;
|
|
7
9
|
setState<K extends string | number | symbol>(state: any, callback?: (() => void) | undefined): void;
|
|
@@ -26,6 +28,8 @@ declare const _default: {
|
|
|
26
28
|
new (props: any, context: any): {
|
|
27
29
|
shouldComponentUpdate(nextProps: any): boolean;
|
|
28
30
|
_onStateAndParamsChange: (stateAndParams: any, options: any) => void;
|
|
31
|
+
_currentRenderProps: {};
|
|
32
|
+
getRenderProps: () => {};
|
|
29
33
|
render(): JSX.Element;
|
|
30
34
|
context: unknown;
|
|
31
35
|
setState<K extends string | number | symbol>(state: any, callback?: (() => void) | undefined): void;
|