@gravity-ui/dashkit 8.5.0-beta.2 → 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 -3
- package/build/cjs/components/GridLayout/GridLayout.js +76 -29
- 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 +106 -21
- 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 -3
- package/build/esm/components/GridLayout/GridLayout.js +76 -29
- 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 +107 -22
- 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,15 +23,24 @@ 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
|
-
caclculateEmptyHorizontalSpace(layout: any, cols: any): any;
|
|
30
|
-
getElementLayout(layout: any, properties: any): any;
|
|
31
44
|
renderGroup(group: any, renderLayout: any, renderItems: any, offset: number | undefined, groupGridProperties: any): JSX.Element;
|
|
32
45
|
render(): any;
|
|
33
46
|
}
|
|
@@ -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,20 +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
|
-
|
|
55
|
-
|
|
56
|
-
if (gridProperties.compactType === constants_1.COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
57
|
-
maxW = this.caclculateEmptyHorizontalSpace(layout, gridProperties.cols);
|
|
58
|
-
}
|
|
59
|
-
if (maxW === 0 || maxH === 0) {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
return onDropDragOver(e, { maxH, maxW });
|
|
117
|
+
const { properties, layout } = this.getLayoutAndPropsByGroup(group);
|
|
118
|
+
return this.context.onDropDragOver(e, properties, layout);
|
|
63
119
|
};
|
|
64
120
|
this._onDrop = (group, newLayout, item, e) => {
|
|
65
121
|
if (!item) {
|
|
@@ -92,6 +148,10 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
92
148
|
componentWillUnmount() {
|
|
93
149
|
clearTimeout(this._timeout);
|
|
94
150
|
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
|
151
|
+
this._memoCallbacksForGroups = {};
|
|
152
|
+
this._memoGroupsProps = {};
|
|
153
|
+
this._memoGroupsLayouts = {};
|
|
154
|
+
this._memoForwardedPluginRef = [];
|
|
95
155
|
}
|
|
96
156
|
getActiveLayout() {
|
|
97
157
|
const { layout, temporaryLayout } = this.context;
|
|
@@ -139,17 +199,6 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
139
199
|
const { type } = temporaryLayout.dragProps;
|
|
140
200
|
return (react_1.default.createElement(GridItem_1.default, { 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), overlayControls: this.props.overlayControls }));
|
|
141
201
|
}
|
|
142
|
-
caclculateEmptyHorizontalSpace(layout, cols) {
|
|
143
|
-
return layout.reduce((memo, item) => memo - item.w, cols);
|
|
144
|
-
}
|
|
145
|
-
getElementLayout(layout, properties) {
|
|
146
|
-
let maxH;
|
|
147
|
-
if (properties.maxRows) {
|
|
148
|
-
maxH = properties.maxRows;
|
|
149
|
-
}
|
|
150
|
-
const leftSpace = this.caclculateEmptyHorizontalSpace(layout, properties.cols);
|
|
151
|
-
return layout.map((item) => (Object.assign(Object.assign({}, item), { maxW: item.w + leftSpace, maxH })));
|
|
152
|
-
}
|
|
153
202
|
renderGroup(group, renderLayout, renderItems, offset = 0, groupGridProperties) {
|
|
154
203
|
const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
|
|
155
204
|
const properties = groupGridProperties
|
|
@@ -157,22 +206,20 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
157
206
|
: registerManager.gridLayout;
|
|
158
207
|
let { compactType } = properties;
|
|
159
208
|
if (compactType === constants_1.COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
160
|
-
renderLayout = this.getElementLayout(renderLayout, properties);
|
|
161
209
|
compactType = 'horizontal';
|
|
162
210
|
}
|
|
163
|
-
|
|
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
|
|
164
213
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
165
214
|
: null), (outerDnDEnable
|
|
166
215
|
? {
|
|
167
216
|
isDroppable: true,
|
|
168
|
-
onDropDragOver:
|
|
169
|
-
onDrop:
|
|
217
|
+
onDropDragOver: callbacks.onDropDragOver,
|
|
218
|
+
onDrop: callbacks.onDrop,
|
|
170
219
|
}
|
|
171
220
|
: null), { draggableCancel: `.${constants_1.OVERLAY_CONTROLS_CLASS_NAME}` }),
|
|
172
221
|
renderItems.map((item, i) => {
|
|
173
|
-
return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: (
|
|
174
|
-
this.pluginsRefs[offset + i] = pluginRef;
|
|
175
|
-
}, 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 }));
|
|
176
223
|
}),
|
|
177
224
|
this.renderTemporaryPlaceholder()));
|
|
178
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,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);
|
|
@@ -52,6 +55,11 @@ function useMemoStateContext(props) {
|
|
|
52
55
|
}
|
|
53
56
|
}, [props.config, onChange]);
|
|
54
57
|
const onItemRemove = react_1.default.useCallback((id) => {
|
|
58
|
+
if (nowrapAdjustedLayouts.current[id]) {
|
|
59
|
+
delete nowrapAdjustedLayouts.current[id];
|
|
60
|
+
delete adjustedLayouts.current[id];
|
|
61
|
+
delete originalLayouts.current[id];
|
|
62
|
+
}
|
|
55
63
|
if (id === common_1.TEMPORARY_ITEM_ID) {
|
|
56
64
|
resetTemporaryLayout();
|
|
57
65
|
}
|
|
@@ -106,7 +114,76 @@ function useMemoStateContext(props) {
|
|
|
106
114
|
forceUpdateLayout((prev) => prev + 1);
|
|
107
115
|
}
|
|
108
116
|
}, []);
|
|
109
|
-
const
|
|
117
|
+
const horizontalNowrapLayoutAdjust = react_1.default.useCallback((groups, layout) => {
|
|
118
|
+
const defaultProps = props.registerManager._gridLayout || {};
|
|
119
|
+
const nowrapGroups = {};
|
|
120
|
+
let hasNowrapGroups = false;
|
|
121
|
+
if (defaultProps.compactType === common_1.COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
122
|
+
nowrapGroups[common_1.DEFAULT_GROUP] = {
|
|
123
|
+
items: [],
|
|
124
|
+
leftSpace: defaultProps.cols,
|
|
125
|
+
};
|
|
126
|
+
hasNowrapGroups = true;
|
|
127
|
+
}
|
|
128
|
+
if (groups) {
|
|
129
|
+
groups.forEach((group) => {
|
|
130
|
+
var _a;
|
|
131
|
+
const resultProps = ((_a = group.gridProperties) === null || _a === void 0 ? void 0 : _a.call(group, defaultProps)) || {};
|
|
132
|
+
if (resultProps.compactType === common_1.COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
133
|
+
nowrapGroups[group.id] = {
|
|
134
|
+
items: [],
|
|
135
|
+
leftSpace: resultProps.cols,
|
|
136
|
+
};
|
|
137
|
+
hasNowrapGroups = true;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (hasNowrapGroups) {
|
|
142
|
+
layout.forEach((item) => {
|
|
143
|
+
const widgetId = item.i;
|
|
144
|
+
const parentId = item.parent || common_1.DEFAULT_GROUP;
|
|
145
|
+
if (nowrapGroups[parentId]) {
|
|
146
|
+
nowrapGroups[parentId].items.push(item);
|
|
147
|
+
nowrapGroups[parentId].leftSpace -= item.w;
|
|
148
|
+
}
|
|
149
|
+
else if (nowrapAdjustedLayouts.current[item.i]) {
|
|
150
|
+
const { originalMaxW } = nowrapAdjustedLayouts.current[widgetId];
|
|
151
|
+
const adjustedItem = adjustedLayouts.current[widgetId];
|
|
152
|
+
if (originalMaxW) {
|
|
153
|
+
adjustedLayouts.current[widgetId] = Object.assign(Object.assign({}, adjustedItem), { maxW: originalMaxW });
|
|
154
|
+
originalLayouts.current[widgetId] = item;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
adjustedLayouts.current[widgetId] = Object.assign({}, adjustedItem);
|
|
158
|
+
}
|
|
159
|
+
delete nowrapAdjustedLayouts.current[widgetId];
|
|
160
|
+
}
|
|
161
|
+
originalLayouts.current[widgetId] = item;
|
|
162
|
+
});
|
|
163
|
+
Object.entries(nowrapGroups).forEach(([, { items, leftSpace }]) => {
|
|
164
|
+
items.forEach((item) => {
|
|
165
|
+
const maxW = item.w + leftSpace;
|
|
166
|
+
if (!adjustedLayouts[item.i] || adjustedLayouts[item.i].maxW > maxW) {
|
|
167
|
+
originalLayouts.current[item.i] = item;
|
|
168
|
+
adjustedLayouts.current[item.i] = Object.assign(Object.assign({}, item), { maxW });
|
|
169
|
+
nowrapAdjustedLayouts.current[item.i] = item.maxW
|
|
170
|
+
? { maxW, originalMaxW: item.maxW }
|
|
171
|
+
: { maxW };
|
|
172
|
+
}
|
|
173
|
+
});
|
|
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
|
+
}
|
|
184
|
+
return adjustedLayouts.current;
|
|
185
|
+
}, [props.registerManager]);
|
|
186
|
+
const itemsParams = (0, useDeepEqualMemo_1.useDeepEqualMemo)(() => (0, shared_1.getItemsParams)({
|
|
110
187
|
defaultGlobalParams: props.defaultGlobalParams,
|
|
111
188
|
globalParams: props.globalParams,
|
|
112
189
|
config: props.config,
|
|
@@ -119,7 +196,7 @@ function useMemoStateContext(props) {
|
|
|
119
196
|
props.itemsStateAndParams,
|
|
120
197
|
props.registerManager,
|
|
121
198
|
]);
|
|
122
|
-
const itemsState =
|
|
199
|
+
const itemsState = (0, useDeepEqualMemo_1.useDeepEqualMemo)(() => (0, shared_1.getItemsState)({
|
|
123
200
|
config: props.config,
|
|
124
201
|
itemsStateAndParams: props.itemsStateAndParams,
|
|
125
202
|
}), [props.config, props.itemsStateAndParams]);
|
|
@@ -134,27 +211,24 @@ function useMemoStateContext(props) {
|
|
|
134
211
|
.filter(Boolean);
|
|
135
212
|
}, []);
|
|
136
213
|
const resultLayout = react_1.default.useMemo(() => {
|
|
214
|
+
const adjusted = horizontalNowrapLayoutAdjust(props.groups, props.layout);
|
|
137
215
|
return props.layout.map((item) => {
|
|
138
|
-
if (item.i in
|
|
216
|
+
if (item.i in adjusted) {
|
|
139
217
|
// eslint-disable-next-line no-unused-vars
|
|
140
|
-
const _a =
|
|
218
|
+
const _a = adjusted[item.i] || {}, { parent } = _a, adjustedItem = tslib_1.__rest(_a, ["parent"]);
|
|
141
219
|
adjustedItem.w = item.w;
|
|
142
220
|
adjustedItem.x = item.x;
|
|
143
221
|
adjustedItem.y = item.y;
|
|
144
222
|
if (item.parent) {
|
|
145
223
|
adjustedItem.parent = item.parent;
|
|
146
224
|
}
|
|
147
|
-
// update originalLayouts memoized item
|
|
148
|
-
if (originalLayouts.current[item.i]) {
|
|
149
|
-
originalLayouts.current[item.i] = item;
|
|
150
|
-
}
|
|
151
225
|
return adjustedItem;
|
|
152
226
|
}
|
|
153
227
|
else {
|
|
154
|
-
return
|
|
228
|
+
return item;
|
|
155
229
|
}
|
|
156
230
|
});
|
|
157
|
-
}, [props.layout, layoutUpdateCounter]);
|
|
231
|
+
}, [props.layout, props.groups, horizontalNowrapLayoutAdjust, layoutUpdateCounter]);
|
|
158
232
|
const reloadItems = react_1.default.useCallback((pluginsRefs, data) => {
|
|
159
233
|
pluginsRefs.forEach((ref) => ref && ref.reload && ref.reload(data));
|
|
160
234
|
}, []);
|
|
@@ -173,20 +247,31 @@ function useMemoStateContext(props) {
|
|
|
173
247
|
return null;
|
|
174
248
|
}
|
|
175
249
|
}, [dragProps, props.registerManager]);
|
|
176
|
-
const onDropDragOver = react_1.default.useCallback((_e, gridProps
|
|
250
|
+
const onDropDragOver = react_1.default.useCallback((_e, gridProps, groupLayout) => {
|
|
177
251
|
if (temporaryLayout) {
|
|
178
252
|
resetTemporaryLayout();
|
|
179
253
|
return false;
|
|
180
254
|
}
|
|
181
|
-
if (dragOverPlugin) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
255
|
+
if (!dragOverPlugin) {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
let maxW = gridProps.cols;
|
|
259
|
+
const { defaultLayout } = dragOverPlugin;
|
|
260
|
+
const maxH = Math.min(gridProps.maxRows || Infinity, defaultLayout.maxH || Infinity);
|
|
261
|
+
if (gridProps.compactType === common_1.COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
262
|
+
maxW = groupLayout.reduce((memo, item) => memo - item.w, gridProps.cols);
|
|
263
|
+
}
|
|
264
|
+
if (maxW === 0 ||
|
|
265
|
+
maxH === 0 ||
|
|
266
|
+
maxW < defaultLayout.minW ||
|
|
267
|
+
maxH < defaultLayout.minH) {
|
|
268
|
+
return false;
|
|
188
269
|
}
|
|
189
|
-
|
|
270
|
+
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 || {};
|
|
271
|
+
return {
|
|
272
|
+
h: maxH ? Math.min(h, maxH) : h,
|
|
273
|
+
w: maxW ? Math.min(w, maxW) : w,
|
|
274
|
+
};
|
|
190
275
|
}, [resetTemporaryLayout, temporaryLayout, dragOverPlugin, dragProps]);
|
|
191
276
|
const onDropProp = props.onDrop;
|
|
192
277
|
const onDrop = react_1.default.useCallback((newLayout, item) => {
|
|
@@ -200,11 +285,11 @@ function useMemoStateContext(props) {
|
|
|
200
285
|
onDropProp({
|
|
201
286
|
newLayout: newLayout.reduce((memo, l) => {
|
|
202
287
|
if (l.i !== item.i) {
|
|
203
|
-
memo.push((0, pick_1.default)(l,
|
|
288
|
+
memo.push((0, pick_1.default)(l, ITEM_PROPS));
|
|
204
289
|
}
|
|
205
290
|
return memo;
|
|
206
291
|
}, []),
|
|
207
|
-
itemLayout: (0, pick_1.default)(item,
|
|
292
|
+
itemLayout: (0, pick_1.default)(item, ITEM_PROPS),
|
|
208
293
|
commit: resetTemporaryLayout,
|
|
209
294
|
dragProps,
|
|
210
295
|
});
|
|
@@ -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,15 +23,24 @@ 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
|
-
caclculateEmptyHorizontalSpace(layout: any, cols: any): any;
|
|
30
|
-
getElementLayout(layout: any, properties: any): any;
|
|
31
44
|
renderGroup(group: any, renderLayout: any, renderItems: any, offset: number | undefined, groupGridProperties: any): JSX.Element;
|
|
32
45
|
render(): any;
|
|
33
46
|
}
|
|
@@ -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,20 +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
|
-
|
|
52
|
-
|
|
53
|
-
if (gridProperties.compactType === COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
54
|
-
maxW = this.caclculateEmptyHorizontalSpace(layout, gridProperties.cols);
|
|
55
|
-
}
|
|
56
|
-
if (maxW === 0 || maxH === 0) {
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
return onDropDragOver(e, { maxH, maxW });
|
|
114
|
+
const { properties, layout } = this.getLayoutAndPropsByGroup(group);
|
|
115
|
+
return this.context.onDropDragOver(e, properties, layout);
|
|
60
116
|
};
|
|
61
117
|
this._onDrop = (group, newLayout, item, e) => {
|
|
62
118
|
if (!item) {
|
|
@@ -89,6 +145,10 @@ class GridLayout extends React.PureComponent {
|
|
|
89
145
|
componentWillUnmount() {
|
|
90
146
|
clearTimeout(this._timeout);
|
|
91
147
|
document.removeEventListener('visibilitychange', this.onVisibilityChange);
|
|
148
|
+
this._memoCallbacksForGroups = {};
|
|
149
|
+
this._memoGroupsProps = {};
|
|
150
|
+
this._memoGroupsLayouts = {};
|
|
151
|
+
this._memoForwardedPluginRef = [];
|
|
92
152
|
}
|
|
93
153
|
getActiveLayout() {
|
|
94
154
|
const { layout, temporaryLayout } = this.context;
|
|
@@ -136,17 +196,6 @@ class GridLayout extends React.PureComponent {
|
|
|
136
196
|
const { type } = temporaryLayout.dragProps;
|
|
137
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), overlayControls: this.props.overlayControls }));
|
|
138
198
|
}
|
|
139
|
-
caclculateEmptyHorizontalSpace(layout, cols) {
|
|
140
|
-
return layout.reduce((memo, item) => memo - item.w, cols);
|
|
141
|
-
}
|
|
142
|
-
getElementLayout(layout, properties) {
|
|
143
|
-
let maxH;
|
|
144
|
-
if (properties.maxRows) {
|
|
145
|
-
maxH = properties.maxRows;
|
|
146
|
-
}
|
|
147
|
-
const leftSpace = this.caclculateEmptyHorizontalSpace(layout, properties.cols);
|
|
148
|
-
return layout.map((item) => (Object.assign(Object.assign({}, item), { maxW: item.w + leftSpace, maxH })));
|
|
149
|
-
}
|
|
150
199
|
renderGroup(group, renderLayout, renderItems, offset = 0, groupGridProperties) {
|
|
151
200
|
const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
|
|
152
201
|
const properties = groupGridProperties
|
|
@@ -154,22 +203,20 @@ class GridLayout extends React.PureComponent {
|
|
|
154
203
|
: registerManager.gridLayout;
|
|
155
204
|
let { compactType } = properties;
|
|
156
205
|
if (compactType === COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
157
|
-
renderLayout = this.getElementLayout(renderLayout, properties);
|
|
158
206
|
compactType = 'horizontal';
|
|
159
207
|
}
|
|
160
|
-
|
|
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
|
|
161
210
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
162
211
|
: null), (outerDnDEnable
|
|
163
212
|
? {
|
|
164
213
|
isDroppable: true,
|
|
165
|
-
onDropDragOver:
|
|
166
|
-
onDrop:
|
|
214
|
+
onDropDragOver: callbacks.onDropDragOver,
|
|
215
|
+
onDrop: callbacks.onDrop,
|
|
167
216
|
}
|
|
168
217
|
: null), { draggableCancel: `.${OVERLAY_CONTROLS_CLASS_NAME}` }),
|
|
169
218
|
renderItems.map((item, i) => {
|
|
170
|
-
return (React.createElement(GridItem, { forwardedPluginRef: (
|
|
171
|
-
this.pluginsRefs[offset + i] = pluginRef;
|
|
172
|
-
}, 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 }));
|
|
173
220
|
}),
|
|
174
221
|
this.renderTemporaryPlaceholder()));
|
|
175
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 = {
|
|
@@ -2,10 +2,12 @@ import { __rest } from "tslib";
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import isEqual from 'lodash/isEqual';
|
|
4
4
|
import pick from 'lodash/pick';
|
|
5
|
-
import { DEFAULT_WIDGET_HEIGHT, DEFAULT_WIDGET_WIDTH, TEMPORARY_ITEM_ID } from '../constants/common';
|
|
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';
|
|
10
|
+
const ITEM_PROPS = ['i', 'h', 'w', 'x', 'y', 'parent'];
|
|
9
11
|
function useMemoStateContext(props) {
|
|
10
12
|
// так как мы не хотим хранить параметры виджета с активированной автовысотой в сторе и на сервере, актуальный
|
|
11
13
|
// (видимый юзером в конкретный момент времени) лэйаут (массив объектов с данными о ширине, высоте,
|
|
@@ -14,6 +16,7 @@ function useMemoStateContext(props) {
|
|
|
14
16
|
// (высота) из конфига будет запоминаться в originalLayouts, новое значение высоты в adjustedLayouts
|
|
15
17
|
const originalLayouts = React.useRef({});
|
|
16
18
|
const adjustedLayouts = React.useRef({});
|
|
19
|
+
const nowrapAdjustedLayouts = React.useRef({});
|
|
17
20
|
const [temporaryLayout, setTemporaryLayout] = React.useState(null);
|
|
18
21
|
const resetTemporaryLayout = React.useCallback(() => setTemporaryLayout(null), [setTemporaryLayout]);
|
|
19
22
|
const dndContext = React.useContext(DashKitDnDContext);
|
|
@@ -49,6 +52,11 @@ function useMemoStateContext(props) {
|
|
|
49
52
|
}
|
|
50
53
|
}, [props.config, onChange]);
|
|
51
54
|
const onItemRemove = React.useCallback((id) => {
|
|
55
|
+
if (nowrapAdjustedLayouts.current[id]) {
|
|
56
|
+
delete nowrapAdjustedLayouts.current[id];
|
|
57
|
+
delete adjustedLayouts.current[id];
|
|
58
|
+
delete originalLayouts.current[id];
|
|
59
|
+
}
|
|
52
60
|
if (id === TEMPORARY_ITEM_ID) {
|
|
53
61
|
resetTemporaryLayout();
|
|
54
62
|
}
|
|
@@ -103,7 +111,76 @@ function useMemoStateContext(props) {
|
|
|
103
111
|
forceUpdateLayout((prev) => prev + 1);
|
|
104
112
|
}
|
|
105
113
|
}, []);
|
|
106
|
-
const
|
|
114
|
+
const horizontalNowrapLayoutAdjust = React.useCallback((groups, layout) => {
|
|
115
|
+
const defaultProps = props.registerManager._gridLayout || {};
|
|
116
|
+
const nowrapGroups = {};
|
|
117
|
+
let hasNowrapGroups = false;
|
|
118
|
+
if (defaultProps.compactType === COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
119
|
+
nowrapGroups[DEFAULT_GROUP] = {
|
|
120
|
+
items: [],
|
|
121
|
+
leftSpace: defaultProps.cols,
|
|
122
|
+
};
|
|
123
|
+
hasNowrapGroups = true;
|
|
124
|
+
}
|
|
125
|
+
if (groups) {
|
|
126
|
+
groups.forEach((group) => {
|
|
127
|
+
var _a;
|
|
128
|
+
const resultProps = ((_a = group.gridProperties) === null || _a === void 0 ? void 0 : _a.call(group, defaultProps)) || {};
|
|
129
|
+
if (resultProps.compactType === COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
130
|
+
nowrapGroups[group.id] = {
|
|
131
|
+
items: [],
|
|
132
|
+
leftSpace: resultProps.cols,
|
|
133
|
+
};
|
|
134
|
+
hasNowrapGroups = true;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
if (hasNowrapGroups) {
|
|
139
|
+
layout.forEach((item) => {
|
|
140
|
+
const widgetId = item.i;
|
|
141
|
+
const parentId = item.parent || DEFAULT_GROUP;
|
|
142
|
+
if (nowrapGroups[parentId]) {
|
|
143
|
+
nowrapGroups[parentId].items.push(item);
|
|
144
|
+
nowrapGroups[parentId].leftSpace -= item.w;
|
|
145
|
+
}
|
|
146
|
+
else if (nowrapAdjustedLayouts.current[item.i]) {
|
|
147
|
+
const { originalMaxW } = nowrapAdjustedLayouts.current[widgetId];
|
|
148
|
+
const adjustedItem = adjustedLayouts.current[widgetId];
|
|
149
|
+
if (originalMaxW) {
|
|
150
|
+
adjustedLayouts.current[widgetId] = Object.assign(Object.assign({}, adjustedItem), { maxW: originalMaxW });
|
|
151
|
+
originalLayouts.current[widgetId] = item;
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
adjustedLayouts.current[widgetId] = Object.assign({}, adjustedItem);
|
|
155
|
+
}
|
|
156
|
+
delete nowrapAdjustedLayouts.current[widgetId];
|
|
157
|
+
}
|
|
158
|
+
originalLayouts.current[widgetId] = item;
|
|
159
|
+
});
|
|
160
|
+
Object.entries(nowrapGroups).forEach(([, { items, leftSpace }]) => {
|
|
161
|
+
items.forEach((item) => {
|
|
162
|
+
const maxW = item.w + leftSpace;
|
|
163
|
+
if (!adjustedLayouts[item.i] || adjustedLayouts[item.i].maxW > maxW) {
|
|
164
|
+
originalLayouts.current[item.i] = item;
|
|
165
|
+
adjustedLayouts.current[item.i] = Object.assign(Object.assign({}, item), { maxW });
|
|
166
|
+
nowrapAdjustedLayouts.current[item.i] = item.maxW
|
|
167
|
+
? { maxW, originalMaxW: item.maxW }
|
|
168
|
+
: { maxW };
|
|
169
|
+
}
|
|
170
|
+
});
|
|
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
|
+
}
|
|
181
|
+
return adjustedLayouts.current;
|
|
182
|
+
}, [props.registerManager]);
|
|
183
|
+
const itemsParams = useDeepEqualMemo(() => getItemsParams({
|
|
107
184
|
defaultGlobalParams: props.defaultGlobalParams,
|
|
108
185
|
globalParams: props.globalParams,
|
|
109
186
|
config: props.config,
|
|
@@ -116,7 +193,7 @@ function useMemoStateContext(props) {
|
|
|
116
193
|
props.itemsStateAndParams,
|
|
117
194
|
props.registerManager,
|
|
118
195
|
]);
|
|
119
|
-
const itemsState =
|
|
196
|
+
const itemsState = useDeepEqualMemo(() => getItemsState({
|
|
120
197
|
config: props.config,
|
|
121
198
|
itemsStateAndParams: props.itemsStateAndParams,
|
|
122
199
|
}), [props.config, props.itemsStateAndParams]);
|
|
@@ -131,27 +208,24 @@ function useMemoStateContext(props) {
|
|
|
131
208
|
.filter(Boolean);
|
|
132
209
|
}, []);
|
|
133
210
|
const resultLayout = React.useMemo(() => {
|
|
211
|
+
const adjusted = horizontalNowrapLayoutAdjust(props.groups, props.layout);
|
|
134
212
|
return props.layout.map((item) => {
|
|
135
|
-
if (item.i in
|
|
213
|
+
if (item.i in adjusted) {
|
|
136
214
|
// eslint-disable-next-line no-unused-vars
|
|
137
|
-
const _a =
|
|
215
|
+
const _a = adjusted[item.i] || {}, { parent } = _a, adjustedItem = __rest(_a, ["parent"]);
|
|
138
216
|
adjustedItem.w = item.w;
|
|
139
217
|
adjustedItem.x = item.x;
|
|
140
218
|
adjustedItem.y = item.y;
|
|
141
219
|
if (item.parent) {
|
|
142
220
|
adjustedItem.parent = item.parent;
|
|
143
221
|
}
|
|
144
|
-
// update originalLayouts memoized item
|
|
145
|
-
if (originalLayouts.current[item.i]) {
|
|
146
|
-
originalLayouts.current[item.i] = item;
|
|
147
|
-
}
|
|
148
222
|
return adjustedItem;
|
|
149
223
|
}
|
|
150
224
|
else {
|
|
151
|
-
return
|
|
225
|
+
return item;
|
|
152
226
|
}
|
|
153
227
|
});
|
|
154
|
-
}, [props.layout, layoutUpdateCounter]);
|
|
228
|
+
}, [props.layout, props.groups, horizontalNowrapLayoutAdjust, layoutUpdateCounter]);
|
|
155
229
|
const reloadItems = React.useCallback((pluginsRefs, data) => {
|
|
156
230
|
pluginsRefs.forEach((ref) => ref && ref.reload && ref.reload(data));
|
|
157
231
|
}, []);
|
|
@@ -170,20 +244,31 @@ function useMemoStateContext(props) {
|
|
|
170
244
|
return null;
|
|
171
245
|
}
|
|
172
246
|
}, [dragProps, props.registerManager]);
|
|
173
|
-
const onDropDragOver = React.useCallback((_e, gridProps
|
|
247
|
+
const onDropDragOver = React.useCallback((_e, gridProps, groupLayout) => {
|
|
174
248
|
if (temporaryLayout) {
|
|
175
249
|
resetTemporaryLayout();
|
|
176
250
|
return false;
|
|
177
251
|
}
|
|
178
|
-
if (dragOverPlugin) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
252
|
+
if (!dragOverPlugin) {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
let maxW = gridProps.cols;
|
|
256
|
+
const { defaultLayout } = dragOverPlugin;
|
|
257
|
+
const maxH = Math.min(gridProps.maxRows || Infinity, defaultLayout.maxH || Infinity);
|
|
258
|
+
if (gridProps.compactType === COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
259
|
+
maxW = groupLayout.reduce((memo, item) => memo - item.w, gridProps.cols);
|
|
260
|
+
}
|
|
261
|
+
if (maxW === 0 ||
|
|
262
|
+
maxH === 0 ||
|
|
263
|
+
maxW < defaultLayout.minW ||
|
|
264
|
+
maxH < defaultLayout.minH) {
|
|
265
|
+
return false;
|
|
185
266
|
}
|
|
186
|
-
|
|
267
|
+
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 || {};
|
|
268
|
+
return {
|
|
269
|
+
h: maxH ? Math.min(h, maxH) : h,
|
|
270
|
+
w: maxW ? Math.min(w, maxW) : w,
|
|
271
|
+
};
|
|
187
272
|
}, [resetTemporaryLayout, temporaryLayout, dragOverPlugin, dragProps]);
|
|
188
273
|
const onDropProp = props.onDrop;
|
|
189
274
|
const onDrop = React.useCallback((newLayout, item) => {
|
|
@@ -197,11 +282,11 @@ function useMemoStateContext(props) {
|
|
|
197
282
|
onDropProp({
|
|
198
283
|
newLayout: newLayout.reduce((memo, l) => {
|
|
199
284
|
if (l.i !== item.i) {
|
|
200
|
-
memo.push(pick(l,
|
|
285
|
+
memo.push(pick(l, ITEM_PROPS));
|
|
201
286
|
}
|
|
202
287
|
return memo;
|
|
203
288
|
}, []),
|
|
204
|
-
itemLayout: pick(item,
|
|
289
|
+
itemLayout: pick(item, ITEM_PROPS),
|
|
205
290
|
commit: resetTemporaryLayout,
|
|
206
291
|
dragProps,
|
|
207
292
|
});
|
|
@@ -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
|
+
};
|