@sima-land/ui-nucleons 42.1.1 → 42.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/autocomplete/index.js +9 -11
- package/hooks/index.js +3 -6
- package/package.json +1 -1
- package/phone-input/index.d.ts +1 -1
- package/phone-input/index.js +24 -17
- package/phone-input/phone-input.module.scss +9 -2
- package/select/index.js +3 -4
- package/text-field/index.d.ts +1 -1
- package/text-field/index.js +3 -3
package/autocomplete/index.js
CHANGED
|
@@ -66,15 +66,13 @@ const Autocomplete = (_a) => {
|
|
|
66
66
|
const rootRef = (0, react_1.useRef)(null);
|
|
67
67
|
const fieldRef = (0, react_1.useRef)();
|
|
68
68
|
const menuRef = (0, react_1.useRef)();
|
|
69
|
-
const [
|
|
69
|
+
const [withMenu, toggleMenu] = (0, react_1.useState)(false);
|
|
70
70
|
const [realValue, setRealValue] = (0, react_1.useState)(value || defaultValue);
|
|
71
71
|
const [activeIndex, setActiveIndex] = (0, react_1.useState)(null);
|
|
72
|
-
const canShowDropdown = preset === 'filled-only-list'
|
|
73
|
-
? needDropdown && realValue && realValue.length > 0
|
|
74
|
-
: needDropdown;
|
|
72
|
+
const canShowDropdown = preset === 'filled-only-list' ? withMenu && realValue && realValue.length > 0 : withMenu;
|
|
75
73
|
const endAdornment = preset === 'default' ? react_1.default.createElement(down_1.default, { fill: colors_1.COLORS.get('gray38') }) : undefined;
|
|
76
74
|
(0, hooks_1.useOutsideClick)(rootRef, () => {
|
|
77
|
-
|
|
75
|
+
toggleMenu(false);
|
|
78
76
|
});
|
|
79
77
|
(0, react_1.useEffect)(() => {
|
|
80
78
|
setRealValue(value);
|
|
@@ -88,7 +86,7 @@ const Autocomplete = (_a) => {
|
|
|
88
86
|
const osInstance = (_a = osComponentRef.current) === null || _a === void 0 ? void 0 : _a.osInstance();
|
|
89
87
|
if (menu && osInstance && activeIndex !== null) {
|
|
90
88
|
const child = menu.querySelectorAll('[role="menuitem"]')[activeIndex];
|
|
91
|
-
child &&
|
|
89
|
+
child instanceof HTMLElement &&
|
|
92
90
|
osInstance.scroll({
|
|
93
91
|
el: child,
|
|
94
92
|
scroll: { y: 'ifneeded' },
|
|
@@ -96,11 +94,11 @@ const Autocomplete = (_a) => {
|
|
|
96
94
|
}
|
|
97
95
|
}, [activeIndex]);
|
|
98
96
|
return (react_1.default.createElement("div", { ref: rootRef, style: style, className: cx('root', className), "data-testid": dataTestId },
|
|
99
|
-
react_1.default.createElement(text_field_1.TextField, Object.assign({}, restProps, { ref: fieldRef, focused:
|
|
100
|
-
|
|
97
|
+
react_1.default.createElement(text_field_1.TextField, Object.assign({}, restProps, { ref: fieldRef, focused: withMenu, endAdornment: endAdornment, "data-testid": 'autocomplete:field', variant: 'desktop', value: value, multiline: false, onClick: e => {
|
|
98
|
+
toggleMenu(true);
|
|
101
99
|
onClick && onClick(e);
|
|
102
100
|
}, onChange: (e) => {
|
|
103
|
-
|
|
101
|
+
toggleMenu(true);
|
|
104
102
|
setRealValue(e.target.value);
|
|
105
103
|
setActiveIndex(0);
|
|
106
104
|
onChange && onChange(e);
|
|
@@ -117,7 +115,7 @@ const Autocomplete = (_a) => {
|
|
|
117
115
|
case 'Enter':
|
|
118
116
|
if (items && !(0, lodash_1.isNull)(activeIndex) && items.length > activeIndex) {
|
|
119
117
|
onSelect && onSelect(items[activeIndex]);
|
|
120
|
-
|
|
118
|
+
toggleMenu(false);
|
|
121
119
|
}
|
|
122
120
|
break;
|
|
123
121
|
}
|
|
@@ -127,7 +125,7 @@ const Autocomplete = (_a) => {
|
|
|
127
125
|
canShowDropdown && (react_1.default.createElement(dropdown_1.Dropdown, Object.assign({}, (0, dropdown_2.placeDropdown)(restProps.size), { ref: menuRef, "data-testid": 'autocomplete:menu', className: cx('menu'), role: 'menu', customScrollbarProps: { osComponentRef } }), loading ? (react_1.default.createElement(dropdown_loading_1.DropdownLoading, { "data-testid": 'autocomplete:loading-area' })) : (react_1.default.createElement(react_1.default.Fragment, null, items && items.length > 0 ? (items.map((item, index) => (react_1.default.createElement(dropdown_item_1.DropdownItem, { size: itemSize, key: index, role: 'menuitem', checked: index === activeIndex, onClick: () => {
|
|
128
126
|
onSelect && onSelect(item);
|
|
129
127
|
setActiveIndex(null);
|
|
130
|
-
|
|
128
|
+
toggleMenu(false);
|
|
131
129
|
fieldRef.current && fieldRef.current.focus();
|
|
132
130
|
} }, renderItem(item))))) : (react_1.default.createElement(dropdown_item_1.DropdownItem, { size: 'm', noHover: true }, "\u041D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u043E"))))))));
|
|
133
131
|
};
|
package/hooks/index.js
CHANGED
|
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.useIsomorphicLayoutEffect = exports.useOutsideClick = exports.useInfiniteScroll = exports.useIsTouchDevice = void 0;
|
|
7
7
|
const react_1 = require("react");
|
|
8
8
|
const is_touch_device_1 = require("../helpers/is-touch-device");
|
|
9
|
-
const lodash_1 = require("lodash");
|
|
10
9
|
const on_1 = __importDefault(require("../helpers/on"));
|
|
11
10
|
const identity_1 = require("./identity");
|
|
12
11
|
/**
|
|
@@ -51,16 +50,14 @@ exports.useInfiniteScroll = useInfiniteScroll;
|
|
|
51
50
|
* @param callback Сработает при клике вне элемента.
|
|
52
51
|
*/
|
|
53
52
|
const useOutsideClick = (elementRef, callback) => {
|
|
54
|
-
const callbackRef = (0,
|
|
55
|
-
|
|
56
|
-
(0, react_1.useEffect)(() => (0, on_1.default)(document.documentElement, 'click', (event) => {
|
|
53
|
+
const callbackRef = (0, identity_1.useIdentityRef)(callback);
|
|
54
|
+
(0, react_1.useEffect)(() => (0, on_1.default)(document.documentElement, 'click', event => {
|
|
57
55
|
const { current: element } = elementRef;
|
|
58
56
|
const { current: handleClick } = callbackRef;
|
|
59
57
|
element &&
|
|
60
58
|
element !== event.target &&
|
|
61
59
|
!element.contains(event.target) &&
|
|
62
|
-
(0
|
|
63
|
-
handleClick(event);
|
|
60
|
+
(handleClick === null || handleClick === void 0 ? void 0 : handleClick(event));
|
|
64
61
|
}), []);
|
|
65
62
|
};
|
|
66
63
|
exports.useOutsideClick = useOutsideClick;
|
package/package.json
CHANGED
package/phone-input/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { Country } from './presets';
|
|
|
5
5
|
interface PhoneInputStyle extends React.CSSProperties {
|
|
6
6
|
'--phone-input-width'?: number | string;
|
|
7
7
|
}
|
|
8
|
-
export interface PhoneInputProps extends Omit<TextFieldProps, 'onChange' | 'onBlur' | 'value' | 'ref' | 'style'> {
|
|
8
|
+
export interface PhoneInputProps extends Omit<TextFieldProps, 'onChange' | 'onBlur' | 'value' | 'ref' | 'style' | 'multiline'> {
|
|
9
9
|
/** Сработает при "blur". */
|
|
10
10
|
onBlur?: (e: React.FocusEvent<HTMLInputElement>, s: MaskState & {
|
|
11
11
|
ready?: boolean;
|
package/phone-input/index.js
CHANGED
|
@@ -35,7 +35,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.PhoneInput = void 0;
|
|
37
37
|
const react_1 = __importStar(require("react"));
|
|
38
|
-
const bind_1 = __importDefault(require("classnames/bind"));
|
|
39
38
|
const down_1 = __importDefault(require("@sima-land/ui-quarks/icons/16x16/Stroked/Arrows/down"));
|
|
40
39
|
const up_1 = __importDefault(require("@sima-land/ui-quarks/icons/16x16/Stroked/Arrows/up"));
|
|
41
40
|
const dropdown_1 = require("../dropdown");
|
|
@@ -44,10 +43,9 @@ const text_field_1 = require("../text-field");
|
|
|
44
43
|
const masked_field_1 = require("../masked-field");
|
|
45
44
|
const hooks_1 = require("../hooks");
|
|
46
45
|
const presets_1 = require("./presets");
|
|
47
|
-
const sizes_1 = require("../styling/sizes");
|
|
48
|
-
const colors_1 = require("../colors");
|
|
49
|
-
const phone_input_module_scss_1 = __importDefault(require("./phone-input.module.scss"));
|
|
50
46
|
const utils_1 = require("./utils");
|
|
47
|
+
const bind_1 = __importDefault(require("classnames/bind"));
|
|
48
|
+
const phone_input_module_scss_1 = __importDefault(require("./phone-input.module.scss"));
|
|
51
49
|
const cx = bind_1.default.bind(phone_input_module_scss_1.default);
|
|
52
50
|
/**
|
|
53
51
|
* Удаляет из значения код переданной страны.
|
|
@@ -66,23 +64,32 @@ const PhoneInput = (_a) => {
|
|
|
66
64
|
// маску определяем автоматически только при старте
|
|
67
65
|
const [country, setCountry] = (0, react_1.useState)((0, utils_1.defineCountry)(value));
|
|
68
66
|
const [cleanValue, setCleanValue] = (0, react_1.useState)(formatValue(value, country));
|
|
69
|
-
const [
|
|
70
|
-
const
|
|
67
|
+
const [withMenu, toggleMenu] = (0, react_1.useState)(false);
|
|
68
|
+
const rootRef = (0, react_1.useRef)(null);
|
|
69
|
+
const openerRef = (0, react_1.useRef)(null);
|
|
71
70
|
(0, react_1.useEffect)(() => {
|
|
72
71
|
setCleanValue(formatValue(value, country));
|
|
73
72
|
}, [value]);
|
|
74
|
-
(0, hooks_1.useOutsideClick)(
|
|
75
|
-
|
|
76
|
-
togglePopup(false);
|
|
73
|
+
(0, hooks_1.useOutsideClick)(rootRef, () => {
|
|
74
|
+
toggleMenu(false);
|
|
77
75
|
});
|
|
78
|
-
const AdornmentSVG =
|
|
79
|
-
const commonFieldProps = Object.assign(Object.assign({}, restProps), { label, multiline: false, className: cx('field'), endAdornment: (react_1.default.createElement("div", { className: cx('adornment'), "data-testid": 'phone-input:dropdown-opener', onClick:
|
|
80
|
-
|
|
81
|
-
togglePopup(true);
|
|
76
|
+
const AdornmentSVG = withMenu ? up_1.default : down_1.default;
|
|
77
|
+
const commonFieldProps = Object.assign(Object.assign({}, restProps), { label, multiline: false, className: cx('field'), endAdornment: (react_1.default.createElement("div", { ref: openerRef, className: cx('adornment'), "data-testid": 'phone-input:dropdown-opener', onClick: () => {
|
|
78
|
+
toggleMenu(true);
|
|
82
79
|
} },
|
|
83
80
|
react_1.default.createElement("img", { alt: '', width: 24, height: 24, src: country.imageSrc }),
|
|
84
|
-
react_1.default.createElement(AdornmentSVG, {
|
|
85
|
-
|
|
81
|
+
react_1.default.createElement(AdornmentSVG, { className: cx('arrow') }))), onClick: event => {
|
|
82
|
+
const opener = openerRef.current;
|
|
83
|
+
if (opener instanceof Node &&
|
|
84
|
+
event.target instanceof Node &&
|
|
85
|
+
(opener === event.target || opener.contains(event.target))) {
|
|
86
|
+
event.preventDefault(); // чтобы не фокусировалось на поле
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
toggleMenu(false);
|
|
90
|
+
}
|
|
91
|
+
} });
|
|
92
|
+
return (react_1.default.createElement("div", { ref: rootRef, "data-testid": testId, style: style, className: cx('root', className) },
|
|
86
93
|
country.id === presets_1.IDS.other ? (react_1.default.createElement(text_field_1.TextField, Object.assign({}, commonFieldProps, { onChange: (e) => {
|
|
87
94
|
e.target.value = e.target.value.replace(/\D/g, '').slice(0, 20);
|
|
88
95
|
onChange && onChange(e);
|
|
@@ -101,8 +108,8 @@ const PhoneInput = (_a) => {
|
|
|
101
108
|
// вставляем код страны обратно в чистое значение
|
|
102
109
|
cleanValue: `${country.codeChars}${state.cleanValue}` }));
|
|
103
110
|
} }))),
|
|
104
|
-
|
|
105
|
-
|
|
111
|
+
withMenu && (react_1.default.createElement(dropdown_1.Dropdown, { role: 'menu', className: cx('menu'), "data-testid": 'phone-input:dropdown' }, presets_1.countriesList.map((item, index) => item.id === country.id ? null : (react_1.default.createElement(dropdown_item_1.DropdownItem, { key: index, size: 'l', role: 'menuitem', className: cx('menu-item'), onClick: () => {
|
|
112
|
+
toggleMenu(false);
|
|
106
113
|
setCountry(item);
|
|
107
114
|
onCountrySelect && onCountrySelect(item);
|
|
108
115
|
} },
|
|
@@ -17,7 +17,14 @@
|
|
|
17
17
|
cursor: pointer;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
.
|
|
20
|
+
.arrow {
|
|
21
|
+
display: block;
|
|
22
|
+
fill: colors.$gray38;
|
|
23
|
+
margin-left: 4px;
|
|
24
|
+
pointer-events: none; // игнорируем клики т.к. после них элемент стрелки подменяется и считается что он сработал вне элемента родителя
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.menu {
|
|
21
28
|
position: absolute;
|
|
22
29
|
width: 100%;
|
|
23
30
|
top: 56px;
|
|
@@ -25,7 +32,7 @@
|
|
|
25
32
|
z-index: 2;
|
|
26
33
|
}
|
|
27
34
|
|
|
28
|
-
.
|
|
35
|
+
.menu-item {
|
|
29
36
|
font-size: 16px;
|
|
30
37
|
line-height: 24px;
|
|
31
38
|
.item-name {
|
package/select/index.js
CHANGED
|
@@ -83,10 +83,9 @@ const Select = (_a) => {
|
|
|
83
83
|
onKeyDown: e => {
|
|
84
84
|
e.key === 'Enter' && toggleMenu(true);
|
|
85
85
|
},
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
},
|
|
86
|
+
}, onClick: e => {
|
|
87
|
+
e.preventDefault();
|
|
88
|
+
onClick && onClick(e);
|
|
90
89
|
}, className: select_module_scss_1.default.field, "data-testid": 'select:field', label: label, focused: opened, baseInputProps: {
|
|
91
90
|
// чтобы не ловить фокус на поле
|
|
92
91
|
style: { pointerEvents: 'none' },
|
package/text-field/index.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ export interface TextFieldProps extends Omit<React.InputHTMLAttributes<HTMLInput
|
|
|
47
47
|
/** Вариант отображения. */
|
|
48
48
|
variant?: Variant;
|
|
49
49
|
/** Свойства элемента-блока. */
|
|
50
|
-
blockProps?: React.HTMLProps<HTMLDivElement>;
|
|
50
|
+
blockProps?: Omit<React.HTMLProps<HTMLDivElement>, 'onClick'>;
|
|
51
51
|
/** Идентификатор для систем автоматизированного тестирования. */
|
|
52
52
|
'data-testid'?: string;
|
|
53
53
|
}
|
package/text-field/index.js
CHANGED
|
@@ -68,9 +68,9 @@ exports.TextField = (0, react_1.forwardRef)(function TextField({ autoFocus, capt
|
|
|
68
68
|
variant,
|
|
69
69
|
});
|
|
70
70
|
(0, react_1.useImperativeHandle)(ref, () => baseInputRef.current);
|
|
71
|
-
(0, react_1.useEffect)(() => toggleHasValue(Boolean(baseInputRef.current.value)));
|
|
71
|
+
(0, react_1.useEffect)(() => { var _a; return toggleHasValue(Boolean((_a = baseInputRef.current) === null || _a === void 0 ? void 0 : _a.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", 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 => {
|
|
73
|
+
react_1.default.createElement("div", Object.assign({}, blockProps, { "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
76
|
input &&
|
|
@@ -78,7 +78,7 @@ exports.TextField = (0, react_1.forwardRef)(function TextField({ autoFocus, capt
|
|
|
78
78
|
!event.defaultPrevented &&
|
|
79
79
|
input !== document.activeElement &&
|
|
80
80
|
input.focus();
|
|
81
|
-
} }
|
|
81
|
+
} }),
|
|
82
82
|
!multiline && Boolean(startAdornment) && (react_1.default.createElement(box_1.Box, { display: 'flex', alignItems: 'center', marginRight: 4 }, startAdornment)),
|
|
83
83
|
react_1.default.createElement("div", { className: cx('main-column') },
|
|
84
84
|
withLabel && (react_1.default.createElement("label", { className: cx('label', commonModifyClasses, hasValue && 'filled', labelAsPlaceholder && 'as-placeholder'), htmlFor: id, children: label, "data-testid": 'text-field:label' })),
|