@true-engineering/true-react-common-ui-kit 2.1.1 → 2.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/dist/components/Button/Button.d.ts +3 -4
- package/dist/components/Input/Input.d.ts +3 -4
- package/dist/components/List/List.d.ts +3 -4
- package/dist/components/ScrollIntoViewIfNeeded/ScrollIntoViewIfNeeded.d.ts +4 -4
- package/dist/components/Select/Select.d.ts +2 -3
- package/dist/helpers/deprecated.d.ts +12 -0
- package/dist/helpers/index.d.ts +2 -2
- package/dist/helpers/misc.d.ts +19 -0
- package/dist/helpers/snippets.d.ts +3 -3
- package/dist/true-react-common-ui-kit.js +238 -308
- package/dist/true-react-common-ui-kit.js.map +1 -1
- package/dist/true-react-common-ui-kit.umd.cjs +238 -309
- package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
- package/dist/types.d.ts +3 -1
- package/package.json +2 -1
- package/src/components/Button/Button.tsx +9 -29
- package/src/components/Checkbox/Checkbox.tsx +7 -2
- package/src/components/DatePicker/DatePicker.tsx +6 -1
- package/src/components/DatePicker/helpers.ts +5 -1
- package/src/components/FiltersPane/FilterSelect/FilterSelect.tsx +3 -2
- package/src/components/FiltersPane/FilterWithDates/FilterWithDates.tsx +2 -1
- package/src/components/IncrementInput/IncrementInput.tsx +3 -2
- package/src/components/Input/Input.tsx +15 -10
- package/src/components/List/List.tsx +13 -10
- package/src/components/Modal/Modal.tsx +8 -3
- package/src/components/MoreMenu/MoreMenu.tsx +3 -2
- package/src/components/Notification/Notification.tsx +11 -7
- package/src/components/NumberInput/NumberInput.tsx +2 -2
- package/src/components/NumberInput/helpers.ts +3 -2
- package/src/components/RadioButton/RadioButton.tsx +3 -2
- package/src/components/ScrollIntoViewIfNeeded/ScrollIntoViewIfNeeded.ts +4 -4
- package/src/components/SearchInput/SearchInput.tsx +2 -1
- package/src/components/Select/MultiSelect.stories.tsx +2 -2
- package/src/components/Select/Select.stories.tsx +2 -2
- package/src/components/Select/Select.tsx +8 -8
- package/src/components/Select/SelectList/SelectList.tsx +11 -5
- package/src/components/Select/SelectListItem/SelectListItem.tsx +2 -1
- package/src/components/Select/helpers.ts +1 -1
- package/src/components/Switch/Switch.tsx +3 -2
- package/src/components/Toaster/Toaster.tsx +10 -5
- package/src/helpers/deprecated.ts +22 -0
- package/src/helpers/index.ts +2 -2
- package/src/helpers/{utils.ts → misc.ts} +11 -84
- package/src/helpers/phone.ts +5 -5
- package/src/helpers/snippets.tsx +4 -3
- package/src/types.ts +10 -1
- package/dist/helpers/colors.d.ts +0 -2
- package/dist/helpers/utils.d.ts +0 -43
- package/src/helpers/colors.ts +0 -3
- package/src/helpers/dateHelpers/date-helpers.ts +0 -9
package/dist/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
1
2
|
import { Styles } from 'react-jss';
|
|
2
3
|
import { Modifier, Placement } from 'react-overlays/usePopper';
|
|
3
|
-
import { ICommonIcon, IComplexIcon, IPreloaderSvgType, ISvgIcon } from './components';
|
|
4
|
+
import type { ICommonIcon, IComplexIcon, IIconType, IPreloaderSvgType, ISvgIcon } from './components';
|
|
4
5
|
export interface IDataAttributes {
|
|
5
6
|
[key: string]: unknown;
|
|
6
7
|
}
|
|
@@ -17,6 +18,7 @@ export interface IDropdownWithPopperOptions {
|
|
|
17
18
|
placement?: Placement;
|
|
18
19
|
flipOptions?: Record<string, any>;
|
|
19
20
|
}
|
|
21
|
+
export declare type IIcon = IIconType | ReactElement;
|
|
20
22
|
export declare type ComponentStyles<StyleSheet, Props = unknown> = Partial<Styles<keyof StyleSheet, Props>>;
|
|
21
23
|
export declare type ComponentName = 'AccountInfo' | 'AddButton' | 'Button' | 'CloseButton' | 'Checkbox' | 'CssBaseline' | 'Colors' | 'DateInput' | 'DatePicker' | 'DatePickerHeader' | 'Description' | 'DotsPreloader' | 'SvgPreloader' | 'FiltersPane' | 'FilterInterval' | 'FilterSelect' | 'FilterWithDates' | 'FilterWithPeriod' | 'FilterWrapper' | 'FiltersPaneSearch' | 'Flag' | 'FlexibleTable' | 'Icon' | 'IncrementInput' | 'Input' | 'List' | 'Modal' | 'MoreMenu' | 'MultiSelect' | 'MultiSelectInput' | 'MultiSelectList' | 'Notification' | 'PhoneInput' | 'PhoneInputCountryList' | 'RadioButton' | 'SearchInput' | 'Select' | 'SelectList' | 'ScrollIntoViewIfNeeded' | 'Switch' | 'TextArea' | 'TextWithInfo' | 'TextWithTooltip' | 'ThemedPreloader' | 'Tooltip' | 'Toaster';
|
|
22
24
|
export declare type UiKitAnimations = Record<string, any>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@true-engineering/true-react-common-ui-kit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "True Engineering React UI Kit with theming support",
|
|
5
5
|
"author": "True Engineering (https://trueengineering.ru)",
|
|
6
6
|
"keywords": [
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"types-check": "tsc --noEmit"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
+
"@true-engineering/true-react-platform-helpers": "0.0.4",
|
|
45
46
|
"clsx": "1.2.1",
|
|
46
47
|
"country-flag-icons": "1.5.5",
|
|
47
48
|
"date-fns": "2.29.3",
|
|
@@ -1,34 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useMemo,
|
|
3
|
-
ReactElement,
|
|
4
|
-
ReactNode,
|
|
5
|
-
ButtonHTMLAttributes,
|
|
6
|
-
MouseEvent,
|
|
7
|
-
forwardRef,
|
|
8
|
-
} from 'react';
|
|
1
|
+
import { useMemo, ReactNode, ButtonHTMLAttributes, MouseEvent, forwardRef } from 'react';
|
|
9
2
|
import clsx from 'clsx';
|
|
10
3
|
import merge from 'lodash-es/merge';
|
|
11
|
-
import {
|
|
4
|
+
import { addDataTestId, isReactNodeNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
5
|
+
import { addDataAttributes } from '../../helpers';
|
|
6
|
+
import { renderIcon } from '../../helpers/snippets';
|
|
12
7
|
import { useTheme } from '../../hooks';
|
|
13
|
-
import { ICommonProps } from '../../types';
|
|
14
|
-
import { Icon, IIconType } from '../Icon';
|
|
8
|
+
import { ICommonProps, IIcon } from '../../types';
|
|
15
9
|
import { ThemedPreloader, IThemedPreloaderProps, ThemedPreloaderStyles } from '../ThemedPreloader';
|
|
16
10
|
import { ButtonStyles, styles, dotsPreloaderStyles } from './Button.styles';
|
|
17
11
|
|
|
18
12
|
export type IButtonSize = 's' | 'm' | 'l' | 'xl';
|
|
19
13
|
|
|
20
|
-
/* Information for migration from old views
|
|
21
|
-
|
|
22
|
-
main => primary
|
|
23
|
-
cancel => secondary
|
|
24
|
-
cancel-light => outline
|
|
25
|
-
attention => warning
|
|
26
|
-
light => text
|
|
27
|
-
error => destructive
|
|
28
|
-
|
|
29
|
-
For other old views use custom.
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
14
|
export const BUTTON_VIEWS = [
|
|
33
15
|
'primary',
|
|
34
16
|
'secondary',
|
|
@@ -82,7 +64,7 @@ export interface IButtonProps extends ICommonProps {
|
|
|
82
64
|
* @default false
|
|
83
65
|
*/
|
|
84
66
|
isActive?: boolean;
|
|
85
|
-
icon?:
|
|
67
|
+
icon?: IIcon;
|
|
86
68
|
/**
|
|
87
69
|
* @default `left`
|
|
88
70
|
*/
|
|
@@ -133,8 +115,8 @@ export const Button = forwardRef<HTMLButtonElement, IButtonProps>(
|
|
|
133
115
|
[tweakStyles?.tweakPreloader, size],
|
|
134
116
|
);
|
|
135
117
|
|
|
136
|
-
const hasIcon =
|
|
137
|
-
const hasChildren =
|
|
118
|
+
const hasIcon = isReactNodeNotEmpty(icon);
|
|
119
|
+
const hasChildren = isReactNodeNotEmpty(children);
|
|
138
120
|
const hasNoAction = isDisabled || isLoading;
|
|
139
121
|
|
|
140
122
|
return (
|
|
@@ -163,9 +145,7 @@ export const Button = forwardRef<HTMLButtonElement, IButtonProps>(
|
|
|
163
145
|
})}
|
|
164
146
|
>
|
|
165
147
|
{hasIcon && (
|
|
166
|
-
<span className={classes.icon}>
|
|
167
|
-
{typeof icon === 'string' ? <Icon type={icon as IIconType} /> : icon}
|
|
168
|
-
</span>
|
|
148
|
+
<span className={classes.icon}>{isReactNodeNotEmpty(icon) && renderIcon(icon)}</span>
|
|
169
149
|
)}
|
|
170
150
|
{hasChildren && (
|
|
171
151
|
<span className={clsx(classes.children, hasIcon && classes.withIcon)}>{children}</span>
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { useEffect, useState, ReactNode } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
addDataTestId,
|
|
5
|
+
getSelectKeyHandler,
|
|
6
|
+
isReactNodeNotEmpty,
|
|
7
|
+
} from '@true-engineering/true-react-platform-helpers';
|
|
8
|
+
import { addDataAttributes } from '../../helpers';
|
|
4
9
|
import { useTheme } from '../../hooks';
|
|
5
10
|
import { ICommonProps } from '../../types';
|
|
6
11
|
import { Icon } from '../Icon';
|
|
@@ -94,7 +99,7 @@ export function Checkbox<V>({
|
|
|
94
99
|
<div className={clsx(classes.check, isSelected && classes.checked)}>
|
|
95
100
|
<Icon type={isSemiChecked ? 'minus' : 'check'} />
|
|
96
101
|
</div>
|
|
97
|
-
{
|
|
102
|
+
{isReactNodeNotEmpty(children) && <div className={classes.children}>{children}</div>}
|
|
98
103
|
</label>
|
|
99
104
|
);
|
|
100
105
|
}
|
|
@@ -14,7 +14,12 @@ import 'react-datepicker/dist/react-datepicker.css';
|
|
|
14
14
|
import { Portal } from 'react-overlays';
|
|
15
15
|
import clsx from 'clsx';
|
|
16
16
|
import { isAfter, isBefore, isValid } from 'date-fns';
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
isEmpty,
|
|
19
|
+
isNotEmpty,
|
|
20
|
+
isStringNotEmpty,
|
|
21
|
+
} from '@true-engineering/true-react-platform-helpers';
|
|
22
|
+
import { addDataAttributes } from '../../helpers';
|
|
18
23
|
import { useTheme, useTweakStyles } from '../../hooks';
|
|
19
24
|
import { DateInput, EMPTY_DATE_INPUT_VALUE, IDateInputProps } from '../DateInput';
|
|
20
25
|
import { DatePickerStyles, styles } from './DatePicker.styles';
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { parse, format, isSameDay } from 'date-fns';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
isEmpty,
|
|
4
|
+
isNotEmpty,
|
|
5
|
+
isStringNotEmpty,
|
|
6
|
+
} from '@true-engineering/true-react-platform-helpers';
|
|
3
7
|
import { EMPTY_DATE_INPUT_VALUE } from '../DateInput';
|
|
4
8
|
|
|
5
9
|
export const getDateFormatter =
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import { debounce } from 'ts-debounce';
|
|
4
|
-
import {
|
|
4
|
+
import { isReactNodeNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
5
|
+
import { addDataAttributes } from '../../../helpers';
|
|
5
6
|
import { useIsMounted, useTheme, useTweakStyles } from '../../../hooks';
|
|
6
7
|
import { ICommonProps } from '../../../types';
|
|
7
8
|
import { Button } from '../../Button';
|
|
@@ -82,7 +83,7 @@ export function FilterSelect<Value>({
|
|
|
82
83
|
const [isLoadingOptionsOnScroll, setLoadingOptionsOnScroll] = useState(false);
|
|
83
84
|
|
|
84
85
|
const shouldShowPreloader = isLoading || isLoadingOptionsOnScroll;
|
|
85
|
-
const hasFooter =
|
|
86
|
+
const hasFooter = isReactNodeNotEmpty(footer);
|
|
86
87
|
|
|
87
88
|
const handleSearchInputChange = useCallback(
|
|
88
89
|
async (inputValue?: string) => {
|
|
@@ -2,7 +2,8 @@ import { useState, useMemo, useRef, FC } from 'react';
|
|
|
2
2
|
import { isAfter, isBefore } from 'date-fns';
|
|
3
3
|
import enUS from 'date-fns/locale/en-US';
|
|
4
4
|
import ru from 'date-fns/locale/ru';
|
|
5
|
-
import {
|
|
5
|
+
import { getTestId } from '@true-engineering/true-react-platform-helpers';
|
|
6
|
+
import { addDataAttributes } from '../../../helpers';
|
|
6
7
|
import { useTheme, useTweakStyles } from '../../../hooks';
|
|
7
8
|
import { ICommonProps } from '../../../types';
|
|
8
9
|
import { Button } from '../../Button';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { isNumberInteger } from '@true-engineering/true-react-platform-helpers';
|
|
3
|
+
import { addDataAttributes, getNumberInRange, getNumberLength } from '../../helpers';
|
|
3
4
|
import { useTheme, useTweakStyles } from '../../hooks';
|
|
4
5
|
import { INumberInputProps, NumberInput } from '../NumberInput';
|
|
5
6
|
import { ChangeButton } from './ChangeButton';
|
|
@@ -21,7 +22,7 @@ export const IncrementInput: FC<IIncrementInputProps> = ({
|
|
|
21
22
|
tweakStyles,
|
|
22
23
|
...props
|
|
23
24
|
}) => {
|
|
24
|
-
if (!
|
|
25
|
+
if (!isNumberInteger(step)) {
|
|
25
26
|
console.error('Параметр step должен быть целым числом');
|
|
26
27
|
}
|
|
27
28
|
|
|
@@ -9,15 +9,19 @@ import {
|
|
|
9
9
|
KeyboardEvent,
|
|
10
10
|
ClipboardEvent,
|
|
11
11
|
InputHTMLAttributes,
|
|
12
|
-
ReactElement,
|
|
13
12
|
} from 'react';
|
|
14
13
|
import InputMask, { Props as ReactInputMaskBaseProps } from 'react-input-mask';
|
|
15
14
|
import clsx from 'clsx';
|
|
16
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
addDataTestId,
|
|
17
|
+
isReactNodeNotEmpty,
|
|
18
|
+
isStringNotEmpty,
|
|
19
|
+
} from '@true-engineering/true-react-platform-helpers';
|
|
20
|
+
import { addDataAttributes } from '../../helpers';
|
|
17
21
|
import { renderIcon } from '../../helpers/snippets';
|
|
18
22
|
import { useTheme, useTweakStyles } from '../../hooks';
|
|
19
|
-
import { ICommonProps } from '../../types';
|
|
20
|
-
import { Icon
|
|
23
|
+
import { ICommonProps, IIcon } from '../../types';
|
|
24
|
+
import { Icon } from '../Icon';
|
|
21
25
|
import { ThemedPreloader } from '../ThemedPreloader';
|
|
22
26
|
import { InputStyles, styles } from './Input.styles';
|
|
23
27
|
|
|
@@ -75,7 +79,7 @@ export interface IInputProps extends ICommonProps, IReactInputMaskProps {
|
|
|
75
79
|
* @default 6
|
|
76
80
|
*/
|
|
77
81
|
defaultSize?: number;
|
|
78
|
-
iconType?:
|
|
82
|
+
iconType?: IIcon;
|
|
79
83
|
units?: string;
|
|
80
84
|
name?: string;
|
|
81
85
|
hasRequiredLabel?: boolean;
|
|
@@ -170,8 +174,9 @@ export const Input = forwardRef<HTMLInputElement, IInputProps>(
|
|
|
170
174
|
const hasControls = hasClearIcon || iconType !== undefined || isLoading;
|
|
171
175
|
const hasValue = value !== undefined && value !== '';
|
|
172
176
|
const hasUnits = units !== undefined && units !== '';
|
|
173
|
-
const hasLabel =
|
|
174
|
-
const hasPlaceholder =
|
|
177
|
+
const hasLabel = isStringNotEmpty(label);
|
|
178
|
+
const hasPlaceholder =
|
|
179
|
+
(!hasLabel || (hasFocus && !isReadonly)) && isStringNotEmpty(placeholder);
|
|
175
180
|
const shouldShowUnits = (hasValue || (isFocused && !hasPlaceholder)) && hasUnits;
|
|
176
181
|
|
|
177
182
|
const props: InputHTMLAttributes<HTMLInputElement> = {
|
|
@@ -280,7 +285,7 @@ export const Input = forwardRef<HTMLInputElement, IInputProps>(
|
|
|
280
285
|
<Icon type="close" />
|
|
281
286
|
</div>
|
|
282
287
|
)}
|
|
283
|
-
{iconType
|
|
288
|
+
{isReactNodeNotEmpty(iconType) && (
|
|
284
289
|
<div
|
|
285
290
|
// .inputIcon extend .icon
|
|
286
291
|
className={clsx(classes.inputIcon, {
|
|
@@ -294,8 +299,8 @@ export const Input = forwardRef<HTMLInputElement, IInputProps>(
|
|
|
294
299
|
</div>
|
|
295
300
|
)}
|
|
296
301
|
</div>
|
|
297
|
-
{
|
|
298
|
-
{
|
|
302
|
+
{isStringNotEmpty(infoMessage) && <div className={classes.info}>{infoMessage}</div>}
|
|
303
|
+
{isStringNotEmpty(errorMessage) && (
|
|
299
304
|
<div className={clsx(classes.error, classes[`error-${errorPosition}`])}>
|
|
300
305
|
{errorMessage}
|
|
301
306
|
</div>
|
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
import { FC, Fragment,
|
|
1
|
+
import { FC, Fragment, ReactNode } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
addDataTestId,
|
|
5
|
+
getTestId,
|
|
6
|
+
isReactNodeNotEmpty,
|
|
7
|
+
} from '@true-engineering/true-react-platform-helpers';
|
|
8
|
+
import { addDataAttributes } from '../../helpers';
|
|
9
|
+
import { renderIcon } from '../../helpers/snippets';
|
|
4
10
|
import { useTheme } from '../../hooks';
|
|
5
|
-
import { ICommonProps } from '../../types';
|
|
6
|
-
import { Icon, IIconType } from '../Icon';
|
|
11
|
+
import { ICommonProps, IIcon } from '../../types';
|
|
7
12
|
import { ListStyles, styles } from './List.styles';
|
|
8
13
|
|
|
9
14
|
export interface IListItem {
|
|
10
15
|
item: ReactNode;
|
|
11
|
-
icon?:
|
|
16
|
+
icon?: IIcon;
|
|
12
17
|
disabled?: boolean;
|
|
13
18
|
shouldDrawSpacerAbove?: boolean;
|
|
14
19
|
shouldDrawSpacerBelow?: boolean;
|
|
@@ -42,14 +47,12 @@ export const List: FC<IListProps> = ({ items, testId, data, tweakStyles, onClick
|
|
|
42
47
|
[classes.disabledItem]: item.disabled,
|
|
43
48
|
[classes.withIconGap]: item.withIconGap,
|
|
44
49
|
})}
|
|
50
|
+
onClick={item.disabled ? undefined : () => handleItemClick(item)}
|
|
45
51
|
{...addDataTestId(item.testId ?? getTestId(testId, `item-${idx}`))}
|
|
46
52
|
{...(item.disabled && addDataAttributes({ disabled: item.disabled }))}
|
|
47
|
-
onClick={item.disabled ? undefined : () => handleItemClick(item)}
|
|
48
53
|
>
|
|
49
|
-
{
|
|
50
|
-
<span className={classes.icon}>
|
|
51
|
-
{typeof item.icon === 'string' ? <Icon type={item.icon} /> : item.icon}
|
|
52
|
-
</span>
|
|
54
|
+
{isReactNodeNotEmpty(item.icon) && (
|
|
55
|
+
<span className={classes.icon}>{renderIcon(item.icon)}</span>
|
|
53
56
|
)}
|
|
54
57
|
<span className={classes.content}>{item.item}</span>
|
|
55
58
|
</div>
|
|
@@ -2,7 +2,12 @@ import { FC, ReactNode, MouseEvent, useCallback, useEffect, useRef, useState } f
|
|
|
2
2
|
import { RemoveScroll } from 'react-remove-scroll';
|
|
3
3
|
import { CSSTransition } from 'react-transition-group';
|
|
4
4
|
import clsx from 'clsx';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
addDataTestId,
|
|
7
|
+
getTestId,
|
|
8
|
+
isReactNodeNotEmpty,
|
|
9
|
+
} from '@true-engineering/true-react-platform-helpers';
|
|
10
|
+
import { addDataAttributes } from '../../helpers';
|
|
6
11
|
import { useTheme, useTweakStyles } from '../../hooks';
|
|
7
12
|
import { ICommonProps } from '../../types';
|
|
8
13
|
import { CloseButton } from '../CloseButton';
|
|
@@ -146,7 +151,7 @@ export const Modal: FC<IModalProps> = ({
|
|
|
146
151
|
/>
|
|
147
152
|
</div>
|
|
148
153
|
)}
|
|
149
|
-
{
|
|
154
|
+
{isReactNodeNotEmpty(title) && (
|
|
150
155
|
<h3
|
|
151
156
|
className={clsx(classes.title, {
|
|
152
157
|
[classes.titleWithCloseButton]: hasCloseButton,
|
|
@@ -155,7 +160,7 @@ export const Modal: FC<IModalProps> = ({
|
|
|
155
160
|
{title}
|
|
156
161
|
</h3>
|
|
157
162
|
)}
|
|
158
|
-
{
|
|
163
|
+
{isReactNodeNotEmpty(children) && <div className={classes.content}>{children}</div>}
|
|
159
164
|
{hasFooter && (
|
|
160
165
|
<div
|
|
161
166
|
className={clsx(classes.footerWrapper, {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FC, MouseEvent, useRef, useState } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
3
|
+
import { addDataTestId, getTestId } from '@true-engineering/true-react-platform-helpers';
|
|
4
|
+
import { addDataAttributes } from '../../helpers';
|
|
4
5
|
import { useTheme, useTweakStyles, useOnClickOutsideWithRef } from '../../hooks';
|
|
5
6
|
import { ICommonProps } from '../../types';
|
|
6
7
|
import { Icon } from '../Icon';
|
|
@@ -66,9 +67,9 @@ export const MoreMenu: FC<IMoreMenuProps> = ({
|
|
|
66
67
|
[classes.disabled]: isButtonDisabled,
|
|
67
68
|
[classes.active]: isMenuShown,
|
|
68
69
|
})}
|
|
70
|
+
onClick={!isButtonDisabled ? toggleMenu : undefined}
|
|
69
71
|
{...addDataTestId(testId)}
|
|
70
72
|
{...addDataAttributes(data)}
|
|
71
|
-
onClick={!isButtonDisabled ? toggleMenu : undefined}
|
|
72
73
|
>
|
|
73
74
|
<div className={classes.icon}>
|
|
74
75
|
<Icon type="menu" />
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { FC, ReactNode } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
addDataTestId,
|
|
5
|
+
isReactNodeNotEmpty,
|
|
6
|
+
isStringNotEmpty,
|
|
7
|
+
} from '@true-engineering/true-react-platform-helpers';
|
|
8
|
+
import { addDataAttributes } from '../../helpers';
|
|
4
9
|
import { useTheme } from '../../hooks';
|
|
5
10
|
import { ICommonProps } from '../../types';
|
|
6
11
|
import { Icon } from '../Icon';
|
|
@@ -38,9 +43,8 @@ export const Notification: FC<INotificationProps> = ({
|
|
|
38
43
|
}) => {
|
|
39
44
|
const { classes } = useTheme('Notification', styles, tweakStyles, { type });
|
|
40
45
|
|
|
41
|
-
const hasText =
|
|
42
|
-
const hasTitle =
|
|
43
|
-
const hasTestId = isNotEmpty(testId);
|
|
46
|
+
const hasText = isStringNotEmpty(text);
|
|
47
|
+
const hasTitle = isStringNotEmpty(title);
|
|
44
48
|
|
|
45
49
|
return (
|
|
46
50
|
<div
|
|
@@ -57,16 +61,16 @@ export const Notification: FC<INotificationProps> = ({
|
|
|
57
61
|
</div>
|
|
58
62
|
<div className={classes.body}>
|
|
59
63
|
{hasTitle && (
|
|
60
|
-
<span className={classes.title}
|
|
64
|
+
<span className={classes.title} {...addDataTestId(testId, 'title')}>
|
|
61
65
|
{title}
|
|
62
66
|
</span>
|
|
63
67
|
)}
|
|
64
68
|
{hasText && (
|
|
65
|
-
<span className={classes.text}
|
|
69
|
+
<span className={classes.text} {...addDataTestId(testId, 'text')}>
|
|
66
70
|
{text}
|
|
67
71
|
</span>
|
|
68
72
|
)}
|
|
69
|
-
{
|
|
73
|
+
{isReactNodeNotEmpty(children) && <div className={classes.content}>{children}</div>}
|
|
70
74
|
</div>
|
|
71
75
|
</div>
|
|
72
76
|
);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { FormEvent, KeyboardEvent, FocusEvent, forwardRef, useState } from 'react';
|
|
2
|
+
import { isStringNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
2
3
|
import {
|
|
3
4
|
formatNumber,
|
|
4
5
|
formatStringNumber,
|
|
5
6
|
getNumberInRange,
|
|
6
|
-
isNotEmpty,
|
|
7
7
|
removeStringFormat,
|
|
8
8
|
setCaretPosition,
|
|
9
9
|
stringToNumber,
|
|
@@ -53,7 +53,7 @@ export const NumberInput = forwardRef<HTMLInputElement, INumberInputProps>(
|
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
const setShowedValueWithDefault = (v: string) => {
|
|
56
|
-
setShowedValue(
|
|
56
|
+
setShowedValue(isStringNotEmpty(v) ? v : formatNumber(defaultValue));
|
|
57
57
|
};
|
|
58
58
|
|
|
59
59
|
const handleChange = async (
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isStringNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
2
|
+
import { formatNumber, isSpaceChar } from '../../helpers';
|
|
2
3
|
import { INumberInputProps } from './NumberInput';
|
|
3
4
|
|
|
4
5
|
const getPrevSpaces = (val: string, position: number): number =>
|
|
@@ -32,7 +33,7 @@ export const formatNumberWithDefault = (
|
|
|
32
33
|
defaultValue?: number,
|
|
33
34
|
): string => {
|
|
34
35
|
const val = formatNumber(value);
|
|
35
|
-
return
|
|
36
|
+
return isStringNotEmpty(val) ? val : formatNumber(defaultValue);
|
|
36
37
|
};
|
|
37
38
|
|
|
38
39
|
export const constructRegExp = ({
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
3
|
+
import { isReactNodeNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
4
|
+
import { addDataAttributes } from '../../helpers';
|
|
4
5
|
import { useTheme } from '../../hooks';
|
|
5
6
|
import { ICommonProps } from '../../types';
|
|
6
7
|
import { RadioButtonStyles, styles } from './RadioButton.styles';
|
|
@@ -48,7 +49,7 @@ export function RadioButton<Value extends string>({
|
|
|
48
49
|
[classes.isInvalid]: isInvalid,
|
|
49
50
|
})}
|
|
50
51
|
/>
|
|
51
|
-
{
|
|
52
|
+
{isReactNodeNotEmpty(children) && <span className={classes.content}>{children}</span>}
|
|
52
53
|
</label>
|
|
53
54
|
);
|
|
54
55
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createElement, createRef, PureComponent } from 'react';
|
|
1
|
+
import { createElement, createRef, HTMLProps, PureComponent, ReactNode, RefObject } from 'react';
|
|
2
2
|
import scrollIntoViewIfNeeded, { StandardBehaviorOptions } from 'scroll-into-view-if-needed';
|
|
3
3
|
|
|
4
|
-
interface IScrollIntoViewIfNeededProps extends
|
|
4
|
+
interface IScrollIntoViewIfNeededProps extends HTMLProps<HTMLElement> {
|
|
5
5
|
active?: boolean;
|
|
6
|
-
children?:
|
|
6
|
+
children?: ReactNode;
|
|
7
7
|
elementType?: string;
|
|
8
8
|
options?: StandardBehaviorOptions;
|
|
9
9
|
}
|
|
@@ -20,7 +20,7 @@ const ScrollIntoViewIfNeededDefaultProps: IScrollIntoViewIfNeededProps = {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
export class ScrollIntoViewIfNeeded extends PureComponent<IScrollIntoViewIfNeededProps> {
|
|
23
|
-
node:
|
|
23
|
+
node: RefObject<HTMLElement> = createRef();
|
|
24
24
|
|
|
25
25
|
public static defaultProps: IScrollIntoViewIfNeededProps = ScrollIntoViewIfNeededDefaultProps;
|
|
26
26
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { addDataTestId, getTestId } from '@true-engineering/true-react-platform-helpers';
|
|
3
|
+
import { addDataAttributes } from '../../helpers';
|
|
3
4
|
import { useTheme, useTweakStyles } from '../../hooks';
|
|
4
5
|
import { Icon } from '../Icon';
|
|
5
6
|
import { IInputProps, Input } from '../Input';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode, useEffect, useState } from 'react';
|
|
2
|
+
import { isStringNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
2
3
|
import { ComponentMeta, ComponentStory } from '@storybook/react';
|
|
3
|
-
import { isNotEmpty } from '../../helpers';
|
|
4
4
|
import { Select, ISelectProps } from './Select';
|
|
5
5
|
|
|
6
6
|
interface ObjectValue {
|
|
@@ -165,7 +165,7 @@ function SelectWithCustomProps<T>({
|
|
|
165
165
|
searchInput: { shouldRenderInList: true },
|
|
166
166
|
})}
|
|
167
167
|
isMultiSelect
|
|
168
|
-
noMatchesLabel={
|
|
168
|
+
noMatchesLabel={isStringNotEmpty(noMatchesLabel) ? noMatchesLabel : undefined}
|
|
169
169
|
optionsMode={optionsMode}
|
|
170
170
|
onType={async () => setDynamicOptions(await getOptions())}
|
|
171
171
|
onOpen={handleOpen}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode, useEffect, useState } from 'react';
|
|
2
|
+
import { isStringNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
2
3
|
import { ComponentMeta, ComponentStory } from '@storybook/react';
|
|
3
|
-
import { isNotEmpty } from '../../helpers';
|
|
4
4
|
import { Select, ISelectProps } from './Select';
|
|
5
5
|
|
|
6
6
|
interface ObjectValue {
|
|
@@ -162,7 +162,7 @@ function SelectWithCustomProps<T>({
|
|
|
162
162
|
{...(shouldRenderSearchInputInList && {
|
|
163
163
|
searchInput: { shouldRenderInList: true },
|
|
164
164
|
})}
|
|
165
|
-
noMatchesLabel={
|
|
165
|
+
noMatchesLabel={isStringNotEmpty(noMatchesLabel) ? noMatchesLabel : undefined}
|
|
166
166
|
optionsMode={optionsMode}
|
|
167
167
|
onType={async () => setDynamicOptions(await getOptions())}
|
|
168
168
|
onOpen={handleOpen}
|
|
@@ -16,12 +16,12 @@ import { Styles } from 'jss';
|
|
|
16
16
|
import merge from 'lodash-es/merge';
|
|
17
17
|
import { debounce } from 'ts-debounce';
|
|
18
18
|
import {
|
|
19
|
-
createFilter,
|
|
20
19
|
getTestId,
|
|
21
|
-
hasExactParent,
|
|
22
20
|
isNotEmpty,
|
|
23
21
|
isStringNotEmpty,
|
|
24
|
-
|
|
22
|
+
createFilter,
|
|
23
|
+
} from '@true-engineering/true-react-platform-helpers';
|
|
24
|
+
import { hasExactParent } from '../../helpers';
|
|
25
25
|
import { renderIcon } from '../../helpers/snippets';
|
|
26
26
|
import {
|
|
27
27
|
useIsMounted,
|
|
@@ -30,8 +30,7 @@ import {
|
|
|
30
30
|
useDropdown,
|
|
31
31
|
useTweakStyles,
|
|
32
32
|
} from '../../hooks';
|
|
33
|
-
import { IDropdownWithPopperOptions } from '../../types';
|
|
34
|
-
import { IIconType, Icon } from '../Icon';
|
|
33
|
+
import { IDropdownWithPopperOptions, IIcon } from '../../types';
|
|
35
34
|
import { IInputProps, Input } from '../Input';
|
|
36
35
|
import { ISearchInputProps, SearchInput } from '../SearchInput';
|
|
37
36
|
import { SelectStyles, styles } from './Select.styles';
|
|
@@ -57,7 +56,7 @@ export interface ISelectProps<Value>
|
|
|
57
56
|
debounceTime?: number;
|
|
58
57
|
minSymbolsCountToOpenList?: number;
|
|
59
58
|
dropdownOptions?: IDropdownWithPopperOptions;
|
|
60
|
-
dropdownIcon?:
|
|
59
|
+
dropdownIcon?: IIcon;
|
|
61
60
|
options: Value[];
|
|
62
61
|
value: Value | undefined;
|
|
63
62
|
shouldScrollToList?: boolean;
|
|
@@ -144,7 +143,8 @@ export function Select<Value>(
|
|
|
144
143
|
|
|
145
144
|
const isMultiSelect = isMultiSelectValue(props, value);
|
|
146
145
|
const strValue = isMultiSelect ? value?.[0] : value;
|
|
147
|
-
const shouldShowAllOption =
|
|
146
|
+
const shouldShowAllOption =
|
|
147
|
+
isMultiSelect && isStringNotEmpty(allOptionsLabel) && searchValue === '';
|
|
148
148
|
|
|
149
149
|
const filteredOptions = useMemo(() => {
|
|
150
150
|
if (optionsMode !== 'search') {
|
|
@@ -560,7 +560,7 @@ export function Select<Value>(
|
|
|
560
560
|
onClick={onArrowClick}
|
|
561
561
|
className={clsx(classes.arrow, isOpen && classes.activeArrow)}
|
|
562
562
|
>
|
|
563
|
-
|
|
563
|
+
{renderIcon(dropdownIcon)}
|
|
564
564
|
</div>
|
|
565
565
|
</div>
|
|
566
566
|
{shouldUsePopper ? (
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { ReactNode, useMemo, MouseEvent } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
isNotEmpty,
|
|
5
|
+
isReactNodeNotEmpty,
|
|
6
|
+
isStringNotEmpty,
|
|
7
|
+
} from '@true-engineering/true-react-platform-helpers';
|
|
4
8
|
import { useTheme } from '../../../hooks';
|
|
5
9
|
import { ICommonProps } from '../../../types';
|
|
6
10
|
import { ScrollIntoViewIfNeeded } from '../../ScrollIntoViewIfNeeded';
|
|
@@ -83,16 +87,18 @@ export function SelectList<Value>({
|
|
|
83
87
|
<ScrollIntoViewIfNeeded
|
|
84
88
|
active={shouldScrollToList && !isMultiSelect}
|
|
85
89
|
className={clsx(classes.root, {
|
|
86
|
-
[classes.withListHeader]:
|
|
90
|
+
[classes.withListHeader]: isReactNodeNotEmpty(customListHeader),
|
|
87
91
|
})}
|
|
88
92
|
>
|
|
89
|
-
{
|
|
93
|
+
{isReactNodeNotEmpty(customListHeader) && (
|
|
94
|
+
<div className={classes.listHeader}>{customListHeader}</div>
|
|
95
|
+
)}
|
|
90
96
|
<div className={classes.list} data-testid={testId}>
|
|
91
97
|
{isLoading ? (
|
|
92
98
|
<div className={clsx(classes.cell, classes.loading)}>{loadingLabel}</div>
|
|
93
99
|
) : (
|
|
94
100
|
<>
|
|
95
|
-
{
|
|
101
|
+
{isStringNotEmpty(defaultOptionLabel) && (
|
|
96
102
|
<ScrollIntoViewIfNeeded
|
|
97
103
|
active={focusedIndex === DEFAULT_OPTION_INDEX}
|
|
98
104
|
options={{ block: 'nearest' }}
|
|
@@ -106,7 +112,7 @@ export function SelectList<Value>({
|
|
|
106
112
|
{defaultOptionLabel}
|
|
107
113
|
</ScrollIntoViewIfNeeded>
|
|
108
114
|
)}
|
|
109
|
-
{
|
|
115
|
+
{isStringNotEmpty(allOptionsLabel) && (
|
|
110
116
|
<SelectListItem
|
|
111
117
|
classes={classes}
|
|
112
118
|
index={ALL_OPTION_INDEX}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ReactNode, MouseEvent, FC } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
3
|
import { Classes } from 'jss';
|
|
4
|
-
import {
|
|
4
|
+
import { isNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
5
|
+
import { addDataAttributes } from '../../../helpers';
|
|
5
6
|
import { Checkbox } from '../../Checkbox';
|
|
6
7
|
import { ScrollIntoViewIfNeeded } from '../../ScrollIntoViewIfNeeded';
|
|
7
8
|
import { checkboxStyles } from './SelectListItem.styles';
|