@sima-land/ui-nucleons 41.2.0 → 42.0.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/alert/index.d.ts CHANGED
@@ -8,8 +8,6 @@ export interface AlertProps extends WithBodyScrollLock {
8
8
  className?: string;
9
9
  /** Содержимое "подвала". */
10
10
  footer?: React.ReactNode;
11
- /** Нужно ли выводить в Layer. */
12
- inPortal?: boolean;
13
11
  /** Свойства компонента NavBar. */
14
12
  navBarProps?: NavBarProps;
15
13
  /** Заголовок. */
@@ -26,4 +24,4 @@ export interface AlertProps extends WithBodyScrollLock {
26
24
  * @param props Свойства.
27
25
  * @return Элемент.
28
26
  */
29
- export declare const Alert: ({ inPortal, ...restProps }: AlertProps) => JSX.Element;
27
+ export declare const Alert: ({ children, className, footer, navBarProps, title, withDivideNavBar, withNavBar, withScrollDisable, scrollDisableOptions, onClose, }: AlertProps) => JSX.Element;
package/alert/index.js CHANGED
@@ -18,24 +18,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
18
18
  __setModuleDefault(result, mod);
19
19
  return result;
20
20
  };
21
- var __rest = (this && this.__rest) || function (s, e) {
22
- var t = {};
23
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
24
- t[p] = s[p];
25
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
26
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
27
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
28
- t[p[i]] = s[p[i]];
29
- }
30
- return t;
31
- };
32
21
  var __importDefault = (this && this.__importDefault) || function (mod) {
33
22
  return (mod && mod.__esModule) ? mod : { "default": mod };
34
23
  };
35
24
  Object.defineProperty(exports, "__esModule", { value: true });
36
25
  exports.Alert = void 0;
37
26
  const react_1 = __importStar(require("react"));
38
- const portal_1 = require("../portal");
39
27
  const nav_bar_1 = require("../nav-bar");
40
28
  const bind_1 = __importDefault(require("classnames/bind"));
41
29
  const alert_module_scss_1 = __importDefault(require("./alert.module.scss"));
@@ -48,27 +36,15 @@ const cx = bind_1.default.bind(alert_module_scss_1.default);
48
36
  * @param props Свойства.
49
37
  * @return Элемент.
50
38
  */
51
- const Alert = (_a) => {
52
- var { inPortal = true } = _a, restProps = __rest(_a, ["inPortal"]);
39
+ const Alert = ({ children, className, footer, navBarProps, title, withDivideNavBar, withNavBar = Boolean(title), withScrollDisable = false, scrollDisableOptions, onClose, }) => {
53
40
  const layer = (0, layer_1.useLayer)() + 100;
54
- const Wrapper = inPortal ? portal_1.Portal : react_1.Fragment;
55
- return (react_1.default.createElement(layer_1.LayerProvider, { value: layer },
56
- react_1.default.createElement(Wrapper, null,
57
- react_1.default.createElement(AlertInner, Object.assign({}, restProps)))));
58
- };
59
- exports.Alert = Alert;
60
- /**
61
- * Промежуточный компонент, необходимый для того чтобы не передавать реф для блокировки прокрутки через портал.
62
- * @param props Свойства.
63
- * @return Элемент.
64
- */
65
- const AlertInner = ({ children, className, footer, navBarProps, title, withDivideNavBar, withNavBar = Boolean(title), withScrollDisable = false, scrollDisableOptions, onClose, }) => {
66
41
  const rootRef = (0, react_1.useRef)(null);
67
- const layer = (0, layer_1.useLayer)();
68
42
  (0, body_scroll_1.useBodyScrollLock)(rootRef, withScrollDisable, Object.assign({ allowTouchMove: body_scroll_1.allowTouchMove }, scrollDisableOptions));
69
- return (react_1.default.createElement("div", { ref: rootRef, className: cx('overlay'), style: { zIndex: layer }, onClick: e => e.target === e.currentTarget && (onClose === null || onClose === void 0 ? void 0 : onClose()), "data-testid": 'alert:overlay' },
70
- react_1.default.createElement("div", { className: cx('alert', className), "data-testid": 'alert' },
71
- withNavBar && (react_1.default.createElement(nav_bar_1.NavBar, Object.assign({}, navBarProps, { title: title, bottomBordered: withDivideNavBar, className: cx('header') }))),
72
- react_1.default.createElement("div", { className: cx('main') }, children),
73
- Boolean(footer) && react_1.default.createElement("div", { className: borders_1.InnerBorder.top }, footer))));
43
+ return (react_1.default.createElement(layer_1.LayerProvider, { value: layer },
44
+ react_1.default.createElement("div", { ref: rootRef, className: cx('overlay'), style: { zIndex: layer }, onClick: e => e.target === e.currentTarget && (onClose === null || onClose === void 0 ? void 0 : onClose()), "data-testid": 'alert:overlay' },
45
+ react_1.default.createElement("div", { className: cx('alert', className), "data-testid": 'alert' },
46
+ withNavBar && (react_1.default.createElement(nav_bar_1.NavBar, Object.assign({}, navBarProps, { title: title, bottomBordered: withDivideNavBar, className: cx('header') }))),
47
+ react_1.default.createElement("div", { className: cx('main') }, children),
48
+ Boolean(footer) && react_1.default.createElement("div", { className: borders_1.InnerBorder.top }, footer)))));
74
49
  };
50
+ exports.Alert = Alert;
@@ -238,7 +238,9 @@ class Draggable extends react_1.Component {
238
238
  render() {
239
239
  const { children, containerProps = {}, transitionDuration: duration = 320 } = this.props;
240
240
  const { x, y } = this.currentOffset;
241
- return (react_1.default.createElement("div", Object.assign({}, containerProps, { className: cx('draggable-container', containerProps.className), onClick: this.handleClick, onMouseDown: this.startCapture, onTouchStart: this.startCapture }),
241
+ return (react_1.default.createElement("div", Object.assign({}, containerProps, { className: cx('draggable-container', containerProps.className),
242
+ // обрабатываем захват чтобы при обработке клика на дочернем элементе defaultPrevented уже был true
243
+ onClickCapture: this.handleClick, onMouseDown: this.startCapture, onTouchStart: this.startCapture }),
242
244
  react_1.default.createElement("div", { ref: this.draggableRef, style: {
243
245
  transform: (0, styles_1.getTranslateStyle)(x, y),
244
246
  transition: this.hasTransition ? (0, styles_1.getTransitionStyle)(duration, 'transform') : '',
@@ -77,7 +77,7 @@ export declare class Carousel extends Component<CarouselProps, State> {
77
77
  * @param index Индекс.
78
78
  * @return Элемент списка.
79
79
  */
80
- static defaultRenderItem(item: any, index: React.Key): JSX.Element;
80
+ static defaultRenderItem(item: any, index: number): JSX.Element;
81
81
  /**
82
82
  * Возвращает кнопку управления.
83
83
  * @param data Данные для вывода кнопки.
@@ -179,7 +179,7 @@ export declare class Carousel extends Component<CarouselProps, State> {
179
179
  */
180
180
  moveBackwardFinite(step: number): void;
181
181
  /**
182
- * Выполняет прокрутка в бесконечном режиме.
182
+ * Выполняет прокрутку в бесконечном режиме.
183
183
  * @param step Количество элементов для прокрутки.
184
184
  * @param forward Нужно выполнить прокрутку вперед?
185
185
  */
package/carousel/index.js CHANGED
@@ -276,7 +276,7 @@ class Carousel extends react_1.Component {
276
276
  this.setCurrentIndex(newIndex !== -1 && newIndex - step >= 0 ? newIndex - step : 0);
277
277
  }
278
278
  /**
279
- * Выполняет прокрутка в бесконечном режиме.
279
+ * Выполняет прокрутку в бесконечном режиме.
280
280
  * @param step Количество элементов для прокрутки.
281
281
  * @param forward Нужно выполнить прокрутку вперед?
282
282
  */
package/modal/index.d.ts CHANGED
@@ -13,8 +13,6 @@ export interface ModalProps extends WithBodyScrollLock {
13
13
  onClose?: () => void;
14
14
  /** Размер окна. */
15
15
  size?: ModalSize;
16
- /** Нужно ли выводить элемент в портале (для SSR следует указывать false). */
17
- inPortal?: boolean;
18
16
  /** Идентификатор для систем автоматизированного тестирования. */
19
17
  'data-testid'?: string;
20
18
  }
package/modal/index.js CHANGED
@@ -18,17 +18,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
18
18
  __setModuleDefault(result, mod);
19
19
  return result;
20
20
  };
21
- var __rest = (this && this.__rest) || function (s, e) {
22
- var t = {};
23
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
24
- t[p] = s[p];
25
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
26
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
27
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
28
- t[p[i]] = s[p[i]];
29
- }
30
- return t;
31
- };
32
21
  var __importDefault = (this && this.__importDefault) || function (mod) {
33
22
  return (mod && mod.__esModule) ? mod : { "default": mod };
34
23
  };
@@ -39,7 +28,6 @@ const top_bar_1 = require("../top-bar");
39
28
  const bottom_bar_1 = require("../bottom-bar");
40
29
  const utils_1 = require("./utils");
41
30
  const shadows_1 = require("../styling/shadows");
42
- const portal_1 = require("../portal");
43
31
  const lodash_1 = require("lodash");
44
32
  const slots_1 = require("./slots");
45
33
  const layer_1 = require("../helpers/layer");
@@ -53,19 +41,7 @@ const cx = bind_1.default.bind(modal_module_scss_1.default);
53
41
  * @param props Свойства.
54
42
  * @return Элемент.
55
43
  */
56
- const Modal = (_a) => {
57
- var { inPortal } = _a, restProps = __rest(_a, ["inPortal"]);
58
- const Wrapper = inPortal ? portal_1.Portal : react_1.Fragment;
59
- return (react_1.default.createElement(Wrapper, null,
60
- react_1.default.createElement(ModalInner, Object.assign({}, restProps))));
61
- };
62
- exports.Modal = Modal;
63
- /**
64
- * Внутренний компонент для того чтобы не прокидывать реф через портал.
65
- * @param props Свойства.
66
- * @return Элемент.
67
- */
68
- const ModalInner = ({ children, height, onClose, scrollDisableOptions = { reserveScrollBarGap: true }, size = 'm', withScrollDisable = false, 'data-testid': testId = 'modal', }) => {
44
+ const Modal = ({ children, height, onClose, scrollDisableOptions = { reserveScrollBarGap: true }, size = 'm', withScrollDisable = false, 'data-testid': testId = 'modal', }) => {
69
45
  const layer = (0, layer_1.useLayer)() + 100;
70
46
  const rootRef = (0, react_1.useRef)(null);
71
47
  const bind = (0, utils_1.useCloseHandler)(onClose);
@@ -102,6 +78,7 @@ const ModalInner = ({ children, height, onClose, scrollDisableOptions = { reserv
102
78
  !footer && !fullscreen && react_1.default.createElement("div", { className: cx('footer-stub') }),
103
79
  !fullscreen && overlap && react_1.default.createElement("div", { className: cx('overlap') }, overlap))));
104
80
  };
81
+ exports.Modal = Modal;
105
82
  exports.Modal.Header = slots_1.ModalHeader;
106
83
  exports.Modal.Body = slots_1.ModalBody;
107
84
  exports.Modal.Footer = slots_1.ModalFooter;
package/modal/utils.d.ts CHANGED
@@ -1,9 +1,10 @@
1
+ import React from 'react';
1
2
  /**
2
3
  * Вызывает callback только если клик был начат и закончен по одному и тому же элементу.
3
4
  * @param callback Сработает при клике.
4
5
  * @return Свойства для целевого элемента.
5
6
  */
6
7
  export declare const useCloseHandler: (callback?: (() => void) | undefined) => {
7
- onMouseUp: ({ target, currentTarget, button }: any) => void;
8
- onMouseDown: ({ button, target }: any) => void;
8
+ onMouseUp: ({ target, currentTarget, button }: React.MouseEvent) => void;
9
+ onMouseDown: ({ button, target }: React.MouseEvent) => void;
9
10
  };
package/modal/utils.js CHANGED
@@ -2,12 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useCloseHandler = void 0;
4
4
  const react_1 = require("react");
5
+ const identity_1 = require("../hooks/identity");
5
6
  /**
6
7
  * Вызывает callback только если клик был начат и закончен по одному и тому же элементу.
7
8
  * @param callback Сработает при клике.
8
9
  * @return Свойства для целевого элемента.
9
10
  */
10
11
  const useCloseHandler = (callback) => {
12
+ const callbackRef = (0, identity_1.useIdentityRef)(callback);
11
13
  const mouseDownTarget = (0, react_1.useRef)();
12
14
  const onMouseDown = (0, react_1.useCallback)(({ button, target }) => {
13
15
  if (button === 0) {
@@ -15,12 +17,13 @@ const useCloseHandler = (callback) => {
15
17
  }
16
18
  }, []);
17
19
  const onMouseUp = (0, react_1.useCallback)(({ target, currentTarget, button }) => {
18
- callback &&
20
+ const fn = callbackRef.current;
21
+ fn &&
19
22
  button === 0 &&
20
23
  target === currentTarget &&
21
24
  currentTarget === mouseDownTarget.current &&
22
- callback();
23
- }, [callback]);
25
+ fn();
26
+ }, []);
24
27
  return { onMouseUp, onMouseDown };
25
28
  };
26
29
  exports.useCloseHandler = useCloseHandler;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sima-land/ui-nucleons",
3
- "version": "41.2.0",
3
+ "version": "42.0.0",
4
4
  "repository": "ssh://git@github.com:sima-land/ui-nucleons.git",
5
5
  "author": "www.sima-land.ru team",
6
6
  "license": "Apache-2.0",
@@ -22,21 +22,20 @@
22
22
  },
23
23
  "devDependencies": {
24
24
  "@babel/core": "^7.16.0",
25
- "@babel/plugin-proposal-class-properties": "^7.16.0",
26
- "@babel/plugin-proposal-optional-chaining": "^7.16.0",
27
25
  "@babel/preset-env": "^7.16.4",
28
26
  "@babel/preset-react": "^7.16.0",
27
+ "@babel/preset-typescript": "^7.16.5",
29
28
  "@rushstack/eslint-patch": "^1.1.0",
30
29
  "@sima-land/linters": "^2.1.1",
31
- "@storybook/addon-actions": "^6.3.12",
32
- "@storybook/addon-backgrounds": "^6.3.12",
33
- "@storybook/addon-docs": "^6.3.12",
34
- "@storybook/addon-storysource": "^6.3.12",
35
- "@storybook/addons": "^6.3.12",
36
- "@storybook/builder-webpack5": "^6.3.12",
37
- "@storybook/manager-webpack5": "^6.3.12",
38
- "@storybook/react": "^6.3.12",
39
- "@storybook/theming": "^6.3.12",
30
+ "@storybook/addon-actions": "^6.4.13",
31
+ "@storybook/addon-backgrounds": "^6.4.13",
32
+ "@storybook/addon-docs": "^6.4.13",
33
+ "@storybook/addon-storysource": "^6.4.13",
34
+ "@storybook/addons": "^6.4.13",
35
+ "@storybook/builder-webpack5": "^6.4.13",
36
+ "@storybook/manager-webpack5": "^6.4.13",
37
+ "@storybook/react": "^6.4.13",
38
+ "@storybook/theming": "^6.4.13",
40
39
  "@svgr/core": "^5.5.0",
41
40
  "@svgr/plugin-svgo": "^5.5.0",
42
41
  "@svgr/webpack": "^5.5.0",
@@ -51,6 +50,7 @@
51
50
  "@typescript-eslint/eslint-plugin": "^5.4.0",
52
51
  "@typescript-eslint/parser": "^5.4.0",
53
52
  "@wojtekmaj/enzyme-adapter-react-17": "^0.6.5",
53
+ "babel-jest": "^27.4.6",
54
54
  "babel-loader": "^8.2.3",
55
55
  "babel-preset-jest": "^27.2.0",
56
56
  "copyfiles": "^2.4.1",
@@ -60,7 +60,6 @@
60
60
  "eslint": "^7.31.0",
61
61
  "file-loader": "^6.2.0",
62
62
  "husky": "^7.0.4",
63
- "identity-obj-proxy": "^3.0.0",
64
63
  "jest": "^27.3.1",
65
64
  "jest-css-modules-transform": "^4.3.0",
66
65
  "lint-staged": "^12.1.2",
@@ -74,7 +73,6 @@
74
73
  "sass-loader": "^10.1.0",
75
74
  "style-loader": "^2.0.0",
76
75
  "stylelint": "^14.1.0",
77
- "ts-jest": "^27.0.7",
78
76
  "typescript": "^4.5.2",
79
77
  "typescript-plugin-css-modules": "^3.4.0",
80
78
  "webpack": "^5.64.2"
@@ -89,13 +87,13 @@
89
87
  "build:main": "tsc --project tsconfig.build.json",
90
88
  "build:after": "node dist.js",
91
89
  "build": "npm run build:before && npm run build:main && npm run build:after",
92
- "test": "jest",
90
+ "test": "BROWSERSLIST_ENV=\"test\" npx jest",
91
+ "coverage": "jest --clearCache && BROWSERSLIST_ENV=\"test\" npx jest --coverage",
93
92
  "type-check": "tsc -p . --noEmit",
94
- "coverage": "jest --clearCache && jest --coverage",
95
93
  "lint:scripts": "eslint --cache src/ --ext .js,.jsx,.ts,.tsx",
96
94
  "lint:styles": "stylelint 'src/**/*.{css,scss}'",
97
- "storybook": "start-storybook -p 9009 -c .storybook",
98
- "storybook:build": "build-storybook --quiet --loglevel error -o build-storybook",
95
+ "storybook": "BROWSERSLIST_ENV=\"storybook\" npx start-storybook -p 9009 -c .storybook",
96
+ "storybook:build": "BROWSERSLIST_ENV=\"storybook\" npx build-storybook --quiet --loglevel error -o build-storybook",
99
97
  "prettier": "prettier --write \"./src/**/*.{js,jsx,ts,tsx,css,scss}\" --loglevel error",
100
98
  "prettier:check": "prettier --check \"./src/**/*.{js,jsx,ts,tsx,css,scss}\" --loglevel error"
101
99
  }
package/rating/index.js CHANGED
@@ -27,7 +27,7 @@ const cx = bind_1.default.bind(rating_module_scss_1.default);
27
27
  * @return Элемент.
28
28
  */
29
29
  const Rating = (_a) => {
30
- var { size, value, className, 'data-testid': testId = 'rating' } = _a, restProps = __rest(_a, ["size", "value", "className", 'data-testid']);
30
+ var { size = 's', value, className, 'data-testid': testId = 'rating' } = _a, restProps = __rest(_a, ["size", "value", "className", 'data-testid']);
31
31
  return (react_1.default.createElement("div", Object.assign({}, restProps, { className: cx('root', className), "data-testid": testId, "data-rating": value }), (0, utils_1.getStars)(Math.min(5, value), 5).map((type, index) => (react_1.default.createElement(Star, { key: index, type: type, size: size })))));
32
32
  };
33
33
  exports.Rating = Rating;
@@ -36,7 +36,7 @@ exports.Rating = Rating;
36
36
  * @param props Свойства.
37
37
  * @return Элемент.
38
38
  */
39
- const Star = ({ type, size = 's' }) => (react_1.default.createElement("div", { className: cx('star', `size-${size}`) },
39
+ const Star = ({ type, size }) => (react_1.default.createElement("div", { className: cx('star', `size-${size}`) },
40
40
  type === 'empty' && react_1.default.createElement(star_svg_1.default, { className: cx('svg') }),
41
41
  type === 'half' && (react_1.default.createElement(react_1.default.Fragment, null,
42
42
  react_1.default.createElement(star_svg_1.default, { className: cx('svg') }),
package/select/index.d.ts CHANGED
@@ -22,5 +22,5 @@ export interface SelectProps extends Omit<TextFieldProps, 'style'> {
22
22
  * @param props Свойства.
23
23
  * @return Элемент.
24
24
  */
25
- export declare const Select: React.FC<SelectProps>;
25
+ export declare const Select: ({ options, optionSize, onSelect, style, className, label, onClick, value, loading, onMenuToggle, renderOption, "data-testid": dataTestId, size, ...restProps }: SelectProps) => JSX.Element;
26
26
  export {};
package/select/index.js CHANGED
@@ -45,6 +45,7 @@ const up_1 = __importDefault(require("@sima-land/ui-quarks/icons/16x16/Stroked/A
45
45
  const select_module_scss_1 = __importDefault(require("./select.module.scss"));
46
46
  const colors_1 = require("../colors");
47
47
  const dropdown_loading_1 = require("../_internal/dropdown-loading");
48
+ const hooks_1 = require("../hooks");
48
49
  const cx = bind_1.default.bind(select_module_scss_1.default);
49
50
  /**
50
51
  * Поле выбора из списка.
@@ -52,31 +53,44 @@ const cx = bind_1.default.bind(select_module_scss_1.default);
52
53
  * @return Элемент.
53
54
  */
54
55
  const Select = (_a) => {
55
- var { options, optionSize, onSelect, style, className, label, onClick, value, loading, onMenuToggle, renderOption = String, 'data-testid': dataTestId } = _a, restProps = __rest(_a, ["options", "optionSize", "onSelect", "style", "className", "label", "onClick", "value", "loading", "onMenuToggle", "renderOption", 'data-testid']);
56
+ var { options, optionSize, onSelect, style, className, label, onClick, value, loading, onMenuToggle, renderOption = String, 'data-testid': dataTestId, size } = _a, restProps = __rest(_a, ["options", "optionSize", "onSelect", "style", "className", "label", "onClick", "value", "loading", "onMenuToggle", "renderOption", 'data-testid', "size"]);
57
+ const rootRef = (0, react_1.useRef)(null);
56
58
  const fieldRef = (0, react_1.useRef)(null);
57
59
  const menuRef = (0, react_1.useRef)(null);
58
60
  const [opened, toggleMenu] = (0, react_1.useState)(false);
59
61
  const ArrowSVG = opened ? up_1.default : down_1.default;
60
62
  (0, react_1.useEffect)(() => {
61
- opened && menuRef.current.focus();
63
+ opened && menuRef.current && menuRef.current.focus();
62
64
  onMenuToggle && onMenuToggle(opened);
63
65
  }, [opened]);
64
- return (react_1.default.createElement("div", { style: style, className: cx('root', className), "data-testid": dataTestId },
65
- react_1.default.createElement(text_field_1.TextField, Object.assign({}, restProps, { readOnly: true, "data-testid": 'select:field', ref: fieldRef, variant: 'desktop', label: label, value: value, multiline: false, focused: opened, onClick: e => {
66
- toggleMenu(o => !o);
67
- onClick && onClick(e);
68
- }, onBlur: ({ relatedTarget }) => {
69
- relatedTarget !== menuRef.current && toggleMenu(false);
70
- }, onKeyDown: (e) => {
71
- e.key === 'Enter' && toggleMenu(true);
72
- }, className: cx('field'), endAdornment: react_1.default.createElement(ArrowSVG, { fill: colors_1.COLORS.get('gray38') }) })),
73
- opened && (loading || options.length > 0) && (react_1.default.createElement(dropdown_1.Dropdown, Object.assign({}, (0, dropdown_2.placeDropdown)(restProps.size), { ref: menuRef, "data-testid": 'select:menu', tabIndex: -1, className: cx('menu'), onBlur: () => {
74
- toggleMenu(false);
75
- }, role: 'menu', onKeyDown: (event) => {
66
+ (0, hooks_1.useOutsideClick)(rootRef, toggleMenu.bind(null, false));
67
+ return (react_1.default.createElement("div", { ref: rootRef, style: style, className: cx('root', className), "data-testid": dataTestId },
68
+ react_1.default.createElement(text_field_1.TextField, Object.assign({}, restProps, { size: size, blockProps: {
69
+ ref: fieldRef,
70
+ tabIndex: 0,
71
+ onMouseDown: () => {
72
+ toggleMenu(a => !a);
73
+ },
74
+ onKeyDown: e => {
75
+ e.key === 'Enter' && toggleMenu(true);
76
+ },
77
+ onClick: e => {
78
+ e.preventDefault();
79
+ onClick && onClick(e);
80
+ },
81
+ }, className: select_module_scss_1.default.field, "data-testid": 'select:field', label: label, focused: opened, baseInputProps: {
82
+ // чтобы не ловить фокус на поле
83
+ style: { pointerEvents: 'none' },
84
+ tabIndex: -1,
85
+ }, value: value, multiline: false, variant: 'desktop', readOnly: true, endAdornment: react_1.default.createElement(ArrowSVG, { fill: colors_1.COLORS.get('gray38') }) })),
86
+ opened && (loading || options.length > 0) && (react_1.default.createElement(dropdown_1.Dropdown, Object.assign({}, (0, dropdown_2.placeDropdown)(size), { ref: menuRef, "data-testid": 'select:menu', role: 'menu', tabIndex: -1, className: cx('menu'), onKeyDown: event => {
76
87
  if (event.key === 'Enter') {
77
88
  toggleMenu(false);
78
89
  fieldRef.current && fieldRef.current.focus();
79
90
  }
91
+ }, onBlur: () => {
92
+ toggleMenu(false);
93
+ fieldRef.current && fieldRef.current.focus();
80
94
  } }), loading ? (react_1.default.createElement(dropdown_loading_1.DropdownLoading, { "data-testid": 'select:loading-area' })) : (options.map((option, index) => (react_1.default.createElement(dropdown_item_1.DropdownItem, { size: optionSize, key: index, role: 'menuitem', onClick: () => {
81
95
  toggleMenu(false);
82
96
  onSelect && onSelect(option);
@@ -41,7 +41,7 @@ export declare const SidePage: {
41
41
  };
42
42
  Body: {
43
43
  ({ children }: {
44
- children?: React.ReactNode; /** Обработчик "onExiting" для CSSTransition. */
44
+ children?: React.ReactNode;
45
45
  }): JSX.Element;
46
46
  displayName: string;
47
47
  };
@@ -81,10 +81,11 @@ const SidePageInner = ({ size = 'm', children, onClose, withScrollDisable, scrol
81
81
  });
82
82
  (0, body_scroll_1.useBodyScrollLock)(ref, withScrollDisable, scrollDisableOptions);
83
83
  return (react_1.default.createElement("div", Object.assign({ ref: ref, className: cx('overlay'), style: overlayStyles }, (transitionStatus !== 'entering' && overlayBind)),
84
- react_1.default.createElement("div", { className: cx('main', `size-${size}`) },
85
- header,
86
- react_1.default.createElement("div", { className: cx('body') }, body),
87
- footer)));
84
+ react_1.default.createElement(layer_1.LayerProvider, { value: layer },
85
+ react_1.default.createElement("div", { className: cx('main', `size-${size}`) },
86
+ header,
87
+ react_1.default.createElement("div", { className: cx('body') }, body),
88
+ footer))));
88
89
  };
89
90
  exports.SidePage.Header = slots_1.SidePageHeader;
90
91
  exports.SidePage.Body = slots_1.SidePageBody;
@@ -46,6 +46,8 @@ export interface TextFieldProps extends Omit<React.InputHTMLAttributes<HTMLInput
46
46
  startAdornment?: React.ReactNode;
47
47
  /** Вариант отображения. */
48
48
  variant?: Variant;
49
+ /** Свойства элемента-блока. */
50
+ blockProps?: React.HTMLProps<HTMLDivElement>;
49
51
  /** Идентификатор для систем автоматизированного тестирования. */
50
52
  'data-testid'?: string;
51
53
  }
@@ -51,7 +51,7 @@ const modifiersToClasses = ({ disabled, failed, focused, variant, }) => cx(disab
51
51
  * @param props Свойства.
52
52
  * @return Элемент.
53
53
  */
54
- exports.TextField = (0, react_1.forwardRef)(function TextField({ autoFocus, caption, classes = {}, defaultValue, disabled, endAdornment, failed, focused: asFocused, label, onClick, onBlur, onChange, onFocus, onInput, onKeyDown, onKeyUp, placeholder, readOnly, rounds = 'all', size = exports.DEFAULTS.size, startAdornment, value, variant = 'desktop', multiline, baseInputProps = {}, className, restPlaceholder, style, 'data-testid': dataTestId, }, ref) {
54
+ exports.TextField = (0, react_1.forwardRef)(function TextField({ autoFocus, caption, classes = {}, defaultValue, disabled, endAdornment, failed, focused: asFocused, label, onClick, onBlur, onChange, onFocus, onInput, onKeyDown, onKeyUp, placeholder, readOnly, rounds = 'all', size = exports.DEFAULTS.size, startAdornment, value, variant = 'desktop', multiline, baseInputProps = {}, className, restPlaceholder, style, blockProps, 'data-testid': dataTestId, }, ref) {
55
55
  const [hasValue, toggleHasValue] = (0, react_1.useState)(isVisible(value) || isVisible(defaultValue));
56
56
  const [reallyFocused, toggleFocused] = (0, react_1.useState)(autoFocus);
57
57
  const focused = reallyFocused || Boolean(asFocused);
@@ -70,21 +70,25 @@ exports.TextField = (0, react_1.forwardRef)(function TextField({ autoFocus, capt
70
70
  (0, react_1.useImperativeHandle)(ref, () => baseInputRef.current);
71
71
  (0, react_1.useEffect)(() => toggleHasValue(Boolean(baseInputRef.current.value)));
72
72
  return (react_1.default.createElement("div", { "data-testid": dataTestId, className: cx('root', className, classes.root), style: style },
73
- react_1.default.createElement("div", { "data-testid": 'text-field:block', className: cx('reset', 'input-block', commonModifyClasses, size && `size-${size}`, focused && classes.blockFocused, multiline && 'multiline', withLabel && 'with-label', variant === 'desktop' && rounds !== 'none' && shapes_1.SmallRounds[rounds]), onClick: event => {
73
+ react_1.default.createElement("div", Object.assign({ "data-testid": 'text-field:block', className: cx('reset', 'input-block', commonModifyClasses, size && `size-${size}`, focused && classes.blockFocused, multiline && 'multiline', withLabel && 'with-label', variant === 'desktop' && rounds !== 'none' && shapes_1.SmallRounds[rounds], blockProps === null || blockProps === void 0 ? void 0 : blockProps.className), onClick: event => {
74
74
  const input = baseInputRef.current;
75
75
  onClick === null || onClick === void 0 ? void 0 : onClick(event);
76
- input && !disabled && input !== document.activeElement && input.focus();
77
- } },
76
+ input &&
77
+ !disabled &&
78
+ !event.defaultPrevented &&
79
+ input !== document.activeElement &&
80
+ input.focus();
81
+ } }, blockProps),
78
82
  !multiline && Boolean(startAdornment) && (react_1.default.createElement(box_1.Box, { display: 'flex', alignItems: 'center', marginRight: 4 }, startAdornment)),
79
83
  react_1.default.createElement("div", { className: cx('main-column') },
80
- withLabel && (react_1.default.createElement("label", { className: cx('label', commonModifyClasses, hasValue && 'filled', labelAsPlaceholder && 'as-placeholder'), children: label })),
84
+ withLabel && (react_1.default.createElement("label", { className: cx('label', commonModifyClasses, hasValue && 'filled', labelAsPlaceholder && 'as-placeholder'), children: label, "data-testid": 'text-field:label' })),
81
85
  react_1.default.createElement("div", { className: cx('input-wrapper') },
82
86
  react_1.default.createElement(base_input_1.BaseInput, Object.assign({}, baseInputProps, { "data-testid": 'text-field:field', multiline: multiline, ref: baseInputRef, placeholder: withLabel && labelAsPlaceholder ? undefined : placeholder, restPlaceholder: withLabel && labelAsPlaceholder ? undefined : restPlaceholder, autoFocus: autoFocus, className: cx('base-input', commonModifyClasses, classes.baseInput, size && `size-${size}`), defaultValue: defaultValue, value: value, readOnly: readOnly, disabled: disabled, onFocus: (event) => {
83
- (0, lodash_1.isFunction)(onFocus) && onFocus(event);
87
+ onFocus && onFocus(event);
84
88
  toggleHasValue(Boolean(event.target.value));
85
89
  toggleFocused(true);
86
90
  }, onBlur: (event) => {
87
- (0, lodash_1.isFunction)(onBlur) && onBlur(event);
91
+ onBlur && onBlur(event);
88
92
  toggleHasValue(Boolean(event.target.value));
89
93
  toggleFocused(false);
90
94
  }, onInput: onInput, onChange: onChange, onKeyDown: onKeyDown, onKeyUp: onKeyUp })))),