@gravity-ui/dashkit 8.5.0-beta.3 → 8.5.0-beta.4
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/build/cjs/components/GridLayout/GridLayout.d.ts +16 -1
- package/build/cjs/components/GridLayout/GridLayout.js +76 -9
- package/build/cjs/components/Item/Item.d.ts +4 -0
- package/build/cjs/hocs/prepareItem.d.ts +4 -0
- package/build/cjs/hocs/prepareItem.js +33 -22
- package/build/cjs/hocs/withContext.js +12 -3
- package/build/cjs/hooks/useDeepEqualMemo.d.ts +2 -0
- package/build/cjs/hooks/useDeepEqualMemo.js +19 -0
- package/build/esm/components/GridLayout/GridLayout.d.ts +16 -1
- package/build/esm/components/GridLayout/GridLayout.js +76 -9
- package/build/esm/components/Item/Item.d.ts +4 -0
- package/build/esm/hocs/prepareItem.d.ts +4 -0
- package/build/esm/hocs/prepareItem.js +33 -22
- package/build/esm/hocs/withContext.js +12 -3
- package/build/esm/hooks/useDeepEqualMemo.d.ts +2 -0
- package/build/esm/hooks/useDeepEqualMemo.js +14 -0
- package/package.json +1 -1
|
@@ -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: (
|
|
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;
|
|
@@ -9,6 +9,10 @@ const ReactGridLayout_1 = require("./ReactGridLayout");
|
|
|
9
9
|
class GridLayout extends react_1.default.PureComponent {
|
|
10
10
|
constructor(props, context) {
|
|
11
11
|
super(props, context);
|
|
12
|
+
this._memoForwardedPluginRef = [];
|
|
13
|
+
this._memoGroupsProps = {};
|
|
14
|
+
this._memoGroupsLayouts = {};
|
|
15
|
+
this._memoCallbacksForGroups = {};
|
|
12
16
|
this.onVisibilityChange = () => {
|
|
13
17
|
this.setState({
|
|
14
18
|
isPageHidden: document.hidden,
|
|
@@ -30,6 +34,65 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
30
34
|
const { getItemsMeta } = this.context;
|
|
31
35
|
return getItemsMeta(this.pluginsRefs);
|
|
32
36
|
};
|
|
37
|
+
this.getMemoGroupLayout = (group, layout) => {
|
|
38
|
+
// fastest possible way to match json
|
|
39
|
+
const key = JSON.stringify(layout);
|
|
40
|
+
if (this._memoGroupsLayouts[group]) {
|
|
41
|
+
if (this._memoGroupsLayouts[group].key === key) {
|
|
42
|
+
return this._memoGroupsLayouts[group];
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
this._memoGroupsLayouts[group].key = key;
|
|
46
|
+
this._memoGroupsLayouts[group].layout = layout;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
this._memoGroupsLayouts[group] = {
|
|
51
|
+
key,
|
|
52
|
+
layout,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
return this._memoGroupsLayouts[group];
|
|
56
|
+
};
|
|
57
|
+
this.getMemoGroupCallbacks = (group) => {
|
|
58
|
+
if (!this._memoCallbacksForGroups[group]) {
|
|
59
|
+
const onStart = this._onStart;
|
|
60
|
+
const onStop = this._onStop.bind(this, group);
|
|
61
|
+
const onDrop = this._onDrop.bind(this, group);
|
|
62
|
+
const onDropDragOver = this._onDropDragOver.bind(this, group);
|
|
63
|
+
this._memoCallbacksForGroups[group] = {
|
|
64
|
+
onDragStart: onStart,
|
|
65
|
+
onResizeStart: onStart,
|
|
66
|
+
onDragStop: onStop,
|
|
67
|
+
onResizeStop: onStop,
|
|
68
|
+
onDrop: onDrop,
|
|
69
|
+
onDropDragOver,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
return this._memoCallbacksForGroups[group];
|
|
73
|
+
};
|
|
74
|
+
this.getMemoGroupProps = (group, renderLayout, properties) => {
|
|
75
|
+
// Needed for _onDropDragOver
|
|
76
|
+
this._memoGroupsProps[group] = properties;
|
|
77
|
+
return {
|
|
78
|
+
layout: this.getMemoGroupLayout(group, renderLayout).layout,
|
|
79
|
+
callbacks: this.getMemoGroupCallbacks(group),
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
this.getLayoutAndPropsByGroup = (group) => {
|
|
83
|
+
return {
|
|
84
|
+
properties: this._memoGroupsProps[group],
|
|
85
|
+
layout: this._memoGroupsLayouts[group].layout,
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
this.getMemoForwardRefCallback = (refIndex) => {
|
|
89
|
+
if (!this._memoForwardedPluginRef[refIndex]) {
|
|
90
|
+
this._memoForwardedPluginRef[refIndex] = (pluginRef) => {
|
|
91
|
+
this.pluginsRefs[refIndex] = pluginRef;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
return this._memoForwardedPluginRef[refIndex];
|
|
95
|
+
};
|
|
33
96
|
this._onStart = () => {
|
|
34
97
|
if (this.temporaryLayout)
|
|
35
98
|
return;
|
|
@@ -46,12 +109,13 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
46
109
|
}
|
|
47
110
|
this.setState({ isDragging: false });
|
|
48
111
|
};
|
|
49
|
-
this._onDropDragOver = (
|
|
50
|
-
const { editMode, dragOverPlugin
|
|
112
|
+
this._onDropDragOver = (group, e) => {
|
|
113
|
+
const { editMode, dragOverPlugin } = this.context;
|
|
51
114
|
if (!editMode || !dragOverPlugin) {
|
|
52
115
|
return false;
|
|
53
116
|
}
|
|
54
|
-
|
|
117
|
+
const { properties, layout } = this.getLayoutAndPropsByGroup(group);
|
|
118
|
+
return this.context.onDropDragOver(e, properties, layout);
|
|
55
119
|
};
|
|
56
120
|
this._onDrop = (group, newLayout, item, e) => {
|
|
57
121
|
if (!item) {
|
|
@@ -84,6 +148,10 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
84
148
|
componentWillUnmount() {
|
|
85
149
|
clearTimeout(this._timeout);
|
|
86
150
|
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
|
151
|
+
this._memoCallbacksForGroups = {};
|
|
152
|
+
this._memoGroupsProps = {};
|
|
153
|
+
this._memoGroupsLayouts = {};
|
|
154
|
+
this._memoForwardedPluginRef = [];
|
|
87
155
|
}
|
|
88
156
|
getActiveLayout() {
|
|
89
157
|
const { layout, temporaryLayout } = this.context;
|
|
@@ -140,19 +208,18 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
140
208
|
if (compactType === constants_1.COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
141
209
|
compactType = 'horizontal';
|
|
142
210
|
}
|
|
143
|
-
|
|
211
|
+
const { callbacks, layout } = this.getMemoGroupProps(group, renderLayout, properties);
|
|
212
|
+
return (react_1.default.createElement(ReactGridLayout_1.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
|
|
144
213
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
145
214
|
: null), (outerDnDEnable
|
|
146
215
|
? {
|
|
147
216
|
isDroppable: true,
|
|
148
|
-
onDropDragOver:
|
|
149
|
-
onDrop:
|
|
217
|
+
onDropDragOver: callbacks.onDropDragOver,
|
|
218
|
+
onDrop: callbacks.onDrop,
|
|
150
219
|
}
|
|
151
220
|
: null), { draggableCancel: `.${constants_1.OVERLAY_CONTROLS_CLASS_NAME}` }),
|
|
152
221
|
renderItems.map((item, i) => {
|
|
153
|
-
return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: (
|
|
154
|
-
this.pluginsRefs[offset + i] = pluginRef;
|
|
155
|
-
}, 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 }));
|
|
222
|
+
return (react_1.default.createElement(GridItem_1.default, { 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), overlayControls: this.props.overlayControls }));
|
|
156
223
|
}),
|
|
157
224
|
this.renderTemporaryPlaceholder()));
|
|
158
225
|
}
|
|
@@ -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;
|
|
@@ -2,6 +2,8 @@ export function prepareItem(Component: any): {
|
|
|
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 @@ export function prepareItem(Component: any): {
|
|
|
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;
|
|
@@ -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,6 +7,7 @@ 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");
|
|
12
13
|
const ITEM_PROPS = ['i', 'h', 'w', 'x', 'y', 'parent'];
|
|
@@ -154,10 +155,10 @@ function useMemoStateContext(props) {
|
|
|
154
155
|
}
|
|
155
156
|
else {
|
|
156
157
|
adjustedLayouts.current[widgetId] = Object.assign({}, adjustedItem);
|
|
157
|
-
originalLayouts.current[widgetId] = item;
|
|
158
158
|
}
|
|
159
159
|
delete nowrapAdjustedLayouts.current[widgetId];
|
|
160
160
|
}
|
|
161
|
+
originalLayouts.current[widgetId] = item;
|
|
161
162
|
});
|
|
162
163
|
Object.entries(nowrapGroups).forEach(([, { items, leftSpace }]) => {
|
|
163
164
|
items.forEach((item) => {
|
|
@@ -172,9 +173,17 @@ function useMemoStateContext(props) {
|
|
|
172
173
|
});
|
|
173
174
|
});
|
|
174
175
|
}
|
|
176
|
+
else if (groups) {
|
|
177
|
+
layout.forEach((item) => {
|
|
178
|
+
const widgetId = item.i;
|
|
179
|
+
if (adjustedLayouts.current[widgetId]) {
|
|
180
|
+
originalLayouts.current[widgetId] = item;
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
175
184
|
return adjustedLayouts.current;
|
|
176
185
|
}, [props.registerManager]);
|
|
177
|
-
const itemsParams =
|
|
186
|
+
const itemsParams = (0, useDeepEqualMemo_1.useDeepEqualMemo)(() => (0, shared_1.getItemsParams)({
|
|
178
187
|
defaultGlobalParams: props.defaultGlobalParams,
|
|
179
188
|
globalParams: props.globalParams,
|
|
180
189
|
config: props.config,
|
|
@@ -187,7 +196,7 @@ function useMemoStateContext(props) {
|
|
|
187
196
|
props.itemsStateAndParams,
|
|
188
197
|
props.registerManager,
|
|
189
198
|
]);
|
|
190
|
-
const itemsState =
|
|
199
|
+
const itemsState = (0, useDeepEqualMemo_1.useDeepEqualMemo)(() => (0, shared_1.getItemsState)({
|
|
191
200
|
config: props.config,
|
|
192
201
|
itemsStateAndParams: props.itemsStateAndParams,
|
|
193
202
|
}), [props.config, props.itemsStateAndParams]);
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
const callbackRef = react_1.default.useRef(predicate);
|
|
10
|
+
callbackRef.current = predicate;
|
|
11
|
+
return react_1.default.useMemo(() => {
|
|
12
|
+
const value = predicate();
|
|
13
|
+
if (!(0, isEqual_1.default)(previousValueRef.current, value)) {
|
|
14
|
+
previousValueRef.current = value;
|
|
15
|
+
}
|
|
16
|
+
return previousValueRef.current;
|
|
17
|
+
}, [callbackRef, previousValueRef, ...deps]);
|
|
18
|
+
};
|
|
19
|
+
exports.useDeepEqualMemo = useDeepEqualMemo;
|
|
@@ -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: (
|
|
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;
|
|
@@ -6,6 +6,10 @@ 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 = (
|
|
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;
|
|
@@ -137,19 +205,18 @@ class GridLayout extends React.PureComponent {
|
|
|
137
205
|
if (compactType === COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
138
206
|
compactType = 'horizontal';
|
|
139
207
|
}
|
|
140
|
-
|
|
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
|
|
141
210
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
142
211
|
: null), (outerDnDEnable
|
|
143
212
|
? {
|
|
144
213
|
isDroppable: true,
|
|
145
|
-
onDropDragOver:
|
|
146
|
-
onDrop:
|
|
214
|
+
onDropDragOver: callbacks.onDropDragOver,
|
|
215
|
+
onDrop: callbacks.onDrop,
|
|
147
216
|
}
|
|
148
217
|
: null), { draggableCancel: `.${OVERLAY_CONTROLS_CLASS_NAME}` }),
|
|
149
218
|
renderItems.map((item, i) => {
|
|
150
|
-
return (React.createElement(GridItem, { forwardedPluginRef: (
|
|
151
|
-
this.pluginsRefs[offset + i] = pluginRef;
|
|
152
|
-
}, 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), overlayControls: this.props.overlayControls }));
|
|
153
220
|
}),
|
|
154
221
|
this.renderTemporaryPlaceholder()));
|
|
155
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;
|
|
@@ -2,6 +2,8 @@ export function prepareItem(Component: any): {
|
|
|
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 @@ export function prepareItem(Component: any): {
|
|
|
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;
|
|
@@ -9,6 +9,35 @@ export function prepareItem(Component) {
|
|
|
9
9
|
this._onStateAndParamsChange = (stateAndParams, options) => {
|
|
10
10
|
this.context.onItemStateAndParamsChange(this.props.id, stateAndParams, options);
|
|
11
11
|
};
|
|
12
|
+
this._currentRenderProps = {};
|
|
13
|
+
this.getRenderProps = () => {
|
|
14
|
+
const { id, width, height, item, adjustWidgetLayout, layout, isPlaceholder } = this.props;
|
|
15
|
+
const { itemsState, itemsParams, registerManager, settings, context, editMode } = this.context;
|
|
16
|
+
const { data, defaults, namespace } = item;
|
|
17
|
+
const rendererProps = {
|
|
18
|
+
data,
|
|
19
|
+
editMode,
|
|
20
|
+
params: itemsParams[id],
|
|
21
|
+
state: itemsState[id],
|
|
22
|
+
onStateAndParamsChange: this._onStateAndParamsChange,
|
|
23
|
+
width,
|
|
24
|
+
height,
|
|
25
|
+
id,
|
|
26
|
+
defaults,
|
|
27
|
+
namespace,
|
|
28
|
+
settings,
|
|
29
|
+
context,
|
|
30
|
+
layout,
|
|
31
|
+
gridLayout: registerManager.gridLayout,
|
|
32
|
+
adjustWidgetLayout,
|
|
33
|
+
isPlaceholder,
|
|
34
|
+
};
|
|
35
|
+
const changedProp = Object.entries(rendererProps).find(([key, value]) => this._currentRenderProps[key] !== value);
|
|
36
|
+
if (changedProp) {
|
|
37
|
+
this._currentRenderProps = rendererProps;
|
|
38
|
+
}
|
|
39
|
+
return this._currentRenderProps;
|
|
40
|
+
};
|
|
12
41
|
}
|
|
13
42
|
shouldComponentUpdate(nextProps) {
|
|
14
43
|
const { width, height, transform } = this.props;
|
|
@@ -22,28 +51,10 @@ export function prepareItem(Component) {
|
|
|
22
51
|
return true;
|
|
23
52
|
}
|
|
24
53
|
render() {
|
|
25
|
-
const {
|
|
26
|
-
const {
|
|
27
|
-
const { type
|
|
28
|
-
|
|
29
|
-
data,
|
|
30
|
-
editMode,
|
|
31
|
-
params: itemsParams[id],
|
|
32
|
-
state: itemsState[id],
|
|
33
|
-
onStateAndParamsChange: this._onStateAndParamsChange,
|
|
34
|
-
width,
|
|
35
|
-
height,
|
|
36
|
-
id,
|
|
37
|
-
defaults,
|
|
38
|
-
namespace,
|
|
39
|
-
settings,
|
|
40
|
-
context,
|
|
41
|
-
layout,
|
|
42
|
-
gridLayout: registerManager.gridLayout,
|
|
43
|
-
adjustWidgetLayout,
|
|
44
|
-
isPlaceholder,
|
|
45
|
-
};
|
|
46
|
-
return (React.createElement(Component, { forwardedPluginRef: this.props.forwardedPluginRef, rendererProps: rendererProps, registerManager: registerManager, type: type, isPlaceholder: isPlaceholder }));
|
|
54
|
+
const { item, isPlaceholder } = this.props;
|
|
55
|
+
const { registerManager } = this.context;
|
|
56
|
+
const { type } = item;
|
|
57
|
+
return (React.createElement(Component, { forwardedPluginRef: this.props.forwardedPluginRef, rendererProps: this.getRenderProps(), registerManager: registerManager, type: type, isPlaceholder: isPlaceholder }));
|
|
47
58
|
}
|
|
48
59
|
},
|
|
49
60
|
_a.propTypes = {
|
|
@@ -4,6 +4,7 @@ import isEqual from 'lodash/isEqual';
|
|
|
4
4
|
import pick from 'lodash/pick';
|
|
5
5
|
import { COMPACT_TYPE_HORIZONTAL_NOWRAP, DEFAULT_GROUP, DEFAULT_WIDGET_HEIGHT, DEFAULT_WIDGET_WIDTH, TEMPORARY_ITEM_ID, } from '../constants/common';
|
|
6
6
|
import { DashKitContext, DashKitDnDContext } from '../context/DashKitContext';
|
|
7
|
+
import { useDeepEqualMemo } from '../hooks/useDeepEqualMemo';
|
|
7
8
|
import { getItemsParams, getItemsState } from '../shared';
|
|
8
9
|
import { UpdateManager } from '../utils';
|
|
9
10
|
const ITEM_PROPS = ['i', 'h', 'w', 'x', 'y', 'parent'];
|
|
@@ -151,10 +152,10 @@ function useMemoStateContext(props) {
|
|
|
151
152
|
}
|
|
152
153
|
else {
|
|
153
154
|
adjustedLayouts.current[widgetId] = Object.assign({}, adjustedItem);
|
|
154
|
-
originalLayouts.current[widgetId] = item;
|
|
155
155
|
}
|
|
156
156
|
delete nowrapAdjustedLayouts.current[widgetId];
|
|
157
157
|
}
|
|
158
|
+
originalLayouts.current[widgetId] = item;
|
|
158
159
|
});
|
|
159
160
|
Object.entries(nowrapGroups).forEach(([, { items, leftSpace }]) => {
|
|
160
161
|
items.forEach((item) => {
|
|
@@ -169,9 +170,17 @@ function useMemoStateContext(props) {
|
|
|
169
170
|
});
|
|
170
171
|
});
|
|
171
172
|
}
|
|
173
|
+
else if (groups) {
|
|
174
|
+
layout.forEach((item) => {
|
|
175
|
+
const widgetId = item.i;
|
|
176
|
+
if (adjustedLayouts.current[widgetId]) {
|
|
177
|
+
originalLayouts.current[widgetId] = item;
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
172
181
|
return adjustedLayouts.current;
|
|
173
182
|
}, [props.registerManager]);
|
|
174
|
-
const itemsParams =
|
|
183
|
+
const itemsParams = useDeepEqualMemo(() => getItemsParams({
|
|
175
184
|
defaultGlobalParams: props.defaultGlobalParams,
|
|
176
185
|
globalParams: props.globalParams,
|
|
177
186
|
config: props.config,
|
|
@@ -184,7 +193,7 @@ function useMemoStateContext(props) {
|
|
|
184
193
|
props.itemsStateAndParams,
|
|
185
194
|
props.registerManager,
|
|
186
195
|
]);
|
|
187
|
-
const itemsState =
|
|
196
|
+
const itemsState = useDeepEqualMemo(() => getItemsState({
|
|
188
197
|
config: props.config,
|
|
189
198
|
itemsStateAndParams: props.itemsStateAndParams,
|
|
190
199
|
}), [props.config, props.itemsStateAndParams]);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import isEqual from 'lodash/isEqual';
|
|
3
|
+
export const useDeepEqualMemo = (predicate, deps) => {
|
|
4
|
+
const previousValueRef = React.useRef({});
|
|
5
|
+
const callbackRef = React.useRef(predicate);
|
|
6
|
+
callbackRef.current = predicate;
|
|
7
|
+
return React.useMemo(() => {
|
|
8
|
+
const value = predicate();
|
|
9
|
+
if (!isEqual(previousValueRef.current, value)) {
|
|
10
|
+
previousValueRef.current = value;
|
|
11
|
+
}
|
|
12
|
+
return previousValueRef.current;
|
|
13
|
+
}, [callbackRef, previousValueRef, ...deps]);
|
|
14
|
+
};
|