@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
package/README.md
CHANGED
|
@@ -35,7 +35,8 @@ interface DashKitProps {
|
|
|
35
35
|
itemsStateAndParams: ItemsStateAndParams;
|
|
36
36
|
settings: SettingsProps;
|
|
37
37
|
context: ContextProps;
|
|
38
|
-
overlayControls?: Record<string, OverlayControlItem[]
|
|
38
|
+
overlayControls?: Record<string, OverlayControlItem[]> | null;
|
|
39
|
+
overlayMenuItems?: MenuItems[] | null;
|
|
39
40
|
noOverlay?: boolean;
|
|
40
41
|
focusable?: boolean;
|
|
41
42
|
draggableHandleClassName?: string;
|
|
@@ -51,7 +52,8 @@ interface DashKitProps {
|
|
|
51
52
|
- **itemsStateAndParams**: [itemsStateAndParams](#temsStateAndParams).
|
|
52
53
|
- **settings**: DashKit settings.
|
|
53
54
|
- **context**: Object that will be propped up on all widgets.
|
|
54
|
-
- **overlayControls**: Object that overrides widget controls at the time of editing. If not transmitted, basic controls will be displayed.
|
|
55
|
+
- **overlayControls**: Object that overrides widget controls at the time of editing. If not transmitted, basic controls will be displayed. If `null` passed only close button or custom menu will be displayed.
|
|
56
|
+
- **overlayMenuItems**: Custom dropdown menu items
|
|
55
57
|
- **noOverlay**: If `true`, overlay and controls are not displayed while editing.
|
|
56
58
|
- **focusable**: If `true`, grid items will be focusable.
|
|
57
59
|
- **draggableHandleClassName** : СSS class name of the element that makes the widget draggable.
|
|
@@ -343,6 +345,10 @@ type MenuItem = {
|
|
|
343
345
|
};
|
|
344
346
|
|
|
345
347
|
// use array of menu items in settings
|
|
348
|
+
<Dashkit overlayMenuItems={[] as Array<MenuItem> | null} />
|
|
349
|
+
|
|
350
|
+
[deprecated]
|
|
351
|
+
// overlayMenuItems property has greater priority over setSettings menu
|
|
346
352
|
DashKit.setSettings({menu: [] as Array<MenuItem>});
|
|
347
353
|
```
|
|
348
354
|
|
|
@@ -386,7 +392,7 @@ type ItemDropProps = {
|
|
|
386
392
|
#### Example:
|
|
387
393
|
|
|
388
394
|
```jsx
|
|
389
|
-
const
|
|
395
|
+
const overlayMenuItems = [
|
|
390
396
|
{
|
|
391
397
|
id: 'chart',
|
|
392
398
|
icon: <Icon data={ChartColumn} />,
|
|
@@ -405,7 +411,7 @@ const onDrop = (dropProps: ItemDropProps) => {
|
|
|
405
411
|
|
|
406
412
|
<DashKitDnDWrapper>
|
|
407
413
|
<DashKit editMode={true} config={config} onChange={onChange} onDrop={onDrop} />
|
|
408
|
-
<ActionPanel items={
|
|
414
|
+
<ActionPanel items={overlayMenuItems} />
|
|
409
415
|
</DashKitDnDWrapper>
|
|
410
416
|
```
|
|
411
417
|
|
|
@@ -475,6 +481,7 @@ const CustomThemeWrapper = (props: {
|
|
|
475
481
|
By default, storybook runs on `http://localhost:7120/`.
|
|
476
482
|
New changes from a project aren't always picked up when storybook is running, so it's better to rebuild a project manually and restart storybook.
|
|
477
483
|
|
|
484
|
+
|
|
478
485
|
### Example of an nginx config for development on a dev machine
|
|
479
486
|
|
|
480
487
|
```bash
|
|
@@ -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;
|
|
@@ -9,10 +9,10 @@ const cn_1 = require("../../utils/cn");
|
|
|
9
9
|
const GridLayout_1 = tslib_1.__importDefault(require("../GridLayout/GridLayout"));
|
|
10
10
|
const MobileLayout_1 = tslib_1.__importDefault(require("../MobileLayout/MobileLayout"));
|
|
11
11
|
const b = (0, cn_1.cn)('dashkit');
|
|
12
|
-
function DashKitView(
|
|
12
|
+
function DashKitView() {
|
|
13
13
|
const context = react_1.default.useContext(DashKitContext_1.DashKitContext);
|
|
14
14
|
const { registerManager, forwardedMetaRef } = context;
|
|
15
|
-
return (react_1.default.createElement("div", { className: b({ theme: registerManager.settings.theme }) }, registerManager.settings.isMobile ? (react_1.default.createElement(MobileLayout_1.default, null)) : (react_1.default.createElement(GridLayout_1.default, { ref: forwardedMetaRef
|
|
15
|
+
return (react_1.default.createElement("div", { className: b({ theme: registerManager.settings.theme }) }, registerManager.settings.isMobile ? (react_1.default.createElement(MobileLayout_1.default, null)) : (react_1.default.createElement(GridLayout_1.default, { ref: forwardedMetaRef }))));
|
|
16
16
|
}
|
|
17
17
|
const DashKitViewWithContext = (0, withContext_1.withContext)(DashKitView);
|
|
18
18
|
const DashKitViewForwardedMeta = react_1.default.forwardRef((props, ref) => {
|
|
@@ -58,16 +58,15 @@ class GridItem extends react_1.default.PureComponent {
|
|
|
58
58
|
};
|
|
59
59
|
}
|
|
60
60
|
renderOverlay() {
|
|
61
|
-
const {
|
|
61
|
+
const { isPlaceholder } = this.props;
|
|
62
62
|
const { editMode } = this.context;
|
|
63
63
|
if (!editMode || this.props.item.data._editActive || isPlaceholder) {
|
|
64
64
|
return null;
|
|
65
65
|
}
|
|
66
66
|
const { item } = this.props;
|
|
67
|
-
const controls = overlayControls && overlayControls[item.type];
|
|
68
67
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
69
68
|
react_1.default.createElement("div", { className: b('overlay') }),
|
|
70
|
-
react_1.default.createElement(OverlayControls_1.default, { configItem: item
|
|
69
|
+
react_1.default.createElement(OverlayControls_1.default, { configItem: item })));
|
|
71
70
|
}
|
|
72
71
|
render() {
|
|
73
72
|
// из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
|
|
@@ -108,7 +107,6 @@ GridItem.propTypes = {
|
|
|
108
107
|
item: prop_types_1.default.object,
|
|
109
108
|
isDragging: prop_types_1.default.bool,
|
|
110
109
|
layout: prop_types_1.default.array,
|
|
111
|
-
overlayControls: prop_types_1.default.object,
|
|
112
110
|
forwardedRef: prop_types_1.default.any,
|
|
113
111
|
forwardedPluginRef: prop_types_1.default.any,
|
|
114
112
|
isPlaceholder: prop_types_1.default.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;
|
|
@@ -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 = (e) => {
|
|
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;
|
|
@@ -129,26 +197,29 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
129
197
|
}
|
|
130
198
|
const id = constants_1.TEMPORARY_ITEM_ID;
|
|
131
199
|
const { type } = temporaryLayout.dragProps;
|
|
132
|
-
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)
|
|
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) }));
|
|
133
201
|
}
|
|
134
202
|
renderGroup(group, renderLayout, renderItems, offset = 0, groupGridProperties) {
|
|
135
203
|
const { registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
|
|
136
204
|
const properties = groupGridProperties
|
|
137
205
|
? groupGridProperties(Object.assign({}, registerManager.gridLayout))
|
|
138
206
|
: registerManager.gridLayout;
|
|
139
|
-
|
|
207
|
+
let { compactType } = properties;
|
|
208
|
+
if (compactType === constants_1.COMPACT_TYPE_HORIZONTAL_NOWRAP) {
|
|
209
|
+
compactType = 'horizontal';
|
|
210
|
+
}
|
|
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
|
|
140
213
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
141
214
|
: null), (outerDnDEnable
|
|
142
215
|
? {
|
|
143
216
|
isDroppable: true,
|
|
144
|
-
onDropDragOver:
|
|
145
|
-
onDrop:
|
|
217
|
+
onDropDragOver: callbacks.onDropDragOver,
|
|
218
|
+
onDrop: callbacks.onDrop,
|
|
146
219
|
}
|
|
147
220
|
: null), { draggableCancel: `.${constants_1.OVERLAY_CONTROLS_CLASS_NAME}` }),
|
|
148
221
|
renderItems.map((item, i) => {
|
|
149
|
-
return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: (
|
|
150
|
-
this.pluginsRefs[offset + i] = pluginRef;
|
|
151
|
-
}, 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) }));
|
|
152
223
|
}),
|
|
153
224
|
this.renderTemporaryPlaceholder()));
|
|
154
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;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ButtonSize, ButtonView, IconProps, MenuItemProps } from '@gravity-ui/uikit';
|
|
3
|
-
import type {
|
|
4
|
-
import
|
|
3
|
+
import type { ConfigItem, ConfigLayout, ItemState, PluginBase, StringParams } from '../../shared';
|
|
4
|
+
import { MenuItem } from '../../typings';
|
|
5
5
|
export declare enum OverlayControlsPosition {
|
|
6
6
|
TopRight = "top_right",
|
|
7
7
|
TopLeft = "top_left",
|
|
@@ -13,6 +13,7 @@ export interface OverlayControlItem {
|
|
|
13
13
|
icon?: IconProps['data'];
|
|
14
14
|
iconSize?: number | string;
|
|
15
15
|
handler?: (item: ConfigItem) => void;
|
|
16
|
+
visible?: (item: ConfigItem) => boolean;
|
|
16
17
|
allWidgetsControls?: boolean;
|
|
17
18
|
excludeWidgetsTypes?: Array<PluginBase['type']>;
|
|
18
19
|
id?: string;
|
|
@@ -35,8 +36,6 @@ interface OverlayControlsDefaultProps {
|
|
|
35
36
|
}
|
|
36
37
|
interface OverlayControlsProps extends OverlayControlsDefaultProps {
|
|
37
38
|
configItem: ConfigItem;
|
|
38
|
-
items?: OverlayControlItem[];
|
|
39
|
-
overlayControls?: Record<string, OverlayControlItem[]>;
|
|
40
39
|
}
|
|
41
40
|
type PreparedCopyItemOptionsArg = Pick<ConfigItem, 'data' | 'type' | 'defaults' | 'namespace'> & {
|
|
42
41
|
timestamp: number;
|
|
@@ -49,21 +48,24 @@ export type PreparedCopyItemOptions<C extends object = {}> = PreparedCopyItemOpt
|
|
|
49
48
|
copyContext?: C;
|
|
50
49
|
};
|
|
51
50
|
type DashKitCtx = React.Context<{
|
|
51
|
+
overlayControls?: Record<string, OverlayControlItem[]>;
|
|
52
52
|
context: Record<string, any>;
|
|
53
|
-
|
|
53
|
+
menu: MenuItem[];
|
|
54
54
|
itemsParams: Record<string, StringParams>;
|
|
55
55
|
itemsState: Record<string, ItemState>;
|
|
56
56
|
editItem: (item: ConfigItem) => void;
|
|
57
57
|
removeItem: (id: string) => void;
|
|
58
|
-
|
|
58
|
+
getLayoutItem: (id: string) => ConfigLayout | void;
|
|
59
59
|
}>;
|
|
60
60
|
declare class OverlayControls extends React.Component<OverlayControlsProps> {
|
|
61
61
|
static contextType: React.Context<any>;
|
|
62
62
|
static defaultProps: OverlayControlsDefaultProps;
|
|
63
63
|
context: React.ContextType<DashKitCtx>;
|
|
64
64
|
render(): JSX.Element;
|
|
65
|
+
private getItems;
|
|
65
66
|
private renderControlsItem;
|
|
66
67
|
private getDropDownMenuItemConfig;
|
|
68
|
+
private getDefaultControls;
|
|
67
69
|
private renderControls;
|
|
68
70
|
private renderMenu;
|
|
69
71
|
private isDefaultMenu;
|
|
@@ -24,6 +24,11 @@ const DEFAULT_DROPDOWN_MENU = [constants_1.MenuItems.Copy, constants_1.MenuItems
|
|
|
24
24
|
class OverlayControls extends react_1.default.Component {
|
|
25
25
|
constructor() {
|
|
26
26
|
super(...arguments);
|
|
27
|
+
this.getItems = () => {
|
|
28
|
+
const { overlayControls } = this.context;
|
|
29
|
+
const { configItem } = this.props;
|
|
30
|
+
return (overlayControls && overlayControls[configItem.type]) || [];
|
|
31
|
+
};
|
|
27
32
|
this.renderControlsItem = (item, index, length) => {
|
|
28
33
|
const { view, size } = this.props;
|
|
29
34
|
const { title, handler, icon, iconSize, qa } = item;
|
|
@@ -31,18 +36,28 @@ class OverlayControls extends react_1.default.Component {
|
|
|
31
36
|
return (react_1.default.createElement(uikit_1.Button, { key: index, view: view, size: size, title: title, pin: this.getControlItemPinStyle(index, length), onClick: () => onItemClickHandler(this.props.configItem), qa: qa },
|
|
32
37
|
react_1.default.createElement(uikit_1.Icon, { data: icon || CogIcon_1.CogIcon, size: icon ? iconSize : 24 })));
|
|
33
38
|
};
|
|
39
|
+
this.getDefaultControls = () => {
|
|
40
|
+
const { view, size } = this.props;
|
|
41
|
+
if (this.context.overlayControls === null) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return (react_1.default.createElement(uikit_1.Button, { view: view, size: size, title: (0, i18n_1.i18n)('label_settings'), pin: "round-brick", onClick: this.onEditItem, qa: "dashkit-overlay-control-settings" },
|
|
45
|
+
react_1.default.createElement(uikit_1.Icon, { data: CogIcon_1.CogIcon, size: "24" })));
|
|
46
|
+
};
|
|
34
47
|
this.getCustomLeftOverlayControls = () => {
|
|
35
48
|
// выбираем только items-ы у которых проставлено поле `allWidgetsControls:true`
|
|
36
49
|
// те контролы, которые будут показываться слева от меню
|
|
37
50
|
let controls = [];
|
|
38
|
-
for (const controlItem of Object.values(this.
|
|
51
|
+
for (const controlItem of Object.values(this.context.overlayControls || {})) {
|
|
39
52
|
controls = controls.concat((controlItem.filter((item) => {
|
|
40
53
|
var _a;
|
|
41
54
|
// если тип виджета-плагина в списке исключаемых, то не показываем такой контрол
|
|
42
55
|
if ((_a = item.excludeWidgetsTypes) === null || _a === void 0 ? void 0 : _a.includes(this.props.configItem.type)) {
|
|
43
56
|
return false;
|
|
44
57
|
}
|
|
45
|
-
return item.
|
|
58
|
+
return item.visible
|
|
59
|
+
? item.visible(this.props.configItem)
|
|
60
|
+
: item.allWidgetsControls;
|
|
46
61
|
}) || []).map((item) => {
|
|
47
62
|
var _a;
|
|
48
63
|
if (!(item === null || item === void 0 ? void 0 : item.id)) {
|
|
@@ -57,15 +72,14 @@ class OverlayControls extends react_1.default.Component {
|
|
|
57
72
|
};
|
|
58
73
|
this.onCopyItem = () => {
|
|
59
74
|
var _a;
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
});
|
|
75
|
+
const { configItem } = this.props;
|
|
76
|
+
const correspondedItemLayout = this.context.getLayoutItem(configItem.id);
|
|
63
77
|
let options = {
|
|
64
78
|
timestamp: Date.now(),
|
|
65
|
-
data:
|
|
66
|
-
type:
|
|
67
|
-
defaults:
|
|
68
|
-
namespace:
|
|
79
|
+
data: configItem.data,
|
|
80
|
+
type: configItem.type,
|
|
81
|
+
defaults: configItem.defaults,
|
|
82
|
+
namespace: configItem.namespace,
|
|
69
83
|
layout: {
|
|
70
84
|
w: correspondedItemLayout.w,
|
|
71
85
|
h: correspondedItemLayout.h,
|
|
@@ -87,7 +101,8 @@ class OverlayControls extends react_1.default.Component {
|
|
|
87
101
|
};
|
|
88
102
|
}
|
|
89
103
|
render() {
|
|
90
|
-
const {
|
|
104
|
+
const { position } = this.props;
|
|
105
|
+
const items = this.getItems();
|
|
91
106
|
const hasCustomControlsWithWidgets = items.length > 0;
|
|
92
107
|
const controls = hasCustomControlsWithWidgets
|
|
93
108
|
? this.getCustomControlsWithWidgets()
|
|
@@ -122,11 +137,9 @@ class OverlayControls extends react_1.default.Component {
|
|
|
122
137
|
return null;
|
|
123
138
|
}
|
|
124
139
|
renderControls() {
|
|
125
|
-
const { view, size } = this.props;
|
|
126
140
|
const customLeftControls = this.getCustomLeftOverlayControls();
|
|
127
141
|
const hasCustomOverlayLeftControls = Boolean(customLeftControls.length);
|
|
128
|
-
const defaultControl =
|
|
129
|
-
react_1.default.createElement(uikit_1.Icon, { data: CogIcon_1.CogIcon, size: "24" })));
|
|
142
|
+
const defaultControl = this.getDefaultControls();
|
|
130
143
|
const controls = hasCustomOverlayLeftControls
|
|
131
144
|
? customLeftControls.map((item, index, items) => this.renderControlsItem(item, index, items.length + 1))
|
|
132
145
|
: defaultControl;
|
|
@@ -139,50 +152,58 @@ class OverlayControls extends react_1.default.Component {
|
|
|
139
152
|
}
|
|
140
153
|
renderMenu() {
|
|
141
154
|
const { view, size } = this.props;
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
155
|
+
const dropdown = this.renderDropdownMenu();
|
|
156
|
+
if (dropdown) {
|
|
157
|
+
return dropdown;
|
|
158
|
+
}
|
|
159
|
+
return (react_1.default.createElement(uikit_1.Button, { key: 'delete-control', view: view, size: size, title: (0, i18n_1.i18n)('label_delete'), pin: "brick-round", onClick: this.onRemoveItem, qa: "dashkit-overlay-control-menu" },
|
|
160
|
+
react_1.default.createElement(uikit_1.Icon, { data: CloseIcon_1.CloseIcon, size: "12" })));
|
|
146
161
|
}
|
|
147
162
|
isDefaultMenu(menu) {
|
|
148
163
|
return menu === null || menu === void 0 ? void 0 : menu.every((item) => Object.values(constants_1.MenuItems).includes(String(item)));
|
|
149
164
|
}
|
|
150
165
|
renderDropdownMenu() {
|
|
151
166
|
const { view, size } = this.props;
|
|
152
|
-
const {
|
|
167
|
+
const { menu: contextMenu, itemsParams, itemsState } = this.context;
|
|
153
168
|
const configItem = this.props.configItem;
|
|
154
169
|
const itemParams = itemsParams[configItem.id];
|
|
155
170
|
const itemState = itemsState[configItem.id];
|
|
156
|
-
|
|
157
|
-
if (!menu.length) {
|
|
158
|
-
menu = DEFAULT_DROPDOWN_MENU;
|
|
159
|
-
}
|
|
171
|
+
const menu = (contextMenu === null || contextMenu === void 0 ? void 0 : contextMenu.length) > 0 ? contextMenu : DEFAULT_DROPDOWN_MENU;
|
|
160
172
|
const isDefaultMenu = this.isDefaultMenu(menu);
|
|
161
|
-
|
|
162
|
-
? (menu || []).
|
|
163
|
-
|
|
173
|
+
const items = isDefaultMenu
|
|
174
|
+
? (menu || []).reduce((memo, name) => {
|
|
175
|
+
const item = this.getDropDownMenuItemConfig(name, true);
|
|
176
|
+
if (item) {
|
|
177
|
+
memo.push(item);
|
|
178
|
+
}
|
|
179
|
+
return memo;
|
|
180
|
+
}, [])
|
|
181
|
+
: menu.reduce((memo, item) => {
|
|
164
182
|
var _a;
|
|
165
183
|
if (typeof item === 'string') {
|
|
166
|
-
return
|
|
184
|
+
return memo;
|
|
167
185
|
}
|
|
168
186
|
// custom menu dropdown item filter
|
|
169
187
|
if (item.visible && !item.visible(configItem)) {
|
|
170
|
-
return
|
|
188
|
+
return memo;
|
|
171
189
|
}
|
|
172
190
|
const itemHandler = item.handler;
|
|
173
191
|
const itemAction = typeof itemHandler === 'function'
|
|
174
192
|
? () => itemHandler(configItem, itemParams, itemState)
|
|
175
193
|
: ((_a = this.getDropDownMenuItemConfig(item.id)) === null || _a === void 0 ? void 0 : _a.action) || (() => { });
|
|
176
|
-
|
|
194
|
+
memo.push({
|
|
177
195
|
// @ts-expect-error
|
|
178
196
|
text: item.title || (0, i18n_1.i18n)(item.id),
|
|
179
197
|
icon: item.icon,
|
|
180
198
|
action: itemAction,
|
|
181
199
|
className: item.className,
|
|
182
200
|
qa: item.qa,
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
|
|
201
|
+
});
|
|
202
|
+
return memo;
|
|
203
|
+
}, []);
|
|
204
|
+
if (items.length === 0) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
186
207
|
return (react_1.default.createElement(uikit_1.DropdownMenu, { items: items, renderSwitcher: (props) => (react_1.default.createElement(uikit_1.Button, Object.assign({}, props, { view: view, size: size, pin: "brick-round", qa: "dashkit-overlay-control-menu" }),
|
|
187
208
|
react_1.default.createElement(uikit_1.Icon, { data: DotsIcon_1.DotsIcon, size: "16" }))) }));
|
|
188
209
|
}
|
|
@@ -202,19 +223,14 @@ class OverlayControls extends react_1.default.Component {
|
|
|
202
223
|
return 'brick-brick';
|
|
203
224
|
}
|
|
204
225
|
getCustomControlsWithWidgets() {
|
|
205
|
-
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
handler: this.onRemoveItem,
|
|
211
|
-
};
|
|
212
|
-
const { items = [] } = this.props;
|
|
213
|
-
const customOverlayControls = [...items, deleteControl];
|
|
214
|
-
return customOverlayControls.map((item, index, controlItems) => this.renderControlsItem(item, index, controlItems.length));
|
|
226
|
+
const items = this.getItems();
|
|
227
|
+
const result = items.map((item, index, controlItems) => this.renderControlsItem(item, index, controlItems.length));
|
|
228
|
+
// Добавляем контрол удаления или меню виджета по умолчанию
|
|
229
|
+
result.push(this.renderMenu());
|
|
230
|
+
return result;
|
|
215
231
|
}
|
|
216
232
|
}
|
|
217
|
-
OverlayControls.contextType = DashKitContext_1.
|
|
233
|
+
OverlayControls.contextType = DashKitContext_1.DashkitOvelayControlsContext;
|
|
218
234
|
OverlayControls.defaultProps = {
|
|
219
235
|
position: OverlayControlsPosition.TopRight,
|
|
220
236
|
view: 'flat',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_GROUP = exports.DEFAULT_WIDGET_WIDTH = exports.DEFAULT_WIDGET_HEIGHT = exports.MenuItems = exports.TEMPORARY_ITEM_ID = exports.OVERLAY_CLASS_NAME = exports.OVERLAY_CONTROLS_CLASS_NAME = exports.DEFAULT_NAMESPACE = exports.COPIED_WIDGET_STORE_KEY = void 0;
|
|
3
|
+
exports.COMPACT_TYPE_HORIZONTAL_NOWRAP = exports.DEFAULT_GROUP = exports.DEFAULT_WIDGET_WIDTH = exports.DEFAULT_WIDGET_HEIGHT = exports.MenuItems = exports.TEMPORARY_ITEM_ID = exports.OVERLAY_CLASS_NAME = exports.OVERLAY_CONTROLS_CLASS_NAME = exports.DEFAULT_NAMESPACE = exports.COPIED_WIDGET_STORE_KEY = void 0;
|
|
4
4
|
exports.COPIED_WIDGET_STORE_KEY = 'dashCopiedItem';
|
|
5
5
|
exports.DEFAULT_NAMESPACE = 'default';
|
|
6
6
|
exports.OVERLAY_CONTROLS_CLASS_NAME = 'dashkit-overlay-controls';
|
|
@@ -14,3 +14,4 @@ exports.MenuItems = {
|
|
|
14
14
|
exports.DEFAULT_WIDGET_HEIGHT = 3;
|
|
15
15
|
exports.DEFAULT_WIDGET_WIDTH = 3;
|
|
16
16
|
exports.DEFAULT_GROUP = '__default';
|
|
17
|
+
exports.COMPACT_TYPE_HORIZONTAL_NOWRAP = 'horizontal-nowrap';
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DashKitDnDContext = exports.DashKitContext = void 0;
|
|
3
|
+
exports.DashKitDnDContext = exports.DashkitOvelayControlsContext = exports.DashKitContext = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const react_1 = tslib_1.__importDefault(require("react"));
|
|
6
6
|
const DashKitContext = react_1.default.createContext();
|
|
7
7
|
exports.DashKitContext = DashKitContext;
|
|
8
|
+
const DashkitOvelayControlsContext = react_1.default.createContext();
|
|
9
|
+
exports.DashkitOvelayControlsContext = DashkitOvelayControlsContext;
|
|
8
10
|
const DashKitDnDContext = react_1.default.createContext();
|
|
9
11
|
exports.DashKitDnDContext = DashKitDnDContext;
|
|
@@ -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;
|