@gravity-ui/dashkit 8.0.2 → 8.1.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/DashKit/DashKit.d.ts +1 -0
- package/build/cjs/components/DashKit/DashKit.js +1 -0
- package/build/cjs/components/GridItem/GridItem.css +7 -0
- package/build/cjs/components/GridItem/GridItem.js +58 -2
- package/build/cjs/components/GridLayout/GridLayout.js +2 -2
- package/build/cjs/hocs/withContext.js +2 -0
- package/build/esm/components/DashKit/DashKit.d.ts +1 -0
- package/build/esm/components/DashKit/DashKit.js +1 -0
- package/build/esm/components/GridItem/GridItem.css +7 -0
- package/build/esm/components/GridItem/GridItem.js +58 -2
- package/build/esm/components/GridLayout/GridLayout.js +2 -2
- package/build/esm/hocs/withContext.js +2 -0
- 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,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);
|
|
@@ -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,
|
|
@@ -72,14 +72,14 @@ class GridLayout extends react_1.default.PureComponent {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
render() {
|
|
75
|
-
const { layout, config, registerManager, editMode, noOverlay, draggableHandleClassName } = this.context;
|
|
75
|
+
const { layout, config, registerManager, editMode, noOverlay, focusable, draggableHandleClassName, } = this.context;
|
|
76
76
|
this.pluginsRefs.length = config.items.length;
|
|
77
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
|
|
78
78
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
79
79
|
: null), { draggableCancel: `.${constants_1.OVERLAY_CONTROLS_CLASS_NAME}` }), config.items.map((item, i) => {
|
|
80
80
|
return (react_1.default.createElement(GridItem_1.default, { forwardedPluginRef: (pluginRef) => {
|
|
81
81
|
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 }));
|
|
82
|
+
}, key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
|
|
83
83
|
})));
|
|
84
84
|
}
|
|
85
85
|
}
|
|
@@ -129,6 +129,7 @@ function useMemoStateContext(props) {
|
|
|
129
129
|
config: props.config,
|
|
130
130
|
context: props.context,
|
|
131
131
|
noOverlay: props.noOverlay,
|
|
132
|
+
focusable: props.focusable,
|
|
132
133
|
defaultGlobalParams: props.globalParams,
|
|
133
134
|
globalParams: props.globalParams,
|
|
134
135
|
editMode: props.editMode,
|
|
@@ -151,6 +152,7 @@ function useMemoStateContext(props) {
|
|
|
151
152
|
props.config,
|
|
152
153
|
props.context,
|
|
153
154
|
props.noOverlay,
|
|
155
|
+
props.focusable,
|
|
154
156
|
props.globalParams,
|
|
155
157
|
props.editMode,
|
|
156
158
|
props.settings,
|
|
@@ -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);
|
|
@@ -6,7 +6,55 @@ import Item from '../Item/Item';
|
|
|
6
6
|
import OverlayControls from '../OverlayControls/OverlayControls';
|
|
7
7
|
import './GridItem.css';
|
|
8
8
|
const b = cn('dashkit-grid-item');
|
|
9
|
+
class WindowFocusObserver {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.blurHandler = (e) => {
|
|
12
|
+
if (e.target === window) {
|
|
13
|
+
this.isFocused = false;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
this.focusHandler = (e) => {
|
|
17
|
+
if (e.target === window) {
|
|
18
|
+
this.isFocused = true;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
this.subscribers = 0;
|
|
22
|
+
this.isFocused = !document.hidden;
|
|
23
|
+
window.addEventListener('blur', this.blurHandler, true);
|
|
24
|
+
window.addEventListener('focus', this.focusHandler, true);
|
|
25
|
+
}
|
|
26
|
+
// Method to get state after all blur\focus events in document are triggered
|
|
27
|
+
async getFocuseState() {
|
|
28
|
+
return new Promise((resolve) => {
|
|
29
|
+
requestAnimationFrame(() => {
|
|
30
|
+
resolve(this.isFocused);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const windowFocusObserver = new WindowFocusObserver();
|
|
9
36
|
class GridItem extends React.PureComponent {
|
|
37
|
+
constructor() {
|
|
38
|
+
super(...arguments);
|
|
39
|
+
this.state = {
|
|
40
|
+
isFocused: false,
|
|
41
|
+
};
|
|
42
|
+
this.onFocusHandler = () => {
|
|
43
|
+
this.setState({ isFocused: true });
|
|
44
|
+
if (this.controller) {
|
|
45
|
+
this.controller.abort();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
this.onBlurHandler = () => {
|
|
49
|
+
this.controller = new AbortController();
|
|
50
|
+
windowFocusObserver.getFocuseState().then((isWindowFocused) => {
|
|
51
|
+
if (!this.controller.signal.aborted && isWindowFocused) {
|
|
52
|
+
this.setState({ isFocused: false });
|
|
53
|
+
}
|
|
54
|
+
this.controller = null;
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
}
|
|
10
58
|
renderOverlay() {
|
|
11
59
|
const { overlayControls } = this.props;
|
|
12
60
|
const { editMode } = this.context;
|
|
@@ -22,7 +70,7 @@ class GridItem extends React.PureComponent {
|
|
|
22
70
|
render() {
|
|
23
71
|
// из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
|
|
24
72
|
// https://github.com/STRML/react-grid-layout/issues/721
|
|
25
|
-
const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, withCustomHandle, } = this.props;
|
|
73
|
+
const { style, onMouseDown, onMouseUp, onTouchEnd, onTouchStart, children, className, isDragging, noOverlay, focusable, withCustomHandle, } = this.props;
|
|
26
74
|
const { editMode } = this.context;
|
|
27
75
|
const width = Number.parseInt(style.width, 10);
|
|
28
76
|
const height = Number.parseInt(style.height, 10);
|
|
@@ -37,8 +85,15 @@ class GridItem extends React.PureComponent {
|
|
|
37
85
|
const { _editActive } = this.props.item.data;
|
|
38
86
|
return (React.createElement("div", Object.assign({ className: b({
|
|
39
87
|
'is-dragging': isDragging,
|
|
88
|
+
'is-focused': this.state.isFocused,
|
|
40
89
|
'with-custom-handle': withCustomHandle,
|
|
41
|
-
}, preparedClassName), "data-qa": "dashkit-grid-item", style: style, ref: this.props.forwardedRef }, reactGridLayoutProps
|
|
90
|
+
}, preparedClassName), "data-qa": "dashkit-grid-item", style: style, ref: this.props.forwardedRef }, reactGridLayoutProps, (focusable
|
|
91
|
+
? {
|
|
92
|
+
onFocus: this.onFocusHandler,
|
|
93
|
+
onBlur: this.onBlurHandler,
|
|
94
|
+
tabIndex: -1,
|
|
95
|
+
}
|
|
96
|
+
: {})),
|
|
42
97
|
React.createElement("div", { className: b('item', { editMode: editMode && !_editActive && !noOverlay }) },
|
|
43
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 })),
|
|
44
99
|
!noOverlay && this.renderOverlay(),
|
|
@@ -59,6 +114,7 @@ GridItem.propTypes = {
|
|
|
59
114
|
className: PropTypes.string,
|
|
60
115
|
style: PropTypes.object,
|
|
61
116
|
noOverlay: PropTypes.bool,
|
|
117
|
+
focusable: PropTypes.bool,
|
|
62
118
|
withCustomHandle: PropTypes.bool,
|
|
63
119
|
onMouseDown: PropTypes.func,
|
|
64
120
|
onMouseUp: PropTypes.func,
|
|
@@ -69,14 +69,14 @@ class GridLayout extends React.PureComponent {
|
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
71
|
render() {
|
|
72
|
-
const { layout, config, registerManager, editMode, noOverlay, draggableHandleClassName } = this.context;
|
|
72
|
+
const { layout, config, registerManager, editMode, noOverlay, focusable, draggableHandleClassName, } = this.context;
|
|
73
73
|
this.pluginsRefs.length = config.items.length;
|
|
74
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
|
|
75
75
|
? { draggableHandle: `.${draggableHandleClassName}` }
|
|
76
76
|
: null), { draggableCancel: `.${OVERLAY_CONTROLS_CLASS_NAME}` }), config.items.map((item, i) => {
|
|
77
77
|
return (React.createElement(GridItem, { forwardedPluginRef: (pluginRef) => {
|
|
78
78
|
this.pluginsRefs[i] = pluginRef;
|
|
79
|
-
}, 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 }));
|
|
79
|
+
}, key: item.id, id: item.id, item: item, layout: layout, adjustWidgetLayout: this.adjustWidgetLayout, isDragging: this.state.isDragging, noOverlay: noOverlay, focusable: focusable, withCustomHandle: Boolean(draggableHandleClassName), overlayControls: this.props.overlayControls }));
|
|
80
80
|
})));
|
|
81
81
|
}
|
|
82
82
|
}
|
|
@@ -125,6 +125,7 @@ function useMemoStateContext(props) {
|
|
|
125
125
|
config: props.config,
|
|
126
126
|
context: props.context,
|
|
127
127
|
noOverlay: props.noOverlay,
|
|
128
|
+
focusable: props.focusable,
|
|
128
129
|
defaultGlobalParams: props.globalParams,
|
|
129
130
|
globalParams: props.globalParams,
|
|
130
131
|
editMode: props.editMode,
|
|
@@ -147,6 +148,7 @@ function useMemoStateContext(props) {
|
|
|
147
148
|
props.config,
|
|
148
149
|
props.context,
|
|
149
150
|
props.noOverlay,
|
|
151
|
+
props.focusable,
|
|
150
152
|
props.globalParams,
|
|
151
153
|
props.editMode,
|
|
152
154
|
props.settings,
|