@gravity-ui/dashkit 8.1.0 → 8.2.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 +95 -0
- package/build/cjs/components/ActionPanel/ActionPanel.d.ts +4 -1
- package/build/cjs/components/ActionPanel/ActionPanel.js +10 -6
- package/build/cjs/components/ActionPanel/types.d.ts +3 -1
- package/build/cjs/components/DashKit/DashKit.d.ts +4 -3
- package/build/cjs/components/DashKit/DashKit.js +1 -0
- package/build/cjs/components/DashKitDnDWrapper/DashKitDnDWrapper.d.ts +10 -0
- package/build/cjs/components/DashKitDnDWrapper/DashKitDnDWrapper.js +35 -0
- package/build/cjs/components/GridItem/GridItem.d.ts +2 -2
- package/build/cjs/components/GridItem/GridItem.js +8 -5
- package/build/cjs/components/GridLayout/GridLayout.d.ts +3 -0
- package/build/cjs/components/GridLayout/GridLayout.js +51 -11
- package/build/cjs/components/GridLayout/ReactGridLayout.d.ts +3 -0
- package/build/cjs/components/GridLayout/ReactGridLayout.js +49 -0
- package/build/cjs/components/Item/Item.css +1 -1
- package/build/cjs/components/Item/Item.d.ts +1 -0
- package/build/cjs/components/Item/Item.js +7 -1
- package/build/cjs/components/OverlayControls/OverlayControls.js +2 -2
- package/build/cjs/components/index.d.ts +1 -0
- package/build/cjs/components/index.js +1 -0
- package/build/cjs/constants/common.d.ts +4 -0
- package/build/cjs/constants/common.js +5 -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 +1 -0
- package/build/cjs/hocs/prepareItem.js +4 -2
- package/build/cjs/hocs/withContext.js +84 -6
- package/build/cjs/hooks/useDnDItemProps.d.ts +10 -0
- package/build/cjs/hooks/useDnDItemProps.js +30 -0
- package/build/cjs/shared/constants/common.d.ts +1 -0
- package/build/cjs/shared/constants/common.js +2 -1
- package/build/cjs/shared/types/common.d.ts +15 -0
- 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 +4 -1
- package/build/esm/components/ActionPanel/ActionPanel.js +8 -5
- package/build/esm/components/ActionPanel/types.d.ts +3 -1
- package/build/esm/components/DashKit/DashKit.d.ts +4 -3
- package/build/esm/components/DashKit/DashKit.js +1 -0
- package/build/esm/components/DashKitDnDWrapper/DashKitDnDWrapper.d.ts +10 -0
- package/build/esm/components/DashKitDnDWrapper/DashKitDnDWrapper.js +30 -0
- package/build/esm/components/GridItem/GridItem.d.ts +2 -2
- package/build/esm/components/GridItem/GridItem.js +8 -5
- package/build/esm/components/GridLayout/GridLayout.d.ts +3 -0
- package/build/esm/components/GridLayout/GridLayout.js +52 -12
- package/build/esm/components/GridLayout/ReactGridLayout.d.ts +3 -0
- package/build/esm/components/GridLayout/ReactGridLayout.js +45 -0
- package/build/esm/components/Item/Item.css +1 -1
- package/build/esm/components/Item/Item.d.ts +1 -0
- package/build/esm/components/Item/Item.js +7 -1
- package/build/esm/components/OverlayControls/OverlayControls.js +2 -2
- package/build/esm/components/index.d.ts +1 -0
- package/build/esm/components/index.js +1 -0
- package/build/esm/constants/common.d.ts +4 -0
- package/build/esm/constants/common.js +4 -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 +1 -0
- package/build/esm/hocs/prepareItem.js +4 -2
- package/build/esm/hocs/withContext.js +85 -7
- package/build/esm/hooks/useDnDItemProps.d.ts +10 -0
- package/build/esm/hooks/useDnDItemProps.js +25 -0
- package/build/esm/shared/constants/common.d.ts +1 -0
- package/build/esm/shared/constants/common.js +1 -0
- package/build/esm/shared/types/common.d.ts +15 -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
|
@@ -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(Object.assign(Object.assign({}, temporaryLayout), { data: temporaryLayout.data.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,8 +144,57 @@ 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 dragProps = dndContext === null || dndContext === void 0 ? void 0 : dndContext.dragProps;
|
|
148
|
+
const dragOverPlugin = react_1.default.useMemo(() => {
|
|
149
|
+
if (!dragProps) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
const pluginType = dragProps.type;
|
|
153
|
+
if (props.registerManager.check(pluginType)) {
|
|
154
|
+
return props.registerManager.getItem(pluginType);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
// eslint-disable-next-line no-console
|
|
158
|
+
console.error(`Uknown pluginType: ${pluginType}`);
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}, [dragProps, props.registerManager]);
|
|
162
|
+
const onDropDragOver = react_1.default.useCallback(() => {
|
|
163
|
+
if (temporaryLayout) {
|
|
164
|
+
resetTemporaryLayout();
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
if (dragOverPlugin) {
|
|
168
|
+
const { defaultLayout } = dragOverPlugin;
|
|
169
|
+
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 || {};
|
|
170
|
+
return { h, w };
|
|
171
|
+
}
|
|
172
|
+
return false;
|
|
173
|
+
}, [resetTemporaryLayout, temporaryLayout, dragOverPlugin, dragProps]);
|
|
174
|
+
const onDrop = react_1.default.useCallback((newLayout, item) => {
|
|
175
|
+
if (!dragProps) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
setTemporaryLayout({
|
|
179
|
+
data: newLayout,
|
|
180
|
+
dragProps,
|
|
181
|
+
});
|
|
182
|
+
const { i, w, h, x, y } = item;
|
|
183
|
+
props.onDrop({
|
|
184
|
+
newLayout: newLayout.reduce((memo, l) => {
|
|
185
|
+
if (l.i !== i) {
|
|
186
|
+
memo.push({ i: l.i, w: l.w, h: l.h, x: l.x, y: l.y });
|
|
187
|
+
}
|
|
188
|
+
return memo;
|
|
189
|
+
}, []),
|
|
190
|
+
itemLayout: { w, h, x, y },
|
|
191
|
+
commit: resetTemporaryLayout,
|
|
192
|
+
dragProps,
|
|
193
|
+
});
|
|
194
|
+
}, [dragProps, props.onDrop, setTemporaryLayout, resetTemporaryLayout]);
|
|
127
195
|
return react_1.default.useMemo(() => ({
|
|
128
196
|
layout: resultLayout,
|
|
197
|
+
temporaryLayout,
|
|
129
198
|
config: props.config,
|
|
130
199
|
context: props.context,
|
|
131
200
|
noOverlay: props.noOverlay,
|
|
@@ -139,6 +208,8 @@ function useMemoStateContext(props) {
|
|
|
139
208
|
registerManager: props.registerManager,
|
|
140
209
|
onItemStateAndParamsChange,
|
|
141
210
|
removeItem: onItemRemove,
|
|
211
|
+
onDrop,
|
|
212
|
+
onDropDragOver,
|
|
142
213
|
editItem: props.onItemEdit,
|
|
143
214
|
layoutChange: onLayoutChange,
|
|
144
215
|
getItemsMeta,
|
|
@@ -147,8 +218,11 @@ function useMemoStateContext(props) {
|
|
|
147
218
|
revertToOriginalLayout,
|
|
148
219
|
forwardedMetaRef: props.forwardedMetaRef,
|
|
149
220
|
draggableHandleClassName: props.draggableHandleClassName,
|
|
221
|
+
outerDnDEnable,
|
|
222
|
+
dragOverPlugin,
|
|
150
223
|
}), [
|
|
151
224
|
resultLayout,
|
|
225
|
+
temporaryLayout,
|
|
152
226
|
props.config,
|
|
153
227
|
props.context,
|
|
154
228
|
props.noOverlay,
|
|
@@ -161,6 +235,8 @@ function useMemoStateContext(props) {
|
|
|
161
235
|
props.registerManager,
|
|
162
236
|
onItemStateAndParamsChange,
|
|
163
237
|
onItemRemove,
|
|
238
|
+
onDrop,
|
|
239
|
+
onDropDragOver,
|
|
164
240
|
props.onItemEdit,
|
|
165
241
|
onLayoutChange,
|
|
166
242
|
getItemsMeta,
|
|
@@ -169,6 +245,8 @@ function useMemoStateContext(props) {
|
|
|
169
245
|
revertToOriginalLayout,
|
|
170
246
|
props.forwardedMetaRef,
|
|
171
247
|
props.draggableHandleClassName,
|
|
248
|
+
outerDnDEnable,
|
|
249
|
+
dragOverPlugin,
|
|
172
250
|
]);
|
|
173
251
|
}
|
|
174
252
|
function withContext(Component) {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ActionPanelItem } from '../components';
|
|
3
|
+
type DndProps = null | {
|
|
4
|
+
draggable: true;
|
|
5
|
+
unselectable: 'on';
|
|
6
|
+
onDragStart: React.DragEventHandler<HTMLDivElement>;
|
|
7
|
+
onDragEnd: React.DragEventHandler<HTMLDivElement>;
|
|
8
|
+
};
|
|
9
|
+
export declare const useDnDItemProps: (item: ActionPanelItem) => DndProps;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useDnDItemProps = 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 useDnDItemProps = (item) => {
|
|
8
|
+
const dragContext = react_1.default.useContext(DashKitContext_1.DashKitDnDContext);
|
|
9
|
+
const onDragStart = react_1.default.useCallback((e) => {
|
|
10
|
+
if (dragContext && item.dragProps) {
|
|
11
|
+
dragContext.onDragStart(e, item.dragProps);
|
|
12
|
+
e.dataTransfer.setDragImage(dragContext.dragImagePreview, 0, 0);
|
|
13
|
+
}
|
|
14
|
+
}, [dragContext, item.dragProps]);
|
|
15
|
+
const onDragEnd = react_1.default.useCallback((e) => {
|
|
16
|
+
if (dragContext) {
|
|
17
|
+
dragContext.onDragEnd(e);
|
|
18
|
+
}
|
|
19
|
+
}, [dragContext]);
|
|
20
|
+
if (dragContext && item.dragProps) {
|
|
21
|
+
return {
|
|
22
|
+
draggable: true,
|
|
23
|
+
unselectable: 'on',
|
|
24
|
+
onDragStart,
|
|
25
|
+
onDragEnd,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
};
|
|
30
|
+
exports.useDnDItemProps = useDnDItemProps;
|
|
@@ -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__';
|
|
@@ -1,5 +1,20 @@
|
|
|
1
|
+
import { ConfigLayout } from './config';
|
|
1
2
|
export type Dictionary<T = unknown> = Record<string, T>;
|
|
2
3
|
export interface StringParams extends Dictionary<string | string[]> {
|
|
3
4
|
}
|
|
4
5
|
export interface GlobalParams extends StringParams {
|
|
5
6
|
}
|
|
7
|
+
export type ItemDragProps = {
|
|
8
|
+
type: string;
|
|
9
|
+
layout?: {
|
|
10
|
+
w?: number;
|
|
11
|
+
h?: number;
|
|
12
|
+
};
|
|
13
|
+
extra?: any;
|
|
14
|
+
};
|
|
15
|
+
export type ItemDropProps = {
|
|
16
|
+
commit: () => void;
|
|
17
|
+
dragProps: ItemDragProps;
|
|
18
|
+
itemLayout: ConfigLayout;
|
|
19
|
+
newLayout: ConfigLayout[];
|
|
20
|
+
};
|
|
@@ -36,4 +36,5 @@ export interface PluginDefaultLayout {
|
|
|
36
36
|
export interface Plugin<P extends PluginWidgetProps<T> = any, T = StringParams> extends PluginBase {
|
|
37
37
|
defaultLayout?: PluginDefaultLayout;
|
|
38
38
|
renderer: (props: P, forwardedRef: React.RefObject<any>) => React.ReactNode;
|
|
39
|
+
placeholderRenderer?: (props: P, forwardedRef: React.RefObject<any>) => React.ReactNode;
|
|
39
40
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Config, ConfigItem, ItemStateAndParams, ItemStateAndParamsChangeOptions, ItemsStateAndParams } from '../shared';
|
|
2
|
-
import type { AddConfigItem, SetItemOptions, WidgetLayout } from '../typings';
|
|
2
|
+
import type { AddConfigItem, SetItemOptions, SetNewItemOptions, WidgetLayout } from '../typings';
|
|
3
3
|
import { RegisterManagerPluginLayout } from './register-manager';
|
|
4
4
|
interface RemoveItemArg {
|
|
5
5
|
id: string;
|
|
@@ -19,7 +19,7 @@ export declare class UpdateManager {
|
|
|
19
19
|
namespace: string;
|
|
20
20
|
layout: RegisterManagerPluginLayout;
|
|
21
21
|
config: Config;
|
|
22
|
-
options:
|
|
22
|
+
options: SetNewItemOptions;
|
|
23
23
|
}): Config;
|
|
24
24
|
static editItem({ item, namespace, config, options, }: {
|
|
25
25
|
item: ConfigItem;
|
|
@@ -216,19 +216,37 @@ function changeGroupParams({ groupItemIds, initiatorId, initiatorItem, itemsStat
|
|
|
216
216
|
}
|
|
217
217
|
class UpdateManager {
|
|
218
218
|
static addItem({ item, namespace = constants_1.DEFAULT_NAMESPACE, layout, config, options, }) {
|
|
219
|
-
const layoutY = Math.max(0, ...config.layout.map(({ h, y }) => h + y));
|
|
220
|
-
const saveDefaultLayout = (0, pick_1.default)(layout, ['h', 'w', 'x', 'y']);
|
|
221
219
|
const salt = config.salt;
|
|
222
220
|
const newItemData = getNewItemData({ item, config, salt, counter: config.counter, options });
|
|
223
221
|
let counter = newItemData.counter;
|
|
224
222
|
const newIdData = (0, get_new_id_1.getNewId)({ config, salt, counter, excludeIds: newItemData.excludeIds });
|
|
225
223
|
counter = newIdData.counter;
|
|
226
224
|
const newItem = Object.assign(Object.assign({}, item), { id: newIdData.id, data: newItemData.data, namespace });
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
225
|
+
const saveDefaultLayout = (0, pick_1.default)(layout, ['h', 'w', 'x', 'y']);
|
|
226
|
+
if (options.updateLayout) {
|
|
227
|
+
const byId = options.updateLayout.reduce((memo, t) => {
|
|
228
|
+
memo[t.i] = t;
|
|
229
|
+
return memo;
|
|
230
|
+
}, {});
|
|
231
|
+
const newLayout = [
|
|
232
|
+
...config.layout.map((t) => (Object.assign(Object.assign({}, t), (byId[t.i] || {})))),
|
|
233
|
+
Object.assign(Object.assign({}, saveDefaultLayout), { i: newItem.id }),
|
|
234
|
+
];
|
|
235
|
+
return (0, immutability_helper_1.default)(config, {
|
|
236
|
+
items: { $push: [newItem] },
|
|
237
|
+
layout: { $set: newLayout },
|
|
238
|
+
counter: { $set: counter },
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
const layoutY = Math.max(0, ...config.layout.map(({ h, y }) => h + y));
|
|
243
|
+
const newLayoutItem = Object.assign(Object.assign({}, saveDefaultLayout), { y: layoutY, i: newItem.id });
|
|
244
|
+
return (0, immutability_helper_1.default)(config, {
|
|
245
|
+
items: { $push: [newItem] },
|
|
246
|
+
layout: { $push: [newLayoutItem] },
|
|
247
|
+
counter: { $set: counter },
|
|
248
|
+
});
|
|
249
|
+
}
|
|
232
250
|
}
|
|
233
251
|
static editItem({ item, namespace = constants_1.DEFAULT_NAMESPACE, config, options, }) {
|
|
234
252
|
const itemIndex = config.items.findIndex(({ id }) => item.id === id);
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
import { ActionPanelProps } from './types';
|
|
2
|
+
import { ActionPanelItem, ActionPanelProps } from './types';
|
|
3
3
|
import './ActionPanel.css';
|
|
4
|
+
export declare const ActionPanelItemContainer: ({ item }: {
|
|
5
|
+
item: ActionPanelItem;
|
|
6
|
+
}) => JSX.Element;
|
|
4
7
|
export declare const ActionPanel: (props: ActionPanelProps) => JSX.Element | null;
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { CSSTransition } from 'react-transition-group';
|
|
3
|
+
import { useDnDItemProps } from '../../hooks/useDnDItemProps';
|
|
3
4
|
import { cn } from '../../utils/cn';
|
|
4
5
|
import './ActionPanel.css';
|
|
5
6
|
const b = cn('dashkit-action-panel');
|
|
7
|
+
export const ActionPanelItemContainer = ({ item }) => {
|
|
8
|
+
const dndProps = useDnDItemProps(item);
|
|
9
|
+
return (React.createElement("div", Object.assign({ role: "button", className: b('item', { draggable: Boolean(dndProps) }, item.className), onClick: item.onClick, "data-qa": item.qa }, dndProps),
|
|
10
|
+
React.createElement("div", { className: b('icon') }, item.icon),
|
|
11
|
+
React.createElement("div", { className: b('title'), title: item.title }, item.title)));
|
|
12
|
+
};
|
|
6
13
|
export const ActionPanel = (props) => {
|
|
7
14
|
var _a, _b;
|
|
8
15
|
const isDisabled = (_a = props.disable) !== null && _a !== void 0 ? _a : false;
|
|
9
16
|
const isAnimated = (_b = props.toggleAnimation) !== null && _b !== void 0 ? _b : false;
|
|
10
17
|
const nodeRef = React.useRef(null);
|
|
11
|
-
const content = (React.createElement("div", { ref: nodeRef, className: b(null, props.className) }, props.items.map((item) => {
|
|
12
|
-
return (React.createElement("div", { role: "button", className: b('item', item.className), key: `dk-action-panel-${item.id}`, onClick: item.onClick, "data-qa": item.qa },
|
|
13
|
-
React.createElement("div", { className: b('icon') }, item.icon),
|
|
14
|
-
React.createElement("div", { className: b('title'), title: item.title }, item.title)));
|
|
15
|
-
})));
|
|
18
|
+
const content = (React.createElement("div", { ref: nodeRef, className: b(null, props.className) }, props.items.map((item) => (React.createElement(ActionPanelItemContainer, { key: `dk-action-panel-${item.id}`, item: item })))));
|
|
16
19
|
if (isAnimated) {
|
|
17
20
|
return (React.createElement(CSSTransition, { in: !isDisabled, nodeRef: nodeRef, classNames: b(null), timeout: 300, unmountOnExit: true }, content));
|
|
18
21
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { ItemDragProps } from '../../shared';
|
|
2
3
|
export type ActionPanelItem = {
|
|
3
4
|
id: string;
|
|
4
5
|
icon: React.ReactNode;
|
|
5
6
|
title: string;
|
|
6
|
-
onClick?: () => void;
|
|
7
7
|
className?: string;
|
|
8
8
|
qa?: string;
|
|
9
|
+
onClick?: () => void;
|
|
10
|
+
dragProps?: ItemDragProps;
|
|
9
11
|
};
|
|
10
12
|
export type ActionPanelProps = {
|
|
11
13
|
items: ActionPanelItem[];
|
|
@@ -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, GlobalParams, ItemDropProps, 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,6 +15,7 @@ interface DashKitDefaultProps {
|
|
|
15
15
|
config: Config;
|
|
16
16
|
itemsStateAndParams: ItemsStateAndParams;
|
|
17
17
|
}) => void;
|
|
18
|
+
onDrop: (dropProps: ItemDropProps) => void;
|
|
18
19
|
defaultGlobalParams: GlobalParams;
|
|
19
20
|
globalParams: GlobalParams;
|
|
20
21
|
itemsStateAndParams: ItemsStateAndParams;
|
|
@@ -34,7 +35,7 @@ export declare class DashKit extends React.PureComponent<DashKitInnerProps> {
|
|
|
34
35
|
item: SetConfigItem;
|
|
35
36
|
namespace?: string;
|
|
36
37
|
config: Config;
|
|
37
|
-
options?:
|
|
38
|
+
options?: SetNewItemOptions;
|
|
38
39
|
}): Config;
|
|
39
40
|
static removeItem({ id, config, itemsStateAndParams, }: {
|
|
40
41
|
id: string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ItemDragProps } from '../../shared';
|
|
3
|
+
type DashKitDnDWrapperProps = {
|
|
4
|
+
dragImageSrc?: string;
|
|
5
|
+
onDragStart?: (dragProps: ItemDragProps) => void;
|
|
6
|
+
onDragEnd?: () => void;
|
|
7
|
+
children: React.ReactElement;
|
|
8
|
+
};
|
|
9
|
+
export declare const DashKitDnDWrapper: React.FC<DashKitDnDWrapperProps>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { DashKitDnDContext } from '../../context/DashKitContext';
|
|
3
|
+
const defaultImageSrc = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=';
|
|
4
|
+
export const DashKitDnDWrapper = (props) => {
|
|
5
|
+
const [dragProps, setDragProps] = React.useState(null);
|
|
6
|
+
const dragImagePreview = React.useMemo(() => {
|
|
7
|
+
const img = new Image();
|
|
8
|
+
img.src = props.dragImageSrc || defaultImageSrc;
|
|
9
|
+
return img;
|
|
10
|
+
}, [props.dragImageSrc]);
|
|
11
|
+
const onDragStart = React.useCallback((_, itemDragProps) => {
|
|
12
|
+
var _a;
|
|
13
|
+
setDragProps(itemDragProps);
|
|
14
|
+
(_a = props.onDragStart) === null || _a === void 0 ? void 0 : _a.call(props, itemDragProps);
|
|
15
|
+
}, [setDragProps, props.onDragStart]);
|
|
16
|
+
const onDragEnd = React.useCallback((_) => {
|
|
17
|
+
var _a;
|
|
18
|
+
setDragProps(null);
|
|
19
|
+
(_a = props.onDragEnd) === null || _a === void 0 ? void 0 : _a.call(props);
|
|
20
|
+
}, [setDragProps, props.onDragEnd]);
|
|
21
|
+
const contextValue = React.useMemo(() => {
|
|
22
|
+
return {
|
|
23
|
+
dragProps,
|
|
24
|
+
dragImagePreview,
|
|
25
|
+
onDragStart,
|
|
26
|
+
onDragEnd,
|
|
27
|
+
};
|
|
28
|
+
}, [dragProps, dragImagePreview, onDragStart, onDragEnd]);
|
|
29
|
+
return (React.createElement(DashKitDnDContext.Provider, { value: contextValue }, props.children));
|
|
30
|
+
};
|
|
@@ -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';
|
|
@@ -56,9 +56,9 @@ class GridItem extends React.PureComponent {
|
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
renderOverlay() {
|
|
59
|
-
const { overlayControls } = this.props;
|
|
59
|
+
const { overlayControls, isPlaceholder } = this.props;
|
|
60
60
|
const { editMode } = this.context;
|
|
61
|
-
if (!editMode || this.props.item.data._editActive) {
|
|
61
|
+
if (!editMode || this.props.item.data._editActive || isPlaceholder) {
|
|
62
62
|
return null;
|
|
63
63
|
}
|
|
64
64
|
const { item } = this.props;
|
|
@@ -70,7 +70,7 @@ class GridItem extends React.PureComponent {
|
|
|
70
70
|
render() {
|
|
71
71
|
// из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
|
|
72
72
|
// https://github.com/STRML/react-grid-layout/issues/721
|
|
73
|
-
const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, } = this.props;
|
|
73
|
+
const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, isPlaceholder, } = this.props;
|
|
74
74
|
const { editMode } = this.context;
|
|
75
75
|
const width = Number.parseInt(style.width, 10);
|
|
76
76
|
const height = Number.parseInt(style.height, 10);
|
|
@@ -95,7 +95,7 @@ class GridItem extends React.PureComponent {
|
|
|
95
95
|
}
|
|
96
96
|
: {})),
|
|
97
97
|
React.createElement("div", { className: b('item', { editMode: editMode && !_editActive && !noOverlay }) },
|
|
98
|
-
React.createElement(Item, { 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 })),
|
|
98
|
+
React.createElement(Item, { id: this.props.id, item: this.props.item, shouldItemUpdate: !isDragging, width: width, height: height, transform: transform, isPlaceholder: isPlaceholder, adjustWidgetLayout: this.props.adjustWidgetLayout, layout: this.props.layout, forwardedPluginRef: this.props.forwardedPluginRef })),
|
|
99
99
|
!noOverlay && this.renderOverlay(),
|
|
100
100
|
preparedChildren));
|
|
101
101
|
}
|
|
@@ -109,6 +109,7 @@ GridItem.propTypes = {
|
|
|
109
109
|
overlayControls: PropTypes.object,
|
|
110
110
|
forwardedRef: PropTypes.any,
|
|
111
111
|
forwardedPluginRef: PropTypes.any,
|
|
112
|
+
isPlaceholder: PropTypes.bool,
|
|
112
113
|
// from react-grid-layout:
|
|
113
114
|
children: PropTypes.node,
|
|
114
115
|
className: PropTypes.string,
|
|
@@ -122,6 +123,8 @@ GridItem.propTypes = {
|
|
|
122
123
|
onTouchStart: PropTypes.func,
|
|
123
124
|
};
|
|
124
125
|
GridItem.contextType = DashKitContext;
|
|
125
|
-
|
|
126
|
+
const GridItemForwarderRef = React.forwardRef((props, ref) => {
|
|
126
127
|
return React.createElement(GridItem, Object.assign({}, props, { forwardedRef: ref }));
|
|
127
128
|
});
|
|
129
|
+
GridItemForwarderRef.displayName = 'forwardRef(GridItem)';
|
|
130
|
+
export default GridItemForwarderRef;
|
|
@@ -21,6 +21,9 @@ 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;
|
|
26
|
+
renderTemporaryPlaceholder(): JSX.Element | null;
|
|
24
27
|
render(): JSX.Element;
|
|
25
28
|
}
|
|
26
29
|
import React from 'react';
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
3
|
-
import { OVERLAY_CONTROLS_CLASS_NAME } from '../../constants';
|
|
2
|
+
import { OVERLAY_CONTROLS_CLASS_NAME, TEMPORARY_ITEM_ID } from '../../constants';
|
|
4
3
|
import { DashKitContext } from '../../context/DashKitContext';
|
|
5
4
|
import GridItem from '../GridItem/GridItem';
|
|
6
|
-
|
|
5
|
+
import { Layout } from './ReactGridLayout';
|
|
7
6
|
class GridLayout extends React.PureComponent {
|
|
8
7
|
constructor(props, context) {
|
|
9
8
|
super(props, context);
|
|
@@ -29,13 +28,37 @@ class GridLayout extends React.PureComponent {
|
|
|
29
28
|
return getItemsMeta(this.pluginsRefs);
|
|
30
29
|
};
|
|
31
30
|
this._onStart = () => {
|
|
31
|
+
if (this.temporaryLayout)
|
|
32
|
+
return;
|
|
32
33
|
this.setState({ isDragging: true });
|
|
33
34
|
};
|
|
34
35
|
this._onStop = (newLayout) => {
|
|
35
|
-
const { layoutChange } = this.context;
|
|
36
|
-
|
|
36
|
+
const { layoutChange, onDrop, temporaryLayout } = this.context;
|
|
37
|
+
if (temporaryLayout) {
|
|
38
|
+
onDrop === null || onDrop === void 0 ? void 0 : onDrop(newLayout, newLayout.find(({ i }) => i === TEMPORARY_ITEM_ID));
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
layoutChange(newLayout);
|
|
42
|
+
}
|
|
37
43
|
this.setState({ isDragging: false });
|
|
38
44
|
};
|
|
45
|
+
this._onDropDragOver = (e) => {
|
|
46
|
+
const { editMode, dragOverPlugin, onDropDragOver } = this.context;
|
|
47
|
+
if (!editMode || !dragOverPlugin) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
return onDropDragOver(e);
|
|
51
|
+
};
|
|
52
|
+
this._onDrop = (layout, item, e) => {
|
|
53
|
+
if (!item) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
const { editMode, onDrop } = this.context;
|
|
57
|
+
if (!editMode) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
onDrop === null || onDrop === void 0 ? void 0 : onDrop(layout, item, e);
|
|
61
|
+
};
|
|
39
62
|
this.pluginsRefs = [];
|
|
40
63
|
this.state = {
|
|
41
64
|
isDragging: false,
|
|
@@ -68,16 +91,33 @@ class GridLayout extends React.PureComponent {
|
|
|
68
91
|
this._timeout = setTimeout(() => this.reloadItems(), reloadIntervalRemains <= 0 ? autoupdateIntervalMs : reloadIntervalRemains);
|
|
69
92
|
}
|
|
70
93
|
}
|
|
94
|
+
renderTemporaryPlaceholder() {
|
|
95
|
+
const { temporaryLayout, noOverlay, draggableHandleClassName } = this.context;
|
|
96
|
+
if (!temporaryLayout || !temporaryLayout.dragProps) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
const id = TEMPORARY_ITEM_ID;
|
|
100
|
+
const { type } = temporaryLayout.dragProps;
|
|
101
|
+
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 }));
|
|
102
|
+
}
|
|
71
103
|
render() {
|
|
72
|
-
const { layout, config, registerManager, editMode, noOverlay, focusable, draggableHandleClassName, } = this.context;
|
|
104
|
+
const { layout, temporaryLayout, config, registerManager, editMode, noOverlay, focusable, draggableHandleClassName, outerDnDEnable, } = this.context;
|
|
73
105
|
this.pluginsRefs.length = config.items.length;
|
|
74
|
-
return (React.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
|
|
106
|
+
return (React.createElement(Layout, Object.assign({}, registerManager.gridLayout, { layout: (temporaryLayout === null || temporaryLayout === void 0 ? void 0 : temporaryLayout.data) || layout, isDraggable: editMode, isResizable: editMode, onDragStart: this._onStart, onDragStop: this._onStop, onResizeStart: this._onStart, onResizeStop: this._onStop }, (draggableHandleClassName
|
|
75
107
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
76
|
-
: null),
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
108
|
+
: null), (outerDnDEnable
|
|
109
|
+
? {
|
|
110
|
+
isDroppable: true,
|
|
111
|
+
onDropDragOver: this._onDropDragOver,
|
|
112
|
+
onDrop: this._onDrop,
|
|
113
|
+
}
|
|
114
|
+
: null), { draggableCancel: `.${OVERLAY_CONTROLS_CLASS_NAME}` }),
|
|
115
|
+
config.items.map((item, i) => {
|
|
116
|
+
return (React.createElement(GridItem, { forwardedPluginRef: (pluginRef) => {
|
|
117
|
+
this.pluginsRefs[i] = pluginRef;
|
|
118
|
+
}, key: item.id, id: item.id, item: item, layout: (temporaryLayout === null || temporaryLayout === void 0 ? void 0 : temporaryLayout.data) || layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
|
|
119
|
+
}),
|
|
120
|
+
this.renderTemporaryPlaceholder()));
|
|
81
121
|
}
|
|
82
122
|
}
|
|
83
123
|
GridLayout.contextType = DashKitContext;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ReactGridLayout, { WidthProvider } from 'react-grid-layout';
|
|
3
|
+
import { OVERLAY_CLASS_NAME } from '../../constants';
|
|
4
|
+
class DragOverLayout extends ReactGridLayout {
|
|
5
|
+
constructor() {
|
|
6
|
+
super(...arguments);
|
|
7
|
+
this.dragReset = () => {
|
|
8
|
+
if (this.dragEnterCounter) {
|
|
9
|
+
this.dragEnterCounter = 0;
|
|
10
|
+
this.removeDroppingPlaceholder();
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
componentDidMount() {
|
|
15
|
+
var _a;
|
|
16
|
+
(_a = super.componentDidMount) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
17
|
+
window.addEventListener('dragend', this.dragReset);
|
|
18
|
+
}
|
|
19
|
+
componentWillUnmount() {
|
|
20
|
+
window.removeEventListener('dragend', this.dragReset);
|
|
21
|
+
}
|
|
22
|
+
processGridItem(child, isDroppingItem) {
|
|
23
|
+
var _a;
|
|
24
|
+
const gridItem = (_a = super.processGridItem) === null || _a === void 0 ? void 0 : _a.call(this, child, isDroppingItem);
|
|
25
|
+
if (isDroppingItem) {
|
|
26
|
+
// Drop item from outside gets 0,0 droppingPosition
|
|
27
|
+
// centering cursor on newly creted grid item
|
|
28
|
+
// And cause grid-layout using it's own GridItem to make it look
|
|
29
|
+
// like overlay adding className
|
|
30
|
+
if (!gridItem)
|
|
31
|
+
return null;
|
|
32
|
+
const { props } = gridItem;
|
|
33
|
+
const { containerWidth, cols, w, h, rowHeight, margin, transformScale } = props;
|
|
34
|
+
const leftOffset = (((containerWidth / cols) * w) / 2 || 0) * transformScale;
|
|
35
|
+
const topOffset = ((h * rowHeight + (h - 1) * margin[1]) / 2 || 0) * transformScale;
|
|
36
|
+
return React.cloneElement(gridItem, {
|
|
37
|
+
className: OVERLAY_CLASS_NAME,
|
|
38
|
+
droppingPosition: Object.assign(Object.assign({}, props.droppingPosition), { left: props.droppingPosition.left - leftOffset, top: props.droppingPosition.top - topOffset }),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return gridItem;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// eslint-disable-next-line new-cap
|
|
45
|
+
export const Layout = WidthProvider(DragOverLayout);
|