@true-engineering/true-react-common-ui-kit 4.0.0-alpha20 → 4.0.0-alpha22
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/IncrementInput/IncrementInput.styles.d.ts +1 -3
- package/dist/components/Input/InputBase.d.ts +1 -1
- package/dist/components/TextArea/TextArea.d.ts +2 -0
- package/dist/components/TextArea/TextArea.styles.d.ts +4 -2
- package/dist/components/TextArea/types.d.ts +4 -0
- package/dist/true-react-common-ui-kit.js +128 -122
- package/dist/true-react-common-ui-kit.js.map +1 -1
- package/dist/true-react-common-ui-kit.umd.cjs +128 -122
- package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
- package/package.json +1 -1
- package/src/components/ControlWrapper/ControlWrapper.stories.tsx +1 -1
- package/src/components/IncrementInput/IncrementInput.stories.tsx +2 -0
- package/src/components/IncrementInput/IncrementInput.styles.ts +31 -39
- package/src/components/IncrementInput/IncrementInput.tsx +28 -25
- package/src/components/Input/InputBase.tsx +3 -1
- package/src/components/TextArea/TextArea.stories.tsx +14 -1
- package/src/components/TextArea/TextArea.styles.ts +11 -1
- package/src/components/TextArea/TextArea.tsx +65 -55
- package/src/components/TextArea/types.ts +6 -0
- package/src/components/WithMessages/WithMessages.stories.tsx +1 -1
package/package.json
CHANGED
|
@@ -1,41 +1,44 @@
|
|
|
1
1
|
import { animations, colors, createThemedStyles, dimensions, ITweakStyles } from '../../theme';
|
|
2
2
|
import { IInputStyles } from '../Input';
|
|
3
3
|
|
|
4
|
-
export const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
export const inputStyles: IInputStyles = {
|
|
5
|
+
tweakControlWrapper: {
|
|
6
|
+
controlWrapper: {
|
|
7
|
+
'--increment-buttons-width': '36px',
|
|
8
|
+
'--increment-buttons-gap': '1px',
|
|
9
|
+
'--increment-buttons-margin': '1px',
|
|
10
|
+
'--increment-button-icon-size': '16px',
|
|
11
|
+
},
|
|
12
12
|
},
|
|
13
|
+
};
|
|
13
14
|
|
|
15
|
+
export const useStyles = createThemedStyles('IncrementInput', {
|
|
14
16
|
buttons: {
|
|
15
17
|
display: 'flex',
|
|
16
18
|
flexDirection: 'column',
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
height: 'calc(100% - var(--increment-buttons-margin) * 2)',
|
|
20
|
+
margin: 'var(--increment-buttons-margin)',
|
|
21
|
+
gap: 'var(--increment-buttons-gap)',
|
|
22
|
+
flexShrink: 0,
|
|
23
|
+
order: 1000, // сдвигаем кнопки на самый конец
|
|
24
|
+
|
|
22
25
|
zIndex: dimensions.Z_INDEX.CONTROL_FOCUS + 1,
|
|
23
26
|
},
|
|
24
27
|
|
|
25
28
|
button: {
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
display: 'flex',
|
|
30
|
+
alignItems: 'center',
|
|
31
|
+
justifyContent: 'center',
|
|
32
|
+
width: 'var(--increment-buttons-width)',
|
|
33
|
+
flexGrow: 1,
|
|
34
|
+
|
|
35
|
+
cursor: 'pointer',
|
|
28
36
|
border: 'none',
|
|
29
37
|
outline: 'none',
|
|
38
|
+
color: colors.FONT_MEDIUM,
|
|
30
39
|
backgroundColor: colors.GREY_BACKGROUND,
|
|
31
40
|
transition: animations.defaultTransition,
|
|
32
|
-
transitionProperty: 'background-color',
|
|
33
|
-
color: colors.FONT_MEDIUM,
|
|
34
|
-
cursor: 'pointer',
|
|
35
|
-
display: 'flex',
|
|
36
|
-
alignItems: 'center',
|
|
37
|
-
justifyContent: 'center',
|
|
38
|
-
padding: [0, 10],
|
|
41
|
+
transitionProperty: 'background-color, color',
|
|
39
42
|
|
|
40
43
|
'&:hover, &:focus': {
|
|
41
44
|
backgroundColor: colors.GREY_HOVER,
|
|
@@ -44,16 +47,12 @@ export const useStyles = createThemedStyles('IncrementInput', {
|
|
|
44
47
|
'&:active': {
|
|
45
48
|
backgroundColor: colors.GREY_ACTIVE,
|
|
46
49
|
},
|
|
47
|
-
|
|
48
|
-
'&:first-child': {
|
|
49
|
-
marginBottom: 1,
|
|
50
|
-
},
|
|
51
50
|
},
|
|
52
51
|
|
|
53
52
|
disabledButton: {
|
|
54
|
-
backgroundColor: colors.CLASSIC_WHITE,
|
|
55
|
-
color: colors.FONT_DISABLED,
|
|
56
53
|
cursor: 'default',
|
|
54
|
+
color: colors.FONT_DISABLED,
|
|
55
|
+
backgroundColor: colors.CLASSIC_WHITE,
|
|
57
56
|
|
|
58
57
|
'&:hover': {
|
|
59
58
|
backgroundColor: colors.CLASSIC_WHITE,
|
|
@@ -61,18 +60,11 @@ export const useStyles = createThemedStyles('IncrementInput', {
|
|
|
61
60
|
},
|
|
62
61
|
|
|
63
62
|
errorButton: {},
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
export const inputStyles: IInputStyles = {
|
|
67
|
-
input: {
|
|
68
|
-
paddingRight: BUTTONS_WIDTH + BUTTONS_GAP,
|
|
69
|
-
},
|
|
70
63
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
},
|
|
64
|
+
icon: {
|
|
65
|
+
width: 'var(--increment-button-icon-size)',
|
|
66
|
+
height: 'var(--increment-button-icon-size)',
|
|
75
67
|
},
|
|
76
|
-
};
|
|
68
|
+
});
|
|
77
69
|
|
|
78
70
|
export type IIncrementInputStyles = ITweakStyles<typeof useStyles, { tweakInput: IInputStyles }>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FC, useEffect } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { isNotEmpty, isNumberInteger } from '@true-engineering/true-react-platform-helpers';
|
|
4
|
+
import { getNumberInRange, getNumberLength } from '../../helpers';
|
|
5
5
|
import { useTweakStyles } from '../../hooks';
|
|
6
6
|
import { ICommonProps } from '../../types';
|
|
7
7
|
import { Icon } from '../Icon';
|
|
@@ -22,8 +22,6 @@ export const IncrementInput: FC<IIncrementInputProps> = ({
|
|
|
22
22
|
max,
|
|
23
23
|
step = 1,
|
|
24
24
|
intPartPrecision,
|
|
25
|
-
data,
|
|
26
|
-
testId,
|
|
27
25
|
tweakStyles,
|
|
28
26
|
isDisabled,
|
|
29
27
|
isReadonly,
|
|
@@ -39,14 +37,15 @@ export const IncrementInput: FC<IIncrementInputProps> = ({
|
|
|
39
37
|
|
|
40
38
|
const classes = useStyles({ theme: tweakStyles });
|
|
41
39
|
|
|
40
|
+
const isEditDisabled = isDisabled || isReadonly;
|
|
41
|
+
|
|
42
42
|
const isIncreaseDisabled =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
(
|
|
46
|
-
(max !== undefined && value !== undefined && value >= max);
|
|
43
|
+
isEditDisabled ||
|
|
44
|
+
(isNotEmpty(intPartPrecision) && getNumberLength((value ?? 0) + step) > intPartPrecision) ||
|
|
45
|
+
(isNotEmpty(max) && isNotEmpty(value) && value >= max);
|
|
47
46
|
|
|
48
47
|
const isDecreaseDisabled =
|
|
49
|
-
|
|
48
|
+
isEditDisabled || (isNotEmpty(min) && isNotEmpty(value) && value <= min);
|
|
50
49
|
|
|
51
50
|
const increment = (): void => {
|
|
52
51
|
onChange(getNumberInRange((value ?? 0) + step, min, max));
|
|
@@ -63,19 +62,18 @@ export const IncrementInput: FC<IIncrementInputProps> = ({
|
|
|
63
62
|
}, [step]);
|
|
64
63
|
|
|
65
64
|
return (
|
|
66
|
-
<
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
/>
|
|
65
|
+
<NumberInput
|
|
66
|
+
{...props}
|
|
67
|
+
isInvalid={isInvalid}
|
|
68
|
+
isDisabled={isDisabled}
|
|
69
|
+
isReadonly={isReadonly}
|
|
70
|
+
min={min}
|
|
71
|
+
max={max}
|
|
72
|
+
intPartPrecision={intPartPrecision}
|
|
73
|
+
onChange={onChange}
|
|
74
|
+
value={value}
|
|
75
|
+
tweakStyles={tweakInputStyles}
|
|
76
|
+
>
|
|
79
77
|
<div className={classes.buttons}>
|
|
80
78
|
<button
|
|
81
79
|
className={clsx(classes.button, {
|
|
@@ -86,8 +84,11 @@ export const IncrementInput: FC<IIncrementInputProps> = ({
|
|
|
86
84
|
disabled={isIncreaseDisabled}
|
|
87
85
|
onClick={increment}
|
|
88
86
|
>
|
|
89
|
-
<
|
|
87
|
+
<div className={classes.icon}>
|
|
88
|
+
<Icon type="plus" />
|
|
89
|
+
</div>
|
|
90
90
|
</button>
|
|
91
|
+
|
|
91
92
|
<button
|
|
92
93
|
className={clsx(classes.button, {
|
|
93
94
|
[classes.disabledButton]: isDecreaseDisabled,
|
|
@@ -97,9 +98,11 @@ export const IncrementInput: FC<IIncrementInputProps> = ({
|
|
|
97
98
|
disabled={isDecreaseDisabled}
|
|
98
99
|
onClick={decrement}
|
|
99
100
|
>
|
|
100
|
-
<
|
|
101
|
+
<div className={classes.icon}>
|
|
102
|
+
<Icon type="minus" />
|
|
103
|
+
</div>
|
|
101
104
|
</button>
|
|
102
105
|
</div>
|
|
103
|
-
</
|
|
106
|
+
</NumberInput>
|
|
104
107
|
);
|
|
105
108
|
};
|
|
@@ -33,13 +33,13 @@ export interface IInputBaseProps
|
|
|
33
33
|
IControlWrapperProps,
|
|
34
34
|
| 'label'
|
|
35
35
|
| 'icon'
|
|
36
|
+
| 'size'
|
|
36
37
|
| 'groupPlacement'
|
|
37
38
|
| 'isInvalid'
|
|
38
39
|
| 'isRequired'
|
|
39
40
|
| 'isLoading'
|
|
40
41
|
| 'isDisabled'
|
|
41
42
|
| 'onIconClick'
|
|
42
|
-
| 'size'
|
|
43
43
|
>,
|
|
44
44
|
Pick<
|
|
45
45
|
Partial<ReactInputMaskBaseProps>,
|
|
@@ -103,6 +103,7 @@ export const InputBase = forwardRef<HTMLInputElement, IInputBaseProps>(
|
|
|
103
103
|
isRequired,
|
|
104
104
|
size,
|
|
105
105
|
onIconClick,
|
|
106
|
+
children,
|
|
106
107
|
...inputProps
|
|
107
108
|
},
|
|
108
109
|
ref,
|
|
@@ -248,6 +249,7 @@ export const InputBase = forwardRef<HTMLInputElement, IInputBaseProps>(
|
|
|
248
249
|
) : (
|
|
249
250
|
inputContent
|
|
250
251
|
)}
|
|
252
|
+
{children}
|
|
251
253
|
</ControlWrapper>
|
|
252
254
|
);
|
|
253
255
|
},
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { useState } from 'react';
|
|
2
2
|
import { ComponentStory } from '@storybook/react';
|
|
3
|
+
import { IExtendableProps } from '../../types';
|
|
3
4
|
import { TextArea } from './TextArea';
|
|
4
5
|
|
|
6
|
+
const COUNTER_POSITIONS = ['default', 'top'] as const;
|
|
7
|
+
|
|
5
8
|
export default {
|
|
6
9
|
title: 'Inputs/TextArea',
|
|
7
10
|
component: TextArea,
|
|
@@ -12,9 +15,14 @@ export default {
|
|
|
12
15
|
},
|
|
13
16
|
};
|
|
14
17
|
|
|
18
|
+
declare module './types' {
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
20
|
+
export interface ITextAreaCounterPositions extends IExtendableProps<typeof COUNTER_POSITIONS> {}
|
|
21
|
+
}
|
|
22
|
+
|
|
15
23
|
const Template: ComponentStory<typeof TextArea> = (args) => {
|
|
16
24
|
const [value, setValue] = useState('');
|
|
17
|
-
return <TextArea {...args} value={value} onChange={
|
|
25
|
+
return <TextArea {...args} value={value} onChange={setValue} />;
|
|
18
26
|
};
|
|
19
27
|
|
|
20
28
|
export const Default = Template.bind({});
|
|
@@ -26,6 +34,7 @@ Default.args = {
|
|
|
26
34
|
rows: 5,
|
|
27
35
|
maxLength: 500,
|
|
28
36
|
isInvalid: false,
|
|
37
|
+
counterPosition: 'default',
|
|
29
38
|
errorMessage: 'Error Text',
|
|
30
39
|
isActive: false,
|
|
31
40
|
isDisabled: false,
|
|
@@ -33,3 +42,7 @@ Default.args = {
|
|
|
33
42
|
isAutoSized: true,
|
|
34
43
|
shouldAlwaysShowPlaceholder: false,
|
|
35
44
|
};
|
|
45
|
+
|
|
46
|
+
Default.argTypes = {
|
|
47
|
+
counterPosition: { options: [undefined, ...COUNTER_POSITIONS], control: 'select' },
|
|
48
|
+
};
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { animations, createThemedStyles, helpers, ITweakStyles } from '../../theme';
|
|
2
|
+
import { IWithPrefix } from '../../types';
|
|
2
3
|
import { IControlWrapperStyles } from '../ControlWrapper';
|
|
3
4
|
import { IWithMessagesStyles } from '../WithMessages';
|
|
5
|
+
import { ITextAreaCounterPositions } from './types';
|
|
4
6
|
|
|
5
7
|
export const useStyles = createThemedStyles('TextArea', {
|
|
8
|
+
root: {
|
|
9
|
+
width: '100%',
|
|
10
|
+
},
|
|
11
|
+
|
|
6
12
|
textarea: {
|
|
7
13
|
...helpers.withScrollBar,
|
|
8
14
|
width: '100%',
|
|
@@ -66,6 +72,10 @@ export const useStyles = createThemedStyles('TextArea', {
|
|
|
66
72
|
color: 'red',
|
|
67
73
|
},
|
|
68
74
|
|
|
75
|
+
symbolsCountActive: {},
|
|
76
|
+
|
|
77
|
+
'counter-default': {},
|
|
78
|
+
|
|
69
79
|
withLabel: {},
|
|
70
80
|
});
|
|
71
81
|
|
|
@@ -74,5 +84,5 @@ export type ITextAreaStyles = ITweakStyles<
|
|
|
74
84
|
{
|
|
75
85
|
tweakWithMessages: IWithMessagesStyles;
|
|
76
86
|
tweakControlWrapper: IControlWrapperStyles;
|
|
77
|
-
}
|
|
87
|
+
} & IWithPrefix<ITextAreaCounterPositions, 'counter-'>
|
|
78
88
|
>;
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
TextareaHTMLAttributes,
|
|
7
7
|
useState,
|
|
8
8
|
} from 'react';
|
|
9
|
+
import { Styles } from 'react-jss';
|
|
9
10
|
import clsx from 'clsx';
|
|
10
11
|
import {
|
|
11
12
|
addDataAttributes,
|
|
@@ -19,6 +20,7 @@ import { useTweakStyles } from '../../hooks';
|
|
|
19
20
|
import { ICommonProps } from '../../types';
|
|
20
21
|
import { ControlWrapper, IControlWrapperProps } from '../ControlWrapper';
|
|
21
22
|
import { IWithMessagesProps, WithMessages } from '../WithMessages';
|
|
23
|
+
import { ITextAreaCounterPosition } from './types';
|
|
22
24
|
import { ITextAreaStyles, useStyles } from './TextArea.styles';
|
|
23
25
|
|
|
24
26
|
export interface ITextAreaProps
|
|
@@ -31,6 +33,7 @@ export interface ITextAreaProps
|
|
|
31
33
|
Pick<IWithMessagesProps, 'infoMessage' | 'errorMessage'> {
|
|
32
34
|
value?: string;
|
|
33
35
|
placeholder?: string;
|
|
36
|
+
counterPosition?: ITextAreaCounterPosition;
|
|
34
37
|
/** @default false */
|
|
35
38
|
isActive?: boolean;
|
|
36
39
|
/**
|
|
@@ -49,14 +52,13 @@ export interface ITextAreaProps
|
|
|
49
52
|
onChange: (value: string, event?: FormEvent<HTMLTextAreaElement>) => void;
|
|
50
53
|
}
|
|
51
54
|
|
|
52
|
-
const DEFAULT_VALUE = '';
|
|
53
|
-
|
|
54
55
|
export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
|
|
55
56
|
(
|
|
56
57
|
{
|
|
57
|
-
value =
|
|
58
|
+
value = '',
|
|
58
59
|
placeholder,
|
|
59
60
|
name,
|
|
61
|
+
counterPosition = 'default',
|
|
60
62
|
shouldFocusOnMount,
|
|
61
63
|
hasCounter = true,
|
|
62
64
|
shouldTrimAfterMaxLength,
|
|
@@ -88,6 +90,9 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
|
|
|
88
90
|
) => {
|
|
89
91
|
const classes = useStyles({ theme: tweakStyles });
|
|
90
92
|
|
|
93
|
+
const shouldShowCounter = hasCounter && isNotEmpty(maxLength);
|
|
94
|
+
const counterString = `${value.length} / ${maxLength}`;
|
|
95
|
+
|
|
91
96
|
const tweakWithMessagesStyles = useTweakStyles({
|
|
92
97
|
tweakStyles,
|
|
93
98
|
className: 'tweakWithMessages',
|
|
@@ -123,60 +128,65 @@ export const TextArea = forwardRef<HTMLTextAreaElement, ITextAreaProps>(
|
|
|
123
128
|
};
|
|
124
129
|
|
|
125
130
|
return (
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
<ControlWrapper
|
|
133
|
-
label={label}
|
|
134
|
-
tweakStyles={tweakControlWrapperStyles}
|
|
135
|
-
isFocused={hasFocus}
|
|
136
|
-
isDisabled={isDisabled}
|
|
137
|
-
hasValue={hasValue}
|
|
138
|
-
isInvalid={isInvalid}
|
|
139
|
-
isRequired={isRequired}
|
|
140
|
-
groupPlacement={groupPlacement}
|
|
141
|
-
size={size}
|
|
142
|
-
isFullWidth
|
|
131
|
+
<div className={classes.root} style={{ '--counter-length': counterString.length } as Styles}>
|
|
132
|
+
<WithMessages
|
|
133
|
+
errorMessage={errorMessage}
|
|
134
|
+
infoMessage={infoMessage}
|
|
135
|
+
tweakStyles={tweakWithMessagesStyles}
|
|
136
|
+
testId={getTestId(testId, 'wrapper')}
|
|
143
137
|
>
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
{
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
disabled={isDisabled}
|
|
156
|
-
placeholder={hasPlaceholder ? placeholder : undefined}
|
|
157
|
-
maxLength={shouldTrimAfterMaxLength ? maxLength : undefined}
|
|
158
|
-
name={name}
|
|
159
|
-
rows={rows}
|
|
160
|
-
onPaste={onPaste}
|
|
161
|
-
onFocus={handleFocus}
|
|
162
|
-
onBlur={handleBlur}
|
|
163
|
-
onChange={handleChange}
|
|
164
|
-
autoFocus={shouldFocusOnMount}
|
|
165
|
-
{...addDataAttributes(data, testId)}
|
|
166
|
-
{...textAreaProps}
|
|
167
|
-
/>
|
|
168
|
-
</div>
|
|
169
|
-
</ControlWrapper>
|
|
170
|
-
{hasCounter && isNotEmpty(maxLength) && (
|
|
171
|
-
<span
|
|
172
|
-
className={clsx(classes.symbolsCount, {
|
|
173
|
-
[classes.symbolsCountError]: value.length > maxLength,
|
|
174
|
-
})}
|
|
138
|
+
<ControlWrapper
|
|
139
|
+
label={label}
|
|
140
|
+
tweakStyles={tweakControlWrapperStyles}
|
|
141
|
+
isFocused={hasFocus}
|
|
142
|
+
isDisabled={isDisabled}
|
|
143
|
+
hasValue={hasValue}
|
|
144
|
+
isInvalid={isInvalid}
|
|
145
|
+
isRequired={isRequired}
|
|
146
|
+
groupPlacement={groupPlacement}
|
|
147
|
+
size={size}
|
|
148
|
+
isFullWidth
|
|
175
149
|
>
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
150
|
+
<div
|
|
151
|
+
className={clsx(classes.wrapper, isNotEmpty(size) && classes[size], {
|
|
152
|
+
[classes.autoSized]: isAutoSized,
|
|
153
|
+
[classes.withLabel]: hasLabel,
|
|
154
|
+
})}
|
|
155
|
+
// Не менять на addDataAttributes
|
|
156
|
+
{...(isAutoSized && { 'data-value': value })}
|
|
157
|
+
>
|
|
158
|
+
<textarea
|
|
159
|
+
ref={ref}
|
|
160
|
+
className={classes.textarea}
|
|
161
|
+
value={value}
|
|
162
|
+
disabled={isDisabled}
|
|
163
|
+
placeholder={hasPlaceholder ? placeholder : undefined}
|
|
164
|
+
maxLength={shouldTrimAfterMaxLength ? maxLength : undefined}
|
|
165
|
+
name={name}
|
|
166
|
+
rows={rows}
|
|
167
|
+
onPaste={onPaste}
|
|
168
|
+
onFocus={handleFocus}
|
|
169
|
+
onBlur={handleBlur}
|
|
170
|
+
onChange={handleChange}
|
|
171
|
+
autoFocus={shouldFocusOnMount}
|
|
172
|
+
{...addDataAttributes(data, testId)}
|
|
173
|
+
{...textAreaProps}
|
|
174
|
+
/>
|
|
175
|
+
{shouldShowCounter && (
|
|
176
|
+
<span
|
|
177
|
+
className={clsx(classes.symbolsCount, classes[`counter-${counterPosition}`], {
|
|
178
|
+
[classes.symbolsCountError]: value.length > maxLength,
|
|
179
|
+
[classes.symbolsCountActive]: hasFocus || hasValue,
|
|
180
|
+
})}
|
|
181
|
+
{...addDataAttributes({ counterPosition })}
|
|
182
|
+
>
|
|
183
|
+
{counterString}
|
|
184
|
+
</span>
|
|
185
|
+
)}
|
|
186
|
+
</div>
|
|
187
|
+
</ControlWrapper>
|
|
188
|
+
</WithMessages>
|
|
189
|
+
</div>
|
|
180
190
|
);
|
|
181
191
|
},
|
|
182
192
|
);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
2
|
+
import { IExtendableProps } from '../../types';
|
|
3
|
+
|
|
4
|
+
export interface ITextAreaCounterPositions extends IExtendableProps<'default'> {}
|
|
5
|
+
|
|
6
|
+
export type ITextAreaCounterPosition = keyof ITextAreaCounterPositions;
|