@dr.pogodin/react-utils 1.43.22 → 1.43.24
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/build/development/shared/components/TextArea/index.js +29 -5
- package/build/development/shared/components/TextArea/index.js.map +1 -1
- package/build/development/style.css +7 -1
- package/build/development/web.bundle.js +2 -2
- package/build/production/shared/components/TextArea/index.js +16 -4
- package/build/production/shared/components/TextArea/index.js.map +1 -1
- package/build/production/style.css +1 -1
- package/build/production/style.css.map +1 -1
- package/build/production/web.bundle.js +1 -1
- package/build/production/web.bundle.js.map +1 -1
- package/build/types-code/shared/components/TextArea/index.d.ts +3 -1
- package/build/types-scss/src/shared/components/TextArea/style.scss.d.ts +1 -0
- package/package.json +1 -1
- package/src/shared/components/TextArea/index.tsx +26 -3
- package/src/shared/components/TextArea/style.scss +8 -1
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { type ChangeEventHandler, type FocusEventHandler, type KeyboardEventHandler } from 'react';
|
|
2
2
|
import { type Theme } from '@dr.pogodin/react-themes';
|
|
3
|
-
type ThemeKeyT = 'container' | 'hidden' | 'textarea';
|
|
3
|
+
type ThemeKeyT = 'container' | 'hidden' | 'label' | 'textarea';
|
|
4
4
|
type Props = {
|
|
5
5
|
disabled?: boolean;
|
|
6
|
+
label?: string;
|
|
6
7
|
onBlur?: FocusEventHandler<HTMLTextAreaElement>;
|
|
7
8
|
onChange?: ChangeEventHandler<HTMLTextAreaElement>;
|
|
8
9
|
onKeyDown?: KeyboardEventHandler<HTMLTextAreaElement>;
|
|
9
10
|
placeholder?: string;
|
|
11
|
+
testId?: string;
|
|
10
12
|
theme: Theme<ThemeKeyT>;
|
|
11
13
|
value?: string;
|
|
12
14
|
};
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type FunctionComponent,
|
|
5
5
|
type KeyboardEventHandler,
|
|
6
6
|
useEffect,
|
|
7
|
+
useLayoutEffect,
|
|
7
8
|
useRef,
|
|
8
9
|
useState,
|
|
9
10
|
} from 'react';
|
|
@@ -15,24 +16,29 @@ import defaultTheme from './style.scss';
|
|
|
15
16
|
type ThemeKeyT =
|
|
16
17
|
| 'container'
|
|
17
18
|
| 'hidden'
|
|
19
|
+
| 'label'
|
|
18
20
|
| 'textarea';
|
|
19
21
|
|
|
20
22
|
type Props = {
|
|
21
23
|
disabled?: boolean;
|
|
24
|
+
label?: string;
|
|
22
25
|
onBlur?: FocusEventHandler<HTMLTextAreaElement>;
|
|
23
26
|
onChange?: ChangeEventHandler<HTMLTextAreaElement>;
|
|
24
27
|
onKeyDown?: KeyboardEventHandler<HTMLTextAreaElement>;
|
|
25
28
|
placeholder?: string;
|
|
29
|
+
testId?: string;
|
|
26
30
|
theme: Theme<ThemeKeyT>;
|
|
27
31
|
value?: string;
|
|
28
32
|
};
|
|
29
33
|
|
|
30
34
|
const TextArea: FunctionComponent<Props> = ({
|
|
31
35
|
disabled,
|
|
36
|
+
label,
|
|
32
37
|
onBlur,
|
|
33
38
|
onChange,
|
|
34
39
|
onKeyDown,
|
|
35
40
|
placeholder,
|
|
41
|
+
testId,
|
|
36
42
|
theme,
|
|
37
43
|
value,
|
|
38
44
|
}) => {
|
|
@@ -58,14 +64,21 @@ const TextArea: FunctionComponent<Props> = ({
|
|
|
58
64
|
};
|
|
59
65
|
}, []);
|
|
60
66
|
|
|
61
|
-
//
|
|
62
|
-
|
|
67
|
+
// Resizes the text area when its content is modified.
|
|
68
|
+
//
|
|
69
|
+
// NOTE: useLayoutEffect() instead of useEffect() makes difference here,
|
|
70
|
+
// as it helps to avoid visible "content/height" jumps (i.e. with just
|
|
71
|
+
// useEffect() it becomes visible how the content is modified first,
|
|
72
|
+
// and then input height is incremented, if necessary).
|
|
73
|
+
// See: https://github.com/birdofpreyru/react-utils/issues/313
|
|
74
|
+
useLayoutEffect(() => {
|
|
63
75
|
const el = hiddenAreaRef.current;
|
|
64
76
|
if (el) setHeight(el.scrollHeight);
|
|
65
77
|
}, [localValue]);
|
|
66
78
|
|
|
67
79
|
return (
|
|
68
80
|
<div className={theme.container}>
|
|
81
|
+
{label === undefined ? null : <div className={theme.label}>{label}</div>}
|
|
69
82
|
<textarea
|
|
70
83
|
className={`${theme.textarea} ${theme.hidden}`}
|
|
71
84
|
|
|
@@ -74,10 +87,20 @@ const TextArea: FunctionComponent<Props> = ({
|
|
|
74
87
|
// of the primary textarea's height.
|
|
75
88
|
readOnly
|
|
76
89
|
ref={hiddenAreaRef}
|
|
77
|
-
|
|
90
|
+
|
|
91
|
+
// The "-1" value of "tabIndex" removes this hidden text area from
|
|
92
|
+
// the tab-focus-chain.
|
|
93
|
+
tabIndex={-1}
|
|
94
|
+
|
|
95
|
+
// NOTE: With empty string value ("") the scrolling height of this text
|
|
96
|
+
// area is zero, thus collapsing <TextArea> height below the single line
|
|
97
|
+
// input height. To avoid it we fallback to whitespace (" ") character
|
|
98
|
+
// here.
|
|
99
|
+
value={localValue || ' '}
|
|
78
100
|
/>
|
|
79
101
|
<textarea
|
|
80
102
|
className={theme.textarea}
|
|
103
|
+
data-testid={process.env.NODE_ENV === 'production' ? undefined : testId}
|
|
81
104
|
disabled={disabled}
|
|
82
105
|
onBlur={onBlur}
|
|
83
106
|
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
position: relative;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
&.label {
|
|
12
|
+
margin: 0 0.3em;
|
|
13
|
+
}
|
|
14
|
+
|
|
11
15
|
&.textarea {
|
|
12
16
|
background: white;
|
|
13
17
|
border: 1px solid gray;
|
|
@@ -19,6 +23,7 @@
|
|
|
19
23
|
overflow: hidden;
|
|
20
24
|
padding: 0.3em 0.3em calc(0.3em + 1px);
|
|
21
25
|
resize: none;
|
|
26
|
+
width: 100%;
|
|
22
27
|
|
|
23
28
|
&:focus {
|
|
24
29
|
border-color: blue;
|
|
@@ -38,7 +43,9 @@
|
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
&.hidden {
|
|
46
|
+
// NOTE: We hide it this way, as setting "display: none" will interfere
|
|
47
|
+
// with measurements, making the hidden input height zero.
|
|
48
|
+
opacity: 0;
|
|
41
49
|
position: absolute;
|
|
42
|
-
z-index: -1;
|
|
43
50
|
}
|
|
44
51
|
}
|