@gravity-ui/dashkit 8.0.2 → 8.1.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/build/cjs/components/ActionPanel/ActionPanel.d.ts +13 -1
- package/build/cjs/components/ActionPanel/ActionPanel.js +25 -6
- package/build/cjs/components/DashKit/DashKit.d.ts +10 -3
- package/build/cjs/components/DashKit/DashKit.js +2 -0
- package/build/cjs/components/DashKitDnDWrapper/DashKitDnDWrapper.d.ts +6 -0
- package/build/cjs/components/DashKitDnDWrapper/DashKitDnDWrapper.js +24 -0
- package/build/cjs/components/GridItem/GridItem.css +7 -0
- package/build/cjs/components/GridItem/GridItem.d.ts +2 -2
- package/build/cjs/components/GridItem/GridItem.js +61 -3
- package/build/cjs/components/GridLayout/GridLayout.d.ts +2 -0
- package/build/cjs/components/GridLayout/GridLayout.js +75 -6
- package/build/cjs/components/Item/Item.css +1 -1
- package/build/cjs/components/index.d.ts +1 -0
- package/build/cjs/components/index.js +1 -0
- package/build/cjs/constants/common.d.ts +2 -0
- package/build/cjs/constants/common.js +3 -1
- package/build/cjs/context/DashKitContext.d.ts +1 -0
- package/build/cjs/context/DashKitContext.js +3 -1
- package/build/cjs/hocs/withContext.js +87 -6
- package/build/cjs/plugins/Text/Text.js +3 -0
- package/build/cjs/shared/constants/common.d.ts +1 -0
- package/build/cjs/shared/constants/common.js +2 -1
- package/build/cjs/typings/config.d.ts +3 -0
- package/build/cjs/typings/plugin.d.ts +1 -0
- package/build/cjs/utils/update-manager.d.ts +2 -2
- package/build/cjs/utils/update-manager.js +25 -7
- package/build/esm/components/ActionPanel/ActionPanel.d.ts +13 -1
- package/build/esm/components/ActionPanel/ActionPanel.js +23 -5
- package/build/esm/components/DashKit/DashKit.d.ts +10 -3
- package/build/esm/components/DashKit/DashKit.js +2 -0
- package/build/esm/components/DashKitDnDWrapper/DashKitDnDWrapper.d.ts +6 -0
- package/build/esm/components/DashKitDnDWrapper/DashKitDnDWrapper.js +19 -0
- package/build/esm/components/GridItem/GridItem.css +7 -0
- package/build/esm/components/GridItem/GridItem.d.ts +2 -2
- package/build/esm/components/GridItem/GridItem.js +61 -3
- package/build/esm/components/GridLayout/GridLayout.d.ts +2 -0
- package/build/esm/components/GridLayout/GridLayout.js +76 -7
- package/build/esm/components/Item/Item.css +1 -1
- package/build/esm/components/index.d.ts +1 -0
- package/build/esm/components/index.js +1 -0
- package/build/esm/constants/common.d.ts +2 -0
- package/build/esm/constants/common.js +2 -0
- package/build/esm/context/DashKitContext.d.ts +1 -0
- package/build/esm/context/DashKitContext.js +2 -1
- package/build/esm/hocs/withContext.js +88 -7
- package/build/esm/plugins/Text/Text.js +3 -0
- package/build/esm/shared/constants/common.d.ts +1 -0
- package/build/esm/shared/constants/common.js +1 -0
- package/build/esm/typings/config.d.ts +3 -0
- package/build/esm/typings/plugin.d.ts +1 -0
- package/build/esm/utils/update-manager.d.ts +2 -2
- package/build/esm/utils/update-manager.js +25 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,6 +49,7 @@ interface DashKitProps {
|
|
|
49
49
|
- **context**: Object that will be propped up on all widgets.
|
|
50
50
|
- **overlayControls**: Object that overrides widget controls at the time of editing. If not transmitted, basic controls will be displayed.
|
|
51
51
|
- **noOverlay**: If `true`, overlay and controls are not displayed while editing.
|
|
52
|
+
- **focusable**: If `true`, grid items will be focusable.
|
|
52
53
|
- **draggableHandleClassName** : СSS class name of the element that makes the widget draggable.
|
|
53
54
|
|
|
54
55
|
## Usage
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import { ActionPanelProps } from './types';
|
|
3
|
+
export type ActionPanelItem = {
|
|
4
|
+
id: string;
|
|
5
|
+
icon: React.ReactNode;
|
|
6
|
+
title: string;
|
|
7
|
+
onClick?: () => void;
|
|
8
|
+
className?: string;
|
|
9
|
+
qa?: string;
|
|
10
|
+
pluginType?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare const ActionPanelItemContainer: ({ item }: {
|
|
13
|
+
item: ActionPanelItem;
|
|
14
|
+
}) => JSX.Element;
|
|
3
15
|
export declare const ActionPanel: (props: ActionPanelProps) => JSX.Element | null;
|
|
@@ -1,21 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ActionPanel = void 0;
|
|
3
|
+
exports.ActionPanel = exports.ActionPanelItemContainer = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const react_1 = tslib_1.__importDefault(require("react"));
|
|
6
6
|
const react_transition_group_1 = require("react-transition-group");
|
|
7
|
+
const DashKitContext_1 = require("../../context/DashKitContext");
|
|
7
8
|
const cn_1 = require("../../utils/cn");
|
|
8
9
|
const b = (0, cn_1.cn)('dashkit-action-panel');
|
|
10
|
+
const ActionPanelItemContainer = ({ item }) => {
|
|
11
|
+
const dragContext = react_1.default.useContext(DashKitContext_1.DashKitDnDContext);
|
|
12
|
+
const onDragStart = react_1.default.useCallback((e) => {
|
|
13
|
+
dragContext.onDragStart(e, item.pluginType);
|
|
14
|
+
}, [dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragStart, item.pluginType]);
|
|
15
|
+
const onDragEnd = react_1.default.useCallback((e) => {
|
|
16
|
+
dragContext.onDragEnd(e);
|
|
17
|
+
}, [dragContext === null || dragContext === void 0 ? void 0 : dragContext.onDragEnd]);
|
|
18
|
+
let dndProps = {};
|
|
19
|
+
if (item.pluginType) {
|
|
20
|
+
dndProps = {
|
|
21
|
+
draggable: true,
|
|
22
|
+
unselectable: 'on',
|
|
23
|
+
onDragStart,
|
|
24
|
+
onDragEnd,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return (react_1.default.createElement("div", Object.assign({ role: "button", className: b('item', item.className), key: `dk-action-panel-${item.id}`, onClick: item.onClick, "data-qa": item.qa }, dndProps),
|
|
28
|
+
react_1.default.createElement("div", { className: b('icon') }, item.icon),
|
|
29
|
+
react_1.default.createElement("div", { className: b('title'), title: item.title }, item.title)));
|
|
30
|
+
};
|
|
31
|
+
exports.ActionPanelItemContainer = ActionPanelItemContainer;
|
|
9
32
|
const ActionPanel = (props) => {
|
|
10
33
|
var _a, _b;
|
|
11
34
|
const isDisabled = (_a = props.disable) !== null && _a !== void 0 ? _a : false;
|
|
12
35
|
const isAnimated = (_b = props.toggleAnimation) !== null && _b !== void 0 ? _b : false;
|
|
13
36
|
const nodeRef = react_1.default.useRef(null);
|
|
14
|
-
const content = (react_1.default.createElement("div", { ref: nodeRef, className: b(null, props.className) }, props.items.map((item) => {
|
|
15
|
-
return (react_1.default.createElement("div", { role: "button", className: b('item', item.className), key: `dk-action-panel-${item.id}`, onClick: item.onClick, "data-qa": item.qa },
|
|
16
|
-
react_1.default.createElement("div", { className: b('icon') }, item.icon),
|
|
17
|
-
react_1.default.createElement("div", { className: b('title'), title: item.title }, item.title)));
|
|
18
|
-
})));
|
|
37
|
+
const content = (react_1.default.createElement("div", { ref: nodeRef, className: b(null, props.className) }, props.items.map((item, i) => (react_1.default.createElement(exports.ActionPanelItemContainer, { key: `item_${i}`, item: item })))));
|
|
19
38
|
if (isAnimated) {
|
|
20
39
|
return (react_1.default.createElement(react_transition_group_1.CSSTransition, { in: !isDisabled, nodeRef: nodeRef, classNames: b(null), timeout: 300, unmountOnExit: true }, content));
|
|
21
40
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { Config, ConfigItem, GlobalParams, ItemsStateAndParams } from '../../shared';
|
|
3
|
-
import { ContextProps, Plugin, SetConfigItem,
|
|
2
|
+
import type { Config, ConfigItem, ConfigLayout, GlobalParams, ItemsStateAndParams } from '../../shared';
|
|
3
|
+
import { ContextProps, 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 {
|
|
@@ -15,12 +15,19 @@ interface DashKitDefaultProps {
|
|
|
15
15
|
config: Config;
|
|
16
16
|
itemsStateAndParams: ItemsStateAndParams;
|
|
17
17
|
}) => void;
|
|
18
|
+
onDrop: (dropProps: {
|
|
19
|
+
commit: () => void;
|
|
20
|
+
pluginType: string;
|
|
21
|
+
itemLayout: ConfigLayout;
|
|
22
|
+
newLayout: ConfigLayout[];
|
|
23
|
+
}) => void;
|
|
18
24
|
defaultGlobalParams: GlobalParams;
|
|
19
25
|
globalParams: GlobalParams;
|
|
20
26
|
itemsStateAndParams: ItemsStateAndParams;
|
|
21
27
|
settings: SettingsProps;
|
|
22
28
|
context: ContextProps;
|
|
23
29
|
noOverlay: boolean;
|
|
30
|
+
focusable?: boolean;
|
|
24
31
|
}
|
|
25
32
|
export interface DashKitProps extends DashKitGeneralProps, Partial<DashKitDefaultProps> {
|
|
26
33
|
}
|
|
@@ -33,7 +40,7 @@ export declare class DashKit extends React.PureComponent<DashKitInnerProps> {
|
|
|
33
40
|
item: SetConfigItem;
|
|
34
41
|
namespace?: string;
|
|
35
42
|
config: Config;
|
|
36
|
-
options?:
|
|
43
|
+
options?: SetNewItemOptions;
|
|
37
44
|
}): Config;
|
|
38
45
|
static removeItem({ id, config, itemsStateAndParams, }: {
|
|
39
46
|
id: string;
|
|
@@ -59,6 +59,7 @@ exports.DashKit = DashKit;
|
|
|
59
59
|
DashKit.defaultProps = {
|
|
60
60
|
onItemEdit: noop_1.default,
|
|
61
61
|
onChange: noop_1.default,
|
|
62
|
+
onDrop: noop_1.default,
|
|
62
63
|
defaultGlobalParams: {},
|
|
63
64
|
globalParams: {},
|
|
64
65
|
itemsStateAndParams: {},
|
|
@@ -68,4 +69,5 @@ DashKit.defaultProps = {
|
|
|
68
69
|
},
|
|
69
70
|
context: {},
|
|
70
71
|
noOverlay: false,
|
|
72
|
+
focusable: false,
|
|
71
73
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DashKitDnDWrapper = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const react_1 = tslib_1.__importDefault(require("react"));
|
|
6
|
+
const DashKitContext_1 = require("../../context/DashKitContext");
|
|
7
|
+
const DashKitDnDWrapper = (props) => {
|
|
8
|
+
const [dragPluginType, setDragPluginType] = react_1.default.useState(null);
|
|
9
|
+
const onDragStart = react_1.default.useCallback((_, type) => {
|
|
10
|
+
setDragPluginType(type);
|
|
11
|
+
}, [setDragPluginType]);
|
|
12
|
+
const onDragEnd = react_1.default.useCallback((_) => {
|
|
13
|
+
setDragPluginType(null);
|
|
14
|
+
}, [setDragPluginType]);
|
|
15
|
+
const contextValue = react_1.default.useMemo(() => {
|
|
16
|
+
return {
|
|
17
|
+
dragPluginType,
|
|
18
|
+
onDragStart,
|
|
19
|
+
onDragEnd,
|
|
20
|
+
};
|
|
21
|
+
}, [dragPluginType, onDragStart, onDragEnd]);
|
|
22
|
+
return (react_1.default.createElement(DashKitContext_1.DashKitDnDContext.Provider, { value: contextValue }, props.children));
|
|
23
|
+
};
|
|
24
|
+
exports.DashKitDnDWrapper = DashKitDnDWrapper;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
.dashkit-grid-item {
|
|
2
2
|
position: relative;
|
|
3
3
|
}
|
|
4
|
+
.dashkit-grid-item:focus {
|
|
5
|
+
outline: none;
|
|
6
|
+
}
|
|
4
7
|
.dashkit-grid-item__overlay {
|
|
5
8
|
--_-dashkit-overlay-color: var(--dashkit-overlay-color, var(--g-color-base-generic));
|
|
6
9
|
--_-dashkit-overlay-border-color: var(--dashkit-overlay-border-color, rgba(0, 0, 0, 0.1));
|
|
@@ -56,6 +59,10 @@
|
|
|
56
59
|
will-change: transform;
|
|
57
60
|
}
|
|
58
61
|
|
|
62
|
+
.react-grid-item.dashkit-grid-item_is-focused {
|
|
63
|
+
z-index: 2;
|
|
64
|
+
}
|
|
65
|
+
|
|
59
66
|
.react-grid-item.react-grid-placeholder {
|
|
60
67
|
--_-dashkit-placeholder-color: var(--dashkit-placeholder-color, #fc0);
|
|
61
68
|
--_-dashkit-placeholder-opacity: var(--dashkit-placeholder-opacity, 0.2);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export default GridItemForwarderRef;
|
|
2
|
+
declare const GridItemForwarderRef: React.ForwardRefExoticComponent<React.RefAttributes<any>>;
|
|
3
3
|
import React from 'react';
|
|
@@ -8,7 +8,55 @@ const cn_1 = require("../../utils/cn");
|
|
|
8
8
|
const Item_1 = tslib_1.__importDefault(require("../Item/Item"));
|
|
9
9
|
const OverlayControls_1 = tslib_1.__importDefault(require("../OverlayControls/OverlayControls"));
|
|
10
10
|
const b = (0, cn_1.cn)('dashkit-grid-item');
|
|
11
|
+
class WindowFocusObserver {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.blurHandler = (e) => {
|
|
14
|
+
if (e.target === window) {
|
|
15
|
+
this.isFocused = false;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
this.focusHandler = (e) => {
|
|
19
|
+
if (e.target === window) {
|
|
20
|
+
this.isFocused = true;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
this.subscribers = 0;
|
|
24
|
+
this.isFocused = !document.hidden;
|
|
25
|
+
window.addEventListener('blur', this.blurHandler, true);
|
|
26
|
+
window.addEventListener('focus', this.focusHandler, true);
|
|
27
|
+
}
|
|
28
|
+
// Method to get state after all blur\focus events in document are triggered
|
|
29
|
+
async getFocuseState() {
|
|
30
|
+
return new Promise((resolve) => {
|
|
31
|
+
requestAnimationFrame(() => {
|
|
32
|
+
resolve(this.isFocused);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const windowFocusObserver = new WindowFocusObserver();
|
|
11
38
|
class GridItem extends react_1.default.PureComponent {
|
|
39
|
+
constructor() {
|
|
40
|
+
super(...arguments);
|
|
41
|
+
this.state = {
|
|
42
|
+
isFocused: false,
|
|
43
|
+
};
|
|
44
|
+
this.onFocusHandler = () => {
|
|
45
|
+
this.setState({ isFocused: true });
|
|
46
|
+
if (this.controller) {
|
|
47
|
+
this.controller.abort();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
this.onBlurHandler = () => {
|
|
51
|
+
this.controller = new AbortController();
|
|
52
|
+
windowFocusObserver.getFocuseState().then((isWindowFocused) => {
|
|
53
|
+
if (!this.controller.signal.aborted && isWindowFocused) {
|
|
54
|
+
this.setState({ isFocused: false });
|
|
55
|
+
}
|
|
56
|
+
this.controller = null;
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
}
|
|
12
60
|
renderOverlay() {
|
|
13
61
|
const { overlayControls } = this.props;
|
|
14
62
|
const { editMode } = this.context;
|
|
@@ -24,7 +72,7 @@ class GridItem extends react_1.default.PureComponent {
|
|
|
24
72
|
render() {
|
|
25
73
|
// из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
|
|
26
74
|
// https://github.com/STRML/react-grid-layout/issues/721
|
|
27
|
-
const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, withCustomHandle, } = this.props;
|
|
75
|
+
const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, } = this.props;
|
|
28
76
|
const { editMode } = this.context;
|
|
29
77
|
const width = Number.parseInt(style.width, 10);
|
|
30
78
|
const height = Number.parseInt(style.height, 10);
|
|
@@ -39,8 +87,15 @@ class GridItem extends react_1.default.PureComponent {
|
|
|
39
87
|
const { _editActive } = this.props.item.data;
|
|
40
88
|
return (react_1.default.createElement("div", Object.assign({ className: b({
|
|
41
89
|
'is-dragging': isDragging,
|
|
90
|
+
'is-focused': this.state.isFocused,
|
|
42
91
|
'with-custom-handle': withCustomHandle,
|
|
43
|
-
}, preparedClassName), "data-qa": "dashkit-grid-item", style: style, ref: this.props.forwardedRef }, reactGridLayoutProps
|
|
92
|
+
}, preparedClassName), "data-qa": "dashkit-grid-item", style: style, ref: this.props.forwardedRef }, reactGridLayoutProps, (focusable
|
|
93
|
+
? {
|
|
94
|
+
onFocus: this.onFocusHandler,
|
|
95
|
+
onBlur: this.onBlurHandler,
|
|
96
|
+
tabIndex: -1,
|
|
97
|
+
}
|
|
98
|
+
: {})),
|
|
44
99
|
react_1.default.createElement("div", { className: b('item', { editMode: editMode && !_editActive && !noOverlay }) },
|
|
45
100
|
react_1.default.createElement(Item_1.default, { id: this.props.id, item: this.props.item, shouldItemUpdate: !isDragging, width: width, height: height, transform: transform, adjustWidgetLayout: this.props.adjustWidgetLayout, layout: this.props.layout, forwardedPluginRef: this.props.forwardedPluginRef })),
|
|
46
101
|
!noOverlay && this.renderOverlay(),
|
|
@@ -61,6 +116,7 @@ GridItem.propTypes = {
|
|
|
61
116
|
className: prop_types_1.default.string,
|
|
62
117
|
style: prop_types_1.default.object,
|
|
63
118
|
noOverlay: prop_types_1.default.bool,
|
|
119
|
+
focusable: prop_types_1.default.bool,
|
|
64
120
|
withCustomHandle: prop_types_1.default.bool,
|
|
65
121
|
onMouseDown: prop_types_1.default.func,
|
|
66
122
|
onMouseUp: prop_types_1.default.func,
|
|
@@ -68,6 +124,8 @@ GridItem.propTypes = {
|
|
|
68
124
|
onTouchStart: prop_types_1.default.func,
|
|
69
125
|
};
|
|
70
126
|
GridItem.contextType = DashKitContext_1.DashKitContext;
|
|
71
|
-
|
|
127
|
+
const GridItemForwarderRef = react_1.default.forwardRef((props, ref) => {
|
|
72
128
|
return react_1.default.createElement(GridItem, Object.assign({}, props, { forwardedRef: ref }));
|
|
73
129
|
});
|
|
130
|
+
GridItemForwarderRef.displayName = 'forwardRef(GridItem)';
|
|
131
|
+
exports.default = GridItemForwarderRef;
|
|
@@ -21,6 +21,8 @@ export default class GridLayout extends React.PureComponent<any, any, any> {
|
|
|
21
21
|
reloadItems(): void;
|
|
22
22
|
_onStart: () => void;
|
|
23
23
|
_onStop: (newLayout: any) => void;
|
|
24
|
+
_onDropDragOver: (e: any) => any;
|
|
25
|
+
_onDrop: (layout: any, item: any, e: any) => false | undefined;
|
|
24
26
|
render(): JSX.Element;
|
|
25
27
|
}
|
|
26
28
|
import React from 'react';
|
|
@@ -6,7 +6,45 @@ const react_grid_layout_1 = tslib_1.__importStar(require("react-grid-layout"));
|
|
|
6
6
|
const constants_1 = require("../../constants");
|
|
7
7
|
const DashKitContext_1 = require("../../context/DashKitContext");
|
|
8
8
|
const GridItem_1 = tslib_1.__importDefault(require("../GridItem/GridItem"));
|
|
9
|
-
|
|
9
|
+
class DragOverLayout extends react_grid_layout_1.default {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.dragReset = () => {
|
|
13
|
+
if (this.dragEnterCounter) {
|
|
14
|
+
this.dragEnterCounter = 0;
|
|
15
|
+
this.removeDroppingPlaceholder();
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
componentDidMount() {
|
|
20
|
+
super.componentDidMount();
|
|
21
|
+
window.addEventListener('dragend', this.dragReset);
|
|
22
|
+
}
|
|
23
|
+
componentWillUnmount() {
|
|
24
|
+
window.removeEventListener('dragend', this.dragReset);
|
|
25
|
+
}
|
|
26
|
+
processGridItem(child, isDroppingItem) {
|
|
27
|
+
if (isDroppingItem) {
|
|
28
|
+
// Drop item from outside gets 0,0 droppingPosition
|
|
29
|
+
// centering cursor on newly creted grid item
|
|
30
|
+
// And cause grid-layout using it's own GridItem to make it look
|
|
31
|
+
// like overlay adding className
|
|
32
|
+
const gridItem = super.processGridItem(child, isDroppingItem);
|
|
33
|
+
if (!gridItem)
|
|
34
|
+
return null;
|
|
35
|
+
const { props } = gridItem;
|
|
36
|
+
const { containerWidth, cols, w, h, rowHeight, margin, transformScale } = props;
|
|
37
|
+
const leftOffset = (((containerWidth / cols) * w) / 2 || 0) * transformScale;
|
|
38
|
+
const topOffset = ((h * rowHeight + (h - 1) * margin[1]) / 2 || 0) * transformScale;
|
|
39
|
+
return react_1.default.cloneElement(gridItem, {
|
|
40
|
+
className: constants_1.OVERLAY_CLASS_NAME,
|
|
41
|
+
droppingPosition: Object.assign(Object.assign({}, props.droppingPosition), { left: props.droppingPosition.left - leftOffset, top: props.droppingPosition.top - topOffset }),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return super.processGridItem(child, isDroppingItem);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const Layout = (0, react_grid_layout_1.WidthProvider)(DragOverLayout); // eslint-disable-line new-cap
|
|
10
48
|
class GridLayout extends react_1.default.PureComponent {
|
|
11
49
|
constructor(props, context) {
|
|
12
50
|
super(props, context);
|
|
@@ -32,13 +70,38 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
32
70
|
return getItemsMeta(this.pluginsRefs);
|
|
33
71
|
};
|
|
34
72
|
this._onStart = () => {
|
|
73
|
+
if (this.temporaryLayout)
|
|
74
|
+
return;
|
|
35
75
|
this.setState({ isDragging: true });
|
|
36
76
|
};
|
|
37
77
|
this._onStop = (newLayout) => {
|
|
38
|
-
const { layoutChange } = this.context;
|
|
39
|
-
|
|
78
|
+
const { layoutChange, onDrop, temporaryLayout } = this.context;
|
|
79
|
+
if (temporaryLayout) {
|
|
80
|
+
onDrop === null || onDrop === void 0 ? void 0 : onDrop(newLayout, newLayout.find(({ i }) => i === constants_1.TEMPORARY_ITEM_ID));
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
layoutChange(newLayout);
|
|
84
|
+
}
|
|
40
85
|
this.setState({ isDragging: false });
|
|
41
86
|
};
|
|
87
|
+
this._onDropDragOver = (e) => {
|
|
88
|
+
const { editMode, onDropDragOver, temporaryLayout } = this.context;
|
|
89
|
+
if (!editMode) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
const result = onDropDragOver(e);
|
|
93
|
+
if (temporaryLayout) {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
};
|
|
98
|
+
this._onDrop = (layout, item, e) => {
|
|
99
|
+
const { editMode, temporaryLayout, onDrop } = this.context;
|
|
100
|
+
if (!editMode && temporaryLayout) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
onDrop === null || onDrop === void 0 ? void 0 : onDrop(layout, item, e);
|
|
104
|
+
};
|
|
42
105
|
this.pluginsRefs = [];
|
|
43
106
|
this.state = {
|
|
44
107
|
isDragging: false,
|
|
@@ -72,14 +135,20 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
72
135
|
}
|
|
73
136
|
}
|
|
74
137
|
render() {
|
|
75
|
-
const { layout, config, registerManager, editMode, noOverlay, draggableHandleClassName } = this.context;
|
|
138
|
+
const { layout, temporaryLayout, config, registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
|
|
76
139
|
this.pluginsRefs.length = config.items.length;
|
|
77
|
-
return (react_1.default.createElement(Layout, Object.assign({}, registerManager.gridLayout, { layout: layout, isDraggable: editMode, isResizable: editMode, onDragStart: this._onStart, onDragStop: this._onStop, onResizeStart: this._onStart, onResizeStop: this._onStop }, (draggableHandleClassName
|
|
140
|
+
return (react_1.default.createElement(Layout, Object.assign({}, registerManager.gridLayout, { layout: temporaryLayout || layout, isDraggable: editMode, isResizable: editMode, onDragStart: this._onStart, onDragStop: this._onStop, onResizeStart: this._onStart, onResizeStop: this._onStop }, (draggableHandleClassName
|
|
78
141
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
142
|
+
: null), (outerDnDEnable
|
|
143
|
+
? {
|
|
144
|
+
isDroppable: true,
|
|
145
|
+
onDropDragOver: this._onDropDragOver,
|
|
146
|
+
onDrop: this._onDrop,
|
|
147
|
+
}
|
|
79
148
|
: null), { draggableCancel: `.${constants_1.OVERLAY_CONTROLS_CLASS_NAME}` }), config.items.map((item, i) => {
|
|
80
149
|
return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: (pluginRef) => {
|
|
81
150
|
this.pluginsRefs[i] = pluginRef;
|
|
82
|
-
}, key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
|
|
151
|
+
}, key: item.id, id: item.id, item: item, layout: temporaryLayout || layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
|
|
83
152
|
})));
|
|
84
153
|
}
|
|
85
154
|
}
|
|
@@ -2,3 +2,4 @@ export * from './DashKit';
|
|
|
2
2
|
export type { OverlayControlItem, PreparedCopyItemOptions } from './OverlayControls/OverlayControls';
|
|
3
3
|
export * from './ActionPanel/ActionPanel';
|
|
4
4
|
export type { ActionPanelItem, ActionPanelProps } from './ActionPanel/types';
|
|
5
|
+
export * from './DashKitDnDWrapper/DashKitDnDWrapper';
|
|
@@ -3,3 +3,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
tslib_1.__exportStar(require("./DashKit"), exports);
|
|
5
5
|
tslib_1.__exportStar(require("./ActionPanel/ActionPanel"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./DashKitDnDWrapper/DashKitDnDWrapper"), exports);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export declare const COPIED_WIDGET_STORE_KEY = "dashCopiedItem";
|
|
2
2
|
export declare const DEFAULT_NAMESPACE = "default";
|
|
3
3
|
export declare const OVERLAY_CONTROLS_CLASS_NAME = "dashkit-overlay-controls";
|
|
4
|
+
export declare const OVERLAY_CLASS_NAME = "dashkit-grid-item__overlay";
|
|
5
|
+
export declare const TEMPORARY_ITEM_ID = "__dropping-elem__";
|
|
4
6
|
export declare const MenuItems: {
|
|
5
7
|
readonly Copy: "copy";
|
|
6
8
|
readonly Delete: "delete";
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MenuItems = exports.OVERLAY_CONTROLS_CLASS_NAME = exports.DEFAULT_NAMESPACE = exports.COPIED_WIDGET_STORE_KEY = void 0;
|
|
3
|
+
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';
|
|
7
|
+
exports.OVERLAY_CLASS_NAME = 'dashkit-grid-item__overlay';
|
|
8
|
+
exports.TEMPORARY_ITEM_ID = '__dropping-elem__';
|
|
7
9
|
exports.MenuItems = {
|
|
8
10
|
Copy: 'copy',
|
|
9
11
|
Delete: 'delete',
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DashKitContext = void 0;
|
|
3
|
+
exports.DashKitDnDContext = 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 DashKitDnDContext = react_1.default.createContext();
|
|
9
|
+
exports.DashKitDnDContext = DashKitDnDContext;
|
|
@@ -4,6 +4,7 @@ exports.withContext = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const react_1 = tslib_1.__importDefault(require("react"));
|
|
6
6
|
const isEqual_1 = tslib_1.__importDefault(require("lodash/isEqual"));
|
|
7
|
+
const common_1 = require("../constants/common");
|
|
7
8
|
const DashKitContext_1 = require("../context/DashKitContext");
|
|
8
9
|
const shared_1 = require("../shared");
|
|
9
10
|
const utils_1 = require("../utils");
|
|
@@ -15,6 +16,10 @@ function useMemoStateContext(props) {
|
|
|
15
16
|
// (высота) из конфига будет запоминаться в originalLayouts, новое значение высоты в adjustedLayouts
|
|
16
17
|
const originalLayouts = react_1.default.useRef({});
|
|
17
18
|
const adjustedLayouts = react_1.default.useRef({});
|
|
19
|
+
const [temporaryLayout, setTemporaryLayout] = react_1.default.useState(null);
|
|
20
|
+
const resetTemporaryLayout = react_1.default.useCallback(() => setTemporaryLayout(null), [setTemporaryLayout]);
|
|
21
|
+
const dndContext = react_1.default.useContext(DashKitContext_1.DashKitDnDContext);
|
|
22
|
+
const outerDnDEnable = Boolean(dndContext);
|
|
18
23
|
// TODO: need move originalLayouts, adjustedLayouts to state
|
|
19
24
|
const [layoutUpdateCounter, forceUpdateLayout] = react_1.default.useState(0);
|
|
20
25
|
const onChange = react_1.default.useCallback(({ config = props.config, itemsStateAndParams = props.itemsStateAndParams }) => {
|
|
@@ -45,12 +50,27 @@ function useMemoStateContext(props) {
|
|
|
45
50
|
}
|
|
46
51
|
}, [props.config, onChange]);
|
|
47
52
|
const onItemRemove = react_1.default.useCallback((id) => {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
if (id === common_1.TEMPORARY_ITEM_ID) {
|
|
54
|
+
resetTemporaryLayout();
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
if (temporaryLayout) {
|
|
58
|
+
setTemporaryLayout(temporaryLayout.filter(({ i }) => i !== id));
|
|
59
|
+
}
|
|
60
|
+
onChange(utils_1.UpdateManager.removeItem({
|
|
61
|
+
id,
|
|
62
|
+
config: props.config,
|
|
63
|
+
itemsStateAndParams: props.itemsStateAndParams,
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
}, [
|
|
67
|
+
props.config,
|
|
68
|
+
props.itemsStateAndParams,
|
|
69
|
+
temporaryLayout,
|
|
70
|
+
onChange,
|
|
71
|
+
setTemporaryLayout,
|
|
72
|
+
resetTemporaryLayout,
|
|
73
|
+
]);
|
|
54
74
|
const onItemStateAndParamsChange = react_1.default.useCallback((id, stateAndParams, options) => {
|
|
55
75
|
onChange({
|
|
56
76
|
itemsStateAndParams: utils_1.UpdateManager.changeStateAndParams({
|
|
@@ -124,11 +144,62 @@ function useMemoStateContext(props) {
|
|
|
124
144
|
const reloadItems = react_1.default.useCallback((pluginsRefs, data) => {
|
|
125
145
|
pluginsRefs.forEach((ref) => ref && ref.reload && ref.reload(data));
|
|
126
146
|
}, []);
|
|
147
|
+
const draggedPluginRef = react_1.default.useRef(dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType);
|
|
148
|
+
react_1.default.useEffect(() => {
|
|
149
|
+
if (!(dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType) && !temporaryLayout) {
|
|
150
|
+
draggedPluginRef.current = null;
|
|
151
|
+
}
|
|
152
|
+
else if (dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType) {
|
|
153
|
+
draggedPluginRef.current = dndContext.dragPluginType;
|
|
154
|
+
}
|
|
155
|
+
}, [draggedPluginRef, dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType, temporaryLayout]);
|
|
156
|
+
const dndPluginType = draggedPluginRef.current || (dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragPluginType);
|
|
157
|
+
const dragOverPlugin = react_1.default.useMemo(() => {
|
|
158
|
+
const pluginType = dndPluginType;
|
|
159
|
+
if (pluginType === null && temporaryLayout === null)
|
|
160
|
+
return null;
|
|
161
|
+
if (props.registerManager.check(pluginType)) {
|
|
162
|
+
return props.registerManager.getItem(pluginType);
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
// eslint-disable-next-line no-console
|
|
166
|
+
console.error(`Uknown pluginType: ${pluginType}`);
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}, [dndPluginType, props.registerManager, temporaryLayout]);
|
|
170
|
+
const onDropDragOver = react_1.default.useCallback(() => {
|
|
171
|
+
if (temporaryLayout) {
|
|
172
|
+
resetTemporaryLayout();
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
if (dragOverPlugin === null || dragOverPlugin === void 0 ? void 0 : dragOverPlugin.defaultLayout) {
|
|
176
|
+
const { h = 3, w = 3 } = dragOverPlugin.defaultLayout;
|
|
177
|
+
return { h, w };
|
|
178
|
+
}
|
|
179
|
+
return false;
|
|
180
|
+
}, [resetTemporaryLayout, temporaryLayout, dragOverPlugin]);
|
|
181
|
+
const onDrop = react_1.default.useCallback((newLayout, item) => {
|
|
182
|
+
setTemporaryLayout(newLayout);
|
|
183
|
+
const { i, w, h, x, y } = item;
|
|
184
|
+
props.onDrop({
|
|
185
|
+
newLayout: newLayout.reduce((memo, l) => {
|
|
186
|
+
if (l.i !== i) {
|
|
187
|
+
memo.push({ i: l.i, w: l.w, h: l.h, x: l.x, y: l.y });
|
|
188
|
+
}
|
|
189
|
+
return memo;
|
|
190
|
+
}, []),
|
|
191
|
+
itemLayout: { w, h, x, y },
|
|
192
|
+
pluginType: dndPluginType,
|
|
193
|
+
commit: resetTemporaryLayout,
|
|
194
|
+
});
|
|
195
|
+
}, [dndPluginType, props.onDrop]);
|
|
127
196
|
return react_1.default.useMemo(() => ({
|
|
128
197
|
layout: resultLayout,
|
|
198
|
+
temporaryLayout,
|
|
129
199
|
config: props.config,
|
|
130
200
|
context: props.context,
|
|
131
201
|
noOverlay: props.noOverlay,
|
|
202
|
+
focusable: props.focusable,
|
|
132
203
|
defaultGlobalParams: props.globalParams,
|
|
133
204
|
globalParams: props.globalParams,
|
|
134
205
|
editMode: props.editMode,
|
|
@@ -138,6 +209,8 @@ function useMemoStateContext(props) {
|
|
|
138
209
|
registerManager: props.registerManager,
|
|
139
210
|
onItemStateAndParamsChange,
|
|
140
211
|
removeItem: onItemRemove,
|
|
212
|
+
onDrop,
|
|
213
|
+
onDropDragOver,
|
|
141
214
|
editItem: props.onItemEdit,
|
|
142
215
|
layoutChange: onLayoutChange,
|
|
143
216
|
getItemsMeta,
|
|
@@ -146,11 +219,15 @@ function useMemoStateContext(props) {
|
|
|
146
219
|
revertToOriginalLayout,
|
|
147
220
|
forwardedMetaRef: props.forwardedMetaRef,
|
|
148
221
|
draggableHandleClassName: props.draggableHandleClassName,
|
|
222
|
+
outerDnDEnable,
|
|
223
|
+
dragOverPlugin,
|
|
149
224
|
}), [
|
|
150
225
|
resultLayout,
|
|
226
|
+
temporaryLayout,
|
|
151
227
|
props.config,
|
|
152
228
|
props.context,
|
|
153
229
|
props.noOverlay,
|
|
230
|
+
props.focusable,
|
|
154
231
|
props.globalParams,
|
|
155
232
|
props.editMode,
|
|
156
233
|
props.settings,
|
|
@@ -159,6 +236,8 @@ function useMemoStateContext(props) {
|
|
|
159
236
|
props.registerManager,
|
|
160
237
|
onItemStateAndParamsChange,
|
|
161
238
|
onItemRemove,
|
|
239
|
+
onDrop,
|
|
240
|
+
onDropDragOver,
|
|
162
241
|
props.onItemEdit,
|
|
163
242
|
onLayoutChange,
|
|
164
243
|
getItemsMeta,
|
|
@@ -167,6 +246,8 @@ function useMemoStateContext(props) {
|
|
|
167
246
|
revertToOriginalLayout,
|
|
168
247
|
props.forwardedMetaRef,
|
|
169
248
|
props.draggableHandleClassName,
|
|
249
|
+
outerDnDEnable,
|
|
250
|
+
dragOverPlugin,
|
|
170
251
|
]);
|
|
171
252
|
}
|
|
172
253
|
function withContext(Component) {
|
|
@@ -117,5 +117,8 @@ const plugin = {
|
|
|
117
117
|
renderer(props, forwardedRef) {
|
|
118
118
|
return react_1.default.createElement(PluginText, Object.assign({}, props, { apiHandler: plugin._apiHandler, ref: forwardedRef }));
|
|
119
119
|
},
|
|
120
|
+
placeholderRenderer(_, forwardedRef) {
|
|
121
|
+
return react_1.default.createElement("div", { ref: forwardedRef }, "Text placeholder");
|
|
122
|
+
},
|
|
120
123
|
};
|
|
121
124
|
exports.default = plugin;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ACTION_PARAM_PREFIX = exports.META_KEY = exports.CURRENT_VERSION = void 0;
|
|
3
|
+
exports.TERMORARY_ITEM_ID = exports.ACTION_PARAM_PREFIX = exports.META_KEY = exports.CURRENT_VERSION = void 0;
|
|
4
4
|
exports.CURRENT_VERSION = 2;
|
|
5
5
|
exports.META_KEY = '__meta__';
|
|
6
6
|
exports.ACTION_PARAM_PREFIX = '_ap_';
|
|
7
|
+
exports.TERMORARY_ITEM_ID = '__dropping-elem__';
|