@gravity-ui/dashkit 8.15.2 → 8.15.3

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.
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const react_1 = tslib_1.__importDefault(require("react"));
5
5
  const prop_types_1 = tslib_1.__importDefault(require("prop-types"));
6
+ const constants_1 = require("../../constants");
6
7
  const DashKitContext_1 = require("../../context/DashKitContext");
7
8
  const cn_1 = require("../../utils/cn");
8
9
  const Item_1 = tslib_1.__importDefault(require("../Item/Item"));
@@ -42,6 +43,29 @@ class GridItem extends react_1.default.PureComponent {
42
43
  this.state = {
43
44
  isFocused: false,
44
45
  };
46
+ this.onOverlayItemClick = () => {
47
+ // Creating button element to trigger focus out
48
+ const focusDummy = document.createElement('button');
49
+ const styles = {
50
+ width: '0',
51
+ height: '0',
52
+ opacity: '0',
53
+ position: 'fixed',
54
+ top: '0',
55
+ left: '0',
56
+ };
57
+ Object.entries(styles).forEach(([key, value]) => {
58
+ focusDummy.style[key] = value;
59
+ });
60
+ // requestAnimationFrame to make call after alert() or confirm()
61
+ requestAnimationFrame(() => {
62
+ // Adding elment an changing focus
63
+ document.body.appendChild(focusDummy);
64
+ focusDummy.focus();
65
+ document.body.removeChild(focusDummy);
66
+ this.setState({ isFocused: false });
67
+ });
68
+ };
45
69
  this.onFocusHandler = () => {
46
70
  this.setState({ isFocused: true });
47
71
  if (this.controller) {
@@ -91,10 +115,10 @@ class GridItem extends react_1.default.PureComponent {
91
115
  if (!editMode || this.props.item.data._editActive || isPlaceholder) {
92
116
  return null;
93
117
  }
94
- const { item } = this.props;
118
+ const { item, focusable } = this.props;
95
119
  return (react_1.default.createElement(react_1.default.Fragment, null,
96
120
  react_1.default.createElement("div", { className: b('overlay') }),
97
- react_1.default.createElement(OverlayControls_1.default, { configItem: item })));
121
+ react_1.default.createElement(OverlayControls_1.default, { configItem: item, onItemClick: focusable ? this.onOverlayItemClick : null })));
98
122
  }
99
123
  render() {
100
124
  // из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
@@ -104,9 +128,13 @@ class GridItem extends react_1.default.PureComponent {
104
128
  const width = Number.parseInt(style.width, 10);
105
129
  const height = Number.parseInt(style.height, 10);
106
130
  const transform = style.transform;
107
- const preparedClassName = editMode
131
+ const preparedClassName = (editMode
108
132
  ? className
109
- : className.replace('react-resizable', '').replace('react-draggable', '');
133
+ : className
134
+ .replace('react-resizable', '')
135
+ .replace('react-draggable', '')
136
+ .replace(constants_1.FOCUSED_CLASS_NAME, '')) +
137
+ (this.state.isFocused ? ` ${constants_1.FOCUSED_CLASS_NAME}` : '');
110
138
  const preparedChildren = editMode ? children : null;
111
139
  const reactGridLayoutProps = editMode
112
140
  ? { onMouseDown, onMouseUp, onTouchEnd, onTouchStart }
@@ -36,6 +36,7 @@ interface OverlayControlsDefaultProps {
36
36
  }
37
37
  interface OverlayControlsProps extends OverlayControlsDefaultProps {
38
38
  configItem: ConfigItem;
39
+ onItemClick?: () => void | null;
39
40
  }
40
41
  type PreparedCopyItemOptionsArg = Pick<ConfigItem, 'data' | 'type' | 'defaults' | 'namespace'> & {
41
42
  timestamp: number;
@@ -28,10 +28,13 @@ class OverlayControls extends react_1.default.Component {
28
28
  return (overlayControls && overlayControls[configItem.type]) || [];
29
29
  };
30
30
  this.renderControlsItem = (item, index, length) => {
31
- const { view, size } = this.props;
31
+ const { view, size, onItemClick } = this.props;
32
32
  const { title, handler, icon, iconSize, qa } = item;
33
33
  const onItemClickHandler = typeof handler === 'function' ? handler : noop_1.default;
34
- 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 },
34
+ return (react_1.default.createElement(uikit_1.Button, { key: index, view: view, size: size, title: title, pin: this.getControlItemPinStyle(index, length), onClick: () => {
35
+ onItemClickHandler(this.props.configItem);
36
+ onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick();
37
+ }, qa: qa },
35
38
  react_1.default.createElement(uikit_1.Icon, { data: icon || icons_1.Gear, size: icon ? iconSize : constants_1.OVERLAY_ICON_SIZE })));
36
39
  };
37
40
  this.getDefaultControls = () => {
@@ -46,6 +49,7 @@ class OverlayControls extends react_1.default.Component {
46
49
  // выбираем только items-ы у которых проставлено поле `allWidgetsControls:true`
47
50
  // те контролы, которые будут показываться слева от меню
48
51
  let controls = [];
52
+ const { onItemClick } = this.props;
49
53
  for (const controlItem of Object.values(this.context.overlayControls || {})) {
50
54
  controls = controls.concat((controlItem.filter((item) => {
51
55
  var _a;
@@ -62,14 +66,19 @@ class OverlayControls extends react_1.default.Component {
62
66
  return item;
63
67
  }
64
68
  return Object.assign(Object.assign({}, item), { handler: typeof item.handler === 'function'
65
- ? item.handler
69
+ ? (...args) => {
70
+ var _a;
71
+ const result = (_a = item.handler) === null || _a === void 0 ? void 0 : _a.call(item, ...args);
72
+ onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick();
73
+ return result;
74
+ }
66
75
  : ((_a = this.getDropDownMenuItemConfig(item.id)) === null || _a === void 0 ? void 0 : _a.action) || (() => { }) });
67
76
  }));
68
77
  }
69
78
  return controls;
70
79
  };
71
80
  this.onCopyItem = () => {
72
- var _a;
81
+ var _a, _b, _c;
73
82
  const { configItem } = this.props;
74
83
  const correspondedItemLayout = this.context.getLayoutItem(configItem.id);
75
84
  let options = {
@@ -89,13 +98,18 @@ class OverlayControls extends react_1.default.Component {
89
98
  localStorage.setItem(constants_1.COPIED_WIDGET_STORE_KEY, JSON.stringify(options));
90
99
  // https://stackoverflow.com/questions/35865481/storage-event-not-firing
91
100
  window.dispatchEvent(new Event('storage'));
101
+ (_c = (_b = this.props).onItemClick) === null || _c === void 0 ? void 0 : _c.call(_b);
92
102
  };
93
103
  this.onEditItem = () => {
104
+ var _a, _b;
94
105
  this.context.editItem(this.props.configItem);
106
+ (_b = (_a = this.props).onItemClick) === null || _b === void 0 ? void 0 : _b.call(_a);
95
107
  };
96
108
  this.onRemoveItem = () => {
109
+ var _a, _b;
97
110
  const { id } = this.props.configItem;
98
111
  this.context.removeItem(id);
112
+ (_b = (_a = this.props).onItemClick) === null || _b === void 0 ? void 0 : _b.call(_a);
99
113
  };
100
114
  }
101
115
  render() {
@@ -161,7 +175,7 @@ class OverlayControls extends react_1.default.Component {
161
175
  return menu === null || menu === void 0 ? void 0 : menu.every((item) => Object.values(constants_1.MenuItems).includes(String(item)));
162
176
  }
163
177
  renderDropdownMenu(isOnlyOneItem) {
164
- const { view, size } = this.props;
178
+ const { view, size, onItemClick } = this.props;
165
179
  const { menu: contextMenu, itemsParams, itemsState } = this.context;
166
180
  const configItem = this.props.configItem;
167
181
  const itemParams = itemsParams[configItem.id];
@@ -187,7 +201,11 @@ class OverlayControls extends react_1.default.Component {
187
201
  }
188
202
  const itemHandler = item.handler;
189
203
  const itemAction = typeof itemHandler === 'function'
190
- ? () => itemHandler(configItem, itemParams, itemState)
204
+ ? () => {
205
+ const result = itemHandler(configItem, itemParams, itemState);
206
+ onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick();
207
+ return result;
208
+ }
191
209
  : ((_a = this.getDropDownMenuItemConfig(item.id)) === null || _a === void 0 ? void 0 : _a.action) || (() => { });
192
210
  memo.push({
193
211
  // @ts-expect-error
@@ -14,3 +14,4 @@ export declare const DEFAULT_WIDGET_WIDTH = 3;
14
14
  export declare const DEFAULT_GROUP = "__default";
15
15
  export declare const COMPACT_TYPE_HORIZONTAL_NOWRAP = "horizontal-nowrap";
16
16
  export declare const DRAGGABLE_CANCEL_CLASS_NAME = "dashkit_draggable_cancel";
17
+ export declare const FOCUSED_CLASS_NAME = "dashkit_focused";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DRAGGABLE_CANCEL_CLASS_NAME = exports.COMPACT_TYPE_HORIZONTAL_NOWRAP = exports.DEFAULT_GROUP = exports.DEFAULT_WIDGET_WIDTH = exports.DEFAULT_WIDGET_HEIGHT = exports.MenuItems = exports.TEMPORARY_ITEM_ID = exports.OVERLAY_ICON_SIZE = exports.OVERLAY_CLASS_NAME = exports.OVERLAY_CONTROLS_CLASS_NAME = exports.DEFAULT_NAMESPACE = exports.COPIED_WIDGET_STORE_KEY = void 0;
3
+ exports.FOCUSED_CLASS_NAME = exports.DRAGGABLE_CANCEL_CLASS_NAME = exports.COMPACT_TYPE_HORIZONTAL_NOWRAP = exports.DEFAULT_GROUP = exports.DEFAULT_WIDGET_WIDTH = exports.DEFAULT_WIDGET_HEIGHT = exports.MenuItems = exports.TEMPORARY_ITEM_ID = exports.OVERLAY_ICON_SIZE = 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';
@@ -17,3 +17,4 @@ exports.DEFAULT_WIDGET_WIDTH = 3;
17
17
  exports.DEFAULT_GROUP = '__default';
18
18
  exports.COMPACT_TYPE_HORIZONTAL_NOWRAP = 'horizontal-nowrap';
19
19
  exports.DRAGGABLE_CANCEL_CLASS_NAME = 'dashkit_draggable_cancel';
20
+ exports.FOCUSED_CLASS_NAME = 'dashkit_focused';
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
+ import { FOCUSED_CLASS_NAME } from '../../constants';
3
4
  import { DashKitContext } from '../../context/DashKitContext';
4
5
  import { cn } from '../../utils/cn';
5
6
  import Item from '../Item/Item';
@@ -40,6 +41,29 @@ class GridItem extends React.PureComponent {
40
41
  this.state = {
41
42
  isFocused: false,
42
43
  };
44
+ this.onOverlayItemClick = () => {
45
+ // Creating button element to trigger focus out
46
+ const focusDummy = document.createElement('button');
47
+ const styles = {
48
+ width: '0',
49
+ height: '0',
50
+ opacity: '0',
51
+ position: 'fixed',
52
+ top: '0',
53
+ left: '0',
54
+ };
55
+ Object.entries(styles).forEach(([key, value]) => {
56
+ focusDummy.style[key] = value;
57
+ });
58
+ // requestAnimationFrame to make call after alert() or confirm()
59
+ requestAnimationFrame(() => {
60
+ // Adding elment an changing focus
61
+ document.body.appendChild(focusDummy);
62
+ focusDummy.focus();
63
+ document.body.removeChild(focusDummy);
64
+ this.setState({ isFocused: false });
65
+ });
66
+ };
43
67
  this.onFocusHandler = () => {
44
68
  this.setState({ isFocused: true });
45
69
  if (this.controller) {
@@ -89,10 +113,10 @@ class GridItem extends React.PureComponent {
89
113
  if (!editMode || this.props.item.data._editActive || isPlaceholder) {
90
114
  return null;
91
115
  }
92
- const { item } = this.props;
116
+ const { item, focusable } = this.props;
93
117
  return (React.createElement(React.Fragment, null,
94
118
  React.createElement("div", { className: b('overlay') }),
95
- React.createElement(OverlayControls, { configItem: item })));
119
+ React.createElement(OverlayControls, { configItem: item, onItemClick: focusable ? this.onOverlayItemClick : null })));
96
120
  }
97
121
  render() {
98
122
  // из-за бага, что Grid Items unmounts при изменении static, isDraggable, isResaizable
@@ -102,9 +126,13 @@ class GridItem extends React.PureComponent {
102
126
  const width = Number.parseInt(style.width, 10);
103
127
  const height = Number.parseInt(style.height, 10);
104
128
  const transform = style.transform;
105
- const preparedClassName = editMode
129
+ const preparedClassName = (editMode
106
130
  ? className
107
- : className.replace('react-resizable', '').replace('react-draggable', '');
131
+ : className
132
+ .replace('react-resizable', '')
133
+ .replace('react-draggable', '')
134
+ .replace(FOCUSED_CLASS_NAME, '')) +
135
+ (this.state.isFocused ? ` ${FOCUSED_CLASS_NAME}` : '');
108
136
  const preparedChildren = editMode ? children : null;
109
137
  const reactGridLayoutProps = editMode
110
138
  ? { onMouseDown, onMouseUp, onTouchEnd, onTouchStart }
@@ -37,6 +37,7 @@ interface OverlayControlsDefaultProps {
37
37
  }
38
38
  interface OverlayControlsProps extends OverlayControlsDefaultProps {
39
39
  configItem: ConfigItem;
40
+ onItemClick?: () => void | null;
40
41
  }
41
42
  type PreparedCopyItemOptionsArg = Pick<ConfigItem, 'data' | 'type' | 'defaults' | 'namespace'> & {
42
43
  timestamp: number;
@@ -25,10 +25,13 @@ class OverlayControls extends React.Component {
25
25
  return (overlayControls && overlayControls[configItem.type]) || [];
26
26
  };
27
27
  this.renderControlsItem = (item, index, length) => {
28
- const { view, size } = this.props;
28
+ const { view, size, onItemClick } = this.props;
29
29
  const { title, handler, icon, iconSize, qa } = item;
30
30
  const onItemClickHandler = typeof handler === 'function' ? handler : noop;
31
- return (React.createElement(Button, { key: index, view: view, size: size, title: title, pin: this.getControlItemPinStyle(index, length), onClick: () => onItemClickHandler(this.props.configItem), qa: qa },
31
+ return (React.createElement(Button, { key: index, view: view, size: size, title: title, pin: this.getControlItemPinStyle(index, length), onClick: () => {
32
+ onItemClickHandler(this.props.configItem);
33
+ onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick();
34
+ }, qa: qa },
32
35
  React.createElement(Icon, { data: icon || Gear, size: icon ? iconSize : OVERLAY_ICON_SIZE })));
33
36
  };
34
37
  this.getDefaultControls = () => {
@@ -43,6 +46,7 @@ class OverlayControls extends React.Component {
43
46
  // выбираем только items-ы у которых проставлено поле `allWidgetsControls:true`
44
47
  // те контролы, которые будут показываться слева от меню
45
48
  let controls = [];
49
+ const { onItemClick } = this.props;
46
50
  for (const controlItem of Object.values(this.context.overlayControls || {})) {
47
51
  controls = controls.concat((controlItem.filter((item) => {
48
52
  var _a;
@@ -59,14 +63,19 @@ class OverlayControls extends React.Component {
59
63
  return item;
60
64
  }
61
65
  return Object.assign(Object.assign({}, item), { handler: typeof item.handler === 'function'
62
- ? item.handler
66
+ ? (...args) => {
67
+ var _a;
68
+ const result = (_a = item.handler) === null || _a === void 0 ? void 0 : _a.call(item, ...args);
69
+ onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick();
70
+ return result;
71
+ }
63
72
  : ((_a = this.getDropDownMenuItemConfig(item.id)) === null || _a === void 0 ? void 0 : _a.action) || (() => { }) });
64
73
  }));
65
74
  }
66
75
  return controls;
67
76
  };
68
77
  this.onCopyItem = () => {
69
- var _a;
78
+ var _a, _b, _c;
70
79
  const { configItem } = this.props;
71
80
  const correspondedItemLayout = this.context.getLayoutItem(configItem.id);
72
81
  let options = {
@@ -86,13 +95,18 @@ class OverlayControls extends React.Component {
86
95
  localStorage.setItem(COPIED_WIDGET_STORE_KEY, JSON.stringify(options));
87
96
  // https://stackoverflow.com/questions/35865481/storage-event-not-firing
88
97
  window.dispatchEvent(new Event('storage'));
98
+ (_c = (_b = this.props).onItemClick) === null || _c === void 0 ? void 0 : _c.call(_b);
89
99
  };
90
100
  this.onEditItem = () => {
101
+ var _a, _b;
91
102
  this.context.editItem(this.props.configItem);
103
+ (_b = (_a = this.props).onItemClick) === null || _b === void 0 ? void 0 : _b.call(_a);
92
104
  };
93
105
  this.onRemoveItem = () => {
106
+ var _a, _b;
94
107
  const { id } = this.props.configItem;
95
108
  this.context.removeItem(id);
109
+ (_b = (_a = this.props).onItemClick) === null || _b === void 0 ? void 0 : _b.call(_a);
96
110
  };
97
111
  }
98
112
  render() {
@@ -158,7 +172,7 @@ class OverlayControls extends React.Component {
158
172
  return menu === null || menu === void 0 ? void 0 : menu.every((item) => Object.values(MenuItems).includes(String(item)));
159
173
  }
160
174
  renderDropdownMenu(isOnlyOneItem) {
161
- const { view, size } = this.props;
175
+ const { view, size, onItemClick } = this.props;
162
176
  const { menu: contextMenu, itemsParams, itemsState } = this.context;
163
177
  const configItem = this.props.configItem;
164
178
  const itemParams = itemsParams[configItem.id];
@@ -184,7 +198,11 @@ class OverlayControls extends React.Component {
184
198
  }
185
199
  const itemHandler = item.handler;
186
200
  const itemAction = typeof itemHandler === 'function'
187
- ? () => itemHandler(configItem, itemParams, itemState)
201
+ ? () => {
202
+ const result = itemHandler(configItem, itemParams, itemState);
203
+ onItemClick === null || onItemClick === void 0 ? void 0 : onItemClick();
204
+ return result;
205
+ }
188
206
  : ((_a = this.getDropDownMenuItemConfig(item.id)) === null || _a === void 0 ? void 0 : _a.action) || (() => { });
189
207
  memo.push({
190
208
  // @ts-expect-error
@@ -14,3 +14,4 @@ export declare const DEFAULT_WIDGET_WIDTH = 3;
14
14
  export declare const DEFAULT_GROUP = "__default";
15
15
  export declare const COMPACT_TYPE_HORIZONTAL_NOWRAP = "horizontal-nowrap";
16
16
  export declare const DRAGGABLE_CANCEL_CLASS_NAME = "dashkit_draggable_cancel";
17
+ export declare const FOCUSED_CLASS_NAME = "dashkit_focused";
@@ -14,3 +14,4 @@ export const DEFAULT_WIDGET_WIDTH = 3;
14
14
  export const DEFAULT_GROUP = '__default';
15
15
  export const COMPACT_TYPE_HORIZONTAL_NOWRAP = 'horizontal-nowrap';
16
16
  export const DRAGGABLE_CANCEL_CLASS_NAME = 'dashkit_draggable_cancel';
17
+ export const FOCUSED_CLASS_NAME = 'dashkit_focused';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/dashkit",
3
- "version": "8.15.2",
3
+ "version": "8.15.3",
4
4
  "description": "Library for rendering dashboard grid layout",
5
5
  "license": "MIT",
6
6
  "repository": {