@hero-design/rn 8.124.2 → 8.126.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/CHANGELOG.md +25 -0
- package/assets/fonts/BeVietnamPro-Medium.ttf +0 -0
- package/assets/fonts/BeVietnamPro-MediumItalic.ttf +0 -0
- package/es/index.js +207 -140
- package/lib/index.js +207 -140
- package/package.json +2 -2
- package/src/components/Badge/Status.tsx +8 -1
- package/src/components/Badge/StyledBadge.tsx +2 -1
- package/src/components/Badge/types.ts +8 -1
- package/src/components/RichTextEditor/RichTextEditor.tsx +88 -74
- package/src/components/Search/StyledSearch.tsx +1 -1
- package/src/components/TextInput/StyledTextInput.tsx +74 -24
- package/src/components/TextInput/index.tsx +126 -103
- package/src/components/Typography/Body/StyledBody.tsx +16 -8
- package/src/components/Typography/Body/index.tsx +12 -3
- package/src/components/Typography/Caption/StyledCaption.tsx +10 -2
- package/src/components/Typography/Caption/index.tsx +1 -1
- package/src/components/Typography/Label/StyledLabel.tsx +4 -5
- package/src/components/Typography/Label/index.tsx +7 -0
- package/src/components/Typography/types.ts +1 -0
- package/src/theme/components/badge.ts +5 -2
- package/src/theme/components/textInput.ts +32 -19
- package/src/theme/components/typography.ts +2 -0
- package/src/theme/global/typography.ts +6 -0
- package/types/components/Badge/Status.d.ts +1 -1
- package/types/components/Badge/StyledBadge.d.ts +1 -1
- package/types/components/Badge/types.d.ts +1 -1
- package/types/components/TextInput/StyledTextInput.d.ts +29 -15
- package/types/components/Typography/Body/StyledBody.d.ts +1 -1
- package/types/components/Typography/Body/index.d.ts +6 -3
- package/types/components/Typography/Caption/StyledCaption.d.ts +1 -1
- package/types/components/Typography/Caption/index.d.ts +1 -1
- package/types/components/Typography/Label/StyledLabel.d.ts +1 -0
- package/types/components/Typography/Label/index.d.ts +6 -1
- package/types/components/Typography/types.d.ts +1 -0
- package/types/theme/components/badge.d.ts +3 -0
- package/types/theme/components/textInput.d.ts +17 -5
- package/types/theme/components/typography.d.ts +2 -0
- package/types/theme/global/typography.d.ts +2 -0
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hero-design/rn",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.126.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"module": "es/index.js",
|
|
7
|
-
"react-native": "src/index.ts",
|
|
8
7
|
"types": "types/index.d.ts",
|
|
8
|
+
"react-native": "src/index.ts",
|
|
9
9
|
"scripts": {
|
|
10
10
|
"lint": "eslint src --quiet",
|
|
11
11
|
"type-check": "tsc --noEmit",
|
|
@@ -16,7 +16,14 @@ export interface StatusProps extends ViewProps {
|
|
|
16
16
|
/**
|
|
17
17
|
* Visual intent color to apply to Status Badge.
|
|
18
18
|
*/
|
|
19
|
-
intent?:
|
|
19
|
+
intent?:
|
|
20
|
+
| 'success'
|
|
21
|
+
| 'warning'
|
|
22
|
+
| 'danger'
|
|
23
|
+
| 'info'
|
|
24
|
+
| 'archived'
|
|
25
|
+
| 'primary'
|
|
26
|
+
| 'neutral';
|
|
20
27
|
/**
|
|
21
28
|
* Additional style.
|
|
22
29
|
*/
|
|
@@ -13,7 +13,14 @@ interface BaseBadgeProps extends React.ComponentProps<typeof Animated.View> {
|
|
|
13
13
|
/**
|
|
14
14
|
* Visual intent color to apply to Badge.
|
|
15
15
|
*/
|
|
16
|
-
intent?:
|
|
16
|
+
intent?:
|
|
17
|
+
| 'primary'
|
|
18
|
+
| 'success'
|
|
19
|
+
| 'warning'
|
|
20
|
+
| 'danger'
|
|
21
|
+
| 'info'
|
|
22
|
+
| 'archived'
|
|
23
|
+
| 'neutral';
|
|
17
24
|
/**
|
|
18
25
|
* Additional style.
|
|
19
26
|
*/
|
|
@@ -12,7 +12,6 @@ import { Animated, Easing } from 'react-native';
|
|
|
12
12
|
import type { ReactElement, Ref } from 'react';
|
|
13
13
|
import type { LayoutChangeEvent } from 'react-native';
|
|
14
14
|
import { useTheme } from '../../theme';
|
|
15
|
-
import Icon from '../Icon';
|
|
16
15
|
import {
|
|
17
16
|
StyledAsteriskLabelInsideTextInput,
|
|
18
17
|
StyledBorderBackDrop,
|
|
@@ -22,6 +21,7 @@ import {
|
|
|
22
21
|
StyledErrorAndMaxLengthContainer,
|
|
23
22
|
StyledErrorContainer,
|
|
24
23
|
StyledHelperText,
|
|
24
|
+
StyledInputContentContainer,
|
|
25
25
|
StyledLabelContainerInsideTextInput,
|
|
26
26
|
StyledLabelInsideTextInput,
|
|
27
27
|
StyledTextInputAndLabelContainer,
|
|
@@ -102,10 +102,7 @@ const RichTextEditor = ({
|
|
|
102
102
|
return 'default';
|
|
103
103
|
}, [isFocused, error, isEmptyValue]);
|
|
104
104
|
|
|
105
|
-
const [
|
|
106
|
-
height: number;
|
|
107
|
-
width: number;
|
|
108
|
-
}>({ height: 0, width: 0 });
|
|
105
|
+
const [containerHeight, setContainerHeight] = React.useState(0);
|
|
109
106
|
|
|
110
107
|
const focusAnimation = useRef(new Animated.Value(0)).current;
|
|
111
108
|
|
|
@@ -119,10 +116,11 @@ const RichTextEditor = ({
|
|
|
119
116
|
}, [focusAnimation, isEmptyValue, isFocused]);
|
|
120
117
|
|
|
121
118
|
const onLayout = useCallback((event: LayoutChangeEvent) => {
|
|
122
|
-
|
|
123
|
-
setInputSize((prev) => ({ ...prev, height, width }));
|
|
119
|
+
setContainerHeight(event.nativeEvent.layout.height);
|
|
124
120
|
}, []);
|
|
125
121
|
|
|
122
|
+
const backgroundColor = theme.__hd__.textInput.colors.containerBackground;
|
|
123
|
+
|
|
126
124
|
const handleEditorFocus = useCallback(() => {
|
|
127
125
|
onFocus?.();
|
|
128
126
|
setIsFocused(true);
|
|
@@ -135,91 +133,107 @@ const RichTextEditor = ({
|
|
|
135
133
|
|
|
136
134
|
return (
|
|
137
135
|
<StyledContainer testID={testID}>
|
|
138
|
-
<
|
|
139
|
-
|
|
136
|
+
<StyledTextInputContainer
|
|
137
|
+
onLayout={onLayout}
|
|
140
138
|
themeVariant="text"
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
{
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
{
|
|
148
|
-
|
|
139
|
+
themeState={state}
|
|
140
|
+
>
|
|
141
|
+
<StyledBorderBackDrop
|
|
142
|
+
themeState={state}
|
|
143
|
+
themeFocused={isFocused}
|
|
144
|
+
themeFilled={!isEmptyValue}
|
|
145
|
+
style={{ backgroundColor }}
|
|
146
|
+
/>
|
|
147
|
+
|
|
148
|
+
<StyledInputContentContainer themeHasLabel={!!label}>
|
|
149
|
+
<StyledLabelContainerInsideTextInput
|
|
150
|
+
themeVariant="text"
|
|
151
|
+
pointerEvents="none"
|
|
152
|
+
testID="input-label-container"
|
|
153
|
+
style={[
|
|
149
154
|
{
|
|
150
|
-
|
|
151
|
-
inputRange: [0, 1],
|
|
152
|
-
outputRange: [inputSize.height / 2, theme.space.xsmall],
|
|
153
|
-
}),
|
|
155
|
+
transformOrigin: 'top left',
|
|
154
156
|
},
|
|
155
157
|
{
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
transform: [
|
|
159
|
+
{
|
|
160
|
+
translateY: focusAnimation.interpolate({
|
|
161
|
+
inputRange: [0, 1],
|
|
162
|
+
outputRange: [
|
|
163
|
+
Math.max(
|
|
164
|
+
0,
|
|
165
|
+
(containerHeight -
|
|
166
|
+
theme.__hd__.textInput.lineHeights.label) /
|
|
167
|
+
2
|
|
168
|
+
),
|
|
169
|
+
theme.__hd__.textInput.space.labelFocusedTranslateY,
|
|
170
|
+
],
|
|
171
|
+
}),
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
scale: focusAnimation.interpolate({
|
|
175
|
+
inputRange: [0, 1],
|
|
176
|
+
outputRange: [1, 0.75],
|
|
177
|
+
}),
|
|
178
|
+
},
|
|
179
|
+
],
|
|
160
180
|
},
|
|
161
|
-
]
|
|
162
|
-
},
|
|
163
|
-
]}
|
|
164
|
-
>
|
|
165
|
-
{!!label && (
|
|
166
|
-
<StyledLabelInsideTextInput
|
|
167
|
-
style={{
|
|
168
|
-
backgroundColor: theme.__hd__.textInput.colors.labelBackground,
|
|
169
|
-
}}
|
|
170
|
-
testID="input-label"
|
|
171
|
-
themeState={state}
|
|
181
|
+
]}
|
|
172
182
|
>
|
|
173
|
-
{
|
|
174
|
-
<
|
|
183
|
+
{!!label && (
|
|
184
|
+
<StyledLabelInsideTextInput
|
|
175
185
|
style={{
|
|
176
186
|
backgroundColor:
|
|
177
187
|
theme.__hd__.textInput.colors.labelBackground,
|
|
178
188
|
}}
|
|
189
|
+
testID="input-label"
|
|
179
190
|
themeState={state}
|
|
180
191
|
>
|
|
181
|
-
|
|
182
|
-
|
|
192
|
+
{required && (
|
|
193
|
+
<StyledAsteriskLabelInsideTextInput
|
|
194
|
+
style={{
|
|
195
|
+
backgroundColor:
|
|
196
|
+
theme.__hd__.textInput.colors.labelBackground,
|
|
197
|
+
}}
|
|
198
|
+
themeState={state}
|
|
199
|
+
>
|
|
200
|
+
*
|
|
201
|
+
</StyledAsteriskLabelInsideTextInput>
|
|
202
|
+
)}
|
|
203
|
+
<Typography.Body intent="muted" numberOfLines={1}>
|
|
204
|
+
{label}
|
|
205
|
+
</Typography.Body>
|
|
206
|
+
</StyledLabelInsideTextInput>
|
|
183
207
|
)}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
onFocus={handleEditorFocus}
|
|
209
|
-
onCursorChange={onCursorChange}
|
|
210
|
-
/>
|
|
211
|
-
</StyledTextInputAndLabelContainer>
|
|
208
|
+
</StyledLabelContainerInsideTextInput>
|
|
209
|
+
|
|
210
|
+
<StyledTextInputAndLabelContainer themeHasLabel={!!label}>
|
|
211
|
+
<RichTextEditorInput
|
|
212
|
+
name={name}
|
|
213
|
+
value={value}
|
|
214
|
+
style={[
|
|
215
|
+
style,
|
|
216
|
+
{
|
|
217
|
+
marginHorizontal:
|
|
218
|
+
theme.__hd__.textInput.space.inputHorizontalMargin,
|
|
219
|
+
},
|
|
220
|
+
]}
|
|
221
|
+
testID="webview"
|
|
222
|
+
onChange={onChange}
|
|
223
|
+
autoFocus={autoFocus}
|
|
224
|
+
editorRef={forwardedRef}
|
|
225
|
+
placeholder={placeholder}
|
|
226
|
+
onBlur={handleEditorBlur}
|
|
227
|
+
onFocus={handleEditorFocus}
|
|
228
|
+
onCursorChange={onCursorChange}
|
|
229
|
+
/>
|
|
230
|
+
</StyledTextInputAndLabelContainer>
|
|
231
|
+
</StyledInputContentContainer>
|
|
212
232
|
</StyledTextInputContainer>
|
|
213
233
|
<StyledErrorAndHelpTextContainer>
|
|
214
234
|
<StyledErrorAndMaxLengthContainer>
|
|
215
235
|
{error ? (
|
|
216
236
|
<StyledErrorContainer>
|
|
217
|
-
<Icon
|
|
218
|
-
testID="input-error-icon"
|
|
219
|
-
icon="circle-info"
|
|
220
|
-
size="xsmall"
|
|
221
|
-
intent="danger"
|
|
222
|
-
/>
|
|
223
237
|
<StyledError testID="input-error-message">{error}</StyledError>
|
|
224
238
|
</StyledErrorContainer>
|
|
225
239
|
) : (
|
|
@@ -48,7 +48,7 @@ export const StyledSuffixContainer = styled(View)(({ theme }) => ({
|
|
|
48
48
|
export const StyledInput = styled(TextInput)(({ theme }) => ({
|
|
49
49
|
textAlignVertical: 'center',
|
|
50
50
|
fontSize: theme.__hd__.search.fontSizes.text,
|
|
51
|
-
color: theme.__hd__.textInput.colors.text,
|
|
51
|
+
color: theme.__hd__.textInput.colors.text.default,
|
|
52
52
|
alignSelf: 'stretch',
|
|
53
53
|
flexGrow: 1,
|
|
54
54
|
flexShrink: 1,
|
|
@@ -1,10 +1,46 @@
|
|
|
1
1
|
import { TextInput, View, StyleSheet, Animated } from 'react-native';
|
|
2
2
|
import styled from '@emotion/native';
|
|
3
|
+
import type { Theme } from '@emotion/react';
|
|
3
4
|
import Typography from '../Typography';
|
|
4
5
|
|
|
5
6
|
export type State = 'default' | 'filled' | 'disabled' | 'readonly' | 'error';
|
|
6
7
|
type Variant = 'text' | 'textarea';
|
|
7
8
|
|
|
9
|
+
const genBorderWidth = (
|
|
10
|
+
theme: Theme,
|
|
11
|
+
themeState: State,
|
|
12
|
+
themeFocused: boolean
|
|
13
|
+
): number => {
|
|
14
|
+
if (themeState === 'readonly') return 0;
|
|
15
|
+
return themeFocused
|
|
16
|
+
? theme.__hd__.textInput.borderWidths.container.focused
|
|
17
|
+
: theme.__hd__.textInput.borderWidths.container.normal;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const genBorderColor = (
|
|
21
|
+
theme: Theme,
|
|
22
|
+
themeState: State,
|
|
23
|
+
themeFocused: boolean,
|
|
24
|
+
themeFilled: boolean
|
|
25
|
+
): string => {
|
|
26
|
+
if (themeState === 'error' && !themeFilled) {
|
|
27
|
+
return theme.__hd__.textInput.colors.borders.default;
|
|
28
|
+
}
|
|
29
|
+
if (themeState === 'error' && themeFilled) {
|
|
30
|
+
return theme.__hd__.textInput.colors.borders.error;
|
|
31
|
+
}
|
|
32
|
+
if (themeFocused) {
|
|
33
|
+
return (
|
|
34
|
+
theme.__hd__.textInput.colors.borders.focused ??
|
|
35
|
+
theme.__hd__.textInput.colors.borders.default
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
return (
|
|
39
|
+
theme.__hd__.textInput.colors.borders[themeState] ??
|
|
40
|
+
theme.__hd__.textInput.colors.borders.default
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
8
44
|
const StyledContainer = styled(View)(({ theme }) => ({
|
|
9
45
|
width: '100%',
|
|
10
46
|
marginTop: theme.__hd__.textInput.space.containerMarginTop,
|
|
@@ -12,17 +48,14 @@ const StyledContainer = styled(View)(({ theme }) => ({
|
|
|
12
48
|
|
|
13
49
|
const StyledLabelContainerInsideTextInput = styled(Animated.View)<{
|
|
14
50
|
themeVariant: Variant;
|
|
15
|
-
|
|
16
|
-
}>(({ themeVariant, themeHasPrefix, theme }) => ({
|
|
51
|
+
}>(({ themeVariant, theme }) => ({
|
|
17
52
|
flexDirection: 'row',
|
|
18
53
|
alignItems: themeVariant === 'text' ? 'center' : 'flex-start',
|
|
19
54
|
position: 'absolute',
|
|
20
55
|
zIndex: 1,
|
|
21
|
-
left:
|
|
22
|
-
? theme.space.xxlarge
|
|
23
|
-
: theme.space.medium + theme.space.small,
|
|
56
|
+
left: 0,
|
|
24
57
|
right: theme.space.medium,
|
|
25
|
-
top:
|
|
58
|
+
top: 0,
|
|
26
59
|
}));
|
|
27
60
|
|
|
28
61
|
const StyledLabelInsideTextInput = styled(View)<{
|
|
@@ -52,7 +85,6 @@ const StyledErrorContainer = styled(View)(({ theme }) => ({
|
|
|
52
85
|
|
|
53
86
|
const StyledError = styled(Typography.Caption)(({ theme }) => ({
|
|
54
87
|
color: theme.__hd__.textInput.colors.error,
|
|
55
|
-
marginLeft: theme.__hd__.textInput.space.errorMarginLeft,
|
|
56
88
|
}));
|
|
57
89
|
|
|
58
90
|
const StyledMaxLengthMessage = styled(Typography.Caption)<{
|
|
@@ -71,7 +103,7 @@ const StyledTextInput = styled(TextInput)<{ themeVariant: Variant }>(
|
|
|
71
103
|
fontSize: theme.__hd__.textInput.fontSizes.text,
|
|
72
104
|
alignSelf: 'stretch',
|
|
73
105
|
flexGrow: 2,
|
|
74
|
-
marginHorizontal:
|
|
106
|
+
marginHorizontal: 0,
|
|
75
107
|
paddingVertical: 0,
|
|
76
108
|
maxHeight: theme.__hd__.textInput.sizes.textInputMaxHeight,
|
|
77
109
|
height:
|
|
@@ -85,37 +117,54 @@ const StyledTextInput = styled(TextInput)<{ themeVariant: Variant }>(
|
|
|
85
117
|
const StyledBorderBackDrop = styled(View)<{
|
|
86
118
|
themeState: State;
|
|
87
119
|
themeFocused: boolean;
|
|
88
|
-
|
|
120
|
+
themeFilled: boolean;
|
|
121
|
+
}>(({ theme, themeFocused, themeState, themeFilled }) => ({
|
|
89
122
|
...StyleSheet.absoluteFillObject,
|
|
90
|
-
borderWidth: themeFocused
|
|
91
|
-
? theme.__hd__.textInput.borderWidths.container.focused
|
|
92
|
-
: theme.__hd__.textInput.borderWidths.container.normal,
|
|
123
|
+
borderWidth: genBorderWidth(theme, themeState, themeFocused),
|
|
93
124
|
borderRadius: theme.__hd__.textInput.radii.container,
|
|
94
|
-
borderColor:
|
|
95
|
-
theme.__hd__.textInput.colors.borders[themeState] ??
|
|
96
|
-
theme.__hd__.textInput.colors.borders.default,
|
|
125
|
+
borderColor: genBorderColor(theme, themeState, themeFocused, themeFilled),
|
|
97
126
|
}));
|
|
98
127
|
|
|
99
|
-
const StyledTextInputContainer = styled(View)
|
|
128
|
+
const StyledTextInputContainer = styled(View)<{
|
|
129
|
+
themeVariant: Variant;
|
|
130
|
+
themeState: State;
|
|
131
|
+
}>(({ theme, themeVariant, themeState }) => ({
|
|
100
132
|
flexDirection: 'row',
|
|
101
133
|
alignItems: 'center',
|
|
102
|
-
|
|
103
|
-
|
|
134
|
+
paddingHorizontal: theme.__hd__.textInput.space.containerHorizontalPadding,
|
|
135
|
+
paddingVertical: theme.__hd__.textInput.space.containerVerticalPadding,
|
|
104
136
|
borderRadius: theme.__hd__.textInput.radii.container,
|
|
137
|
+
...(themeVariant === 'text' && {
|
|
138
|
+
minHeight: theme.__hd__.textInput.sizes.containerMinHeight,
|
|
139
|
+
}),
|
|
140
|
+
...(themeState === 'disabled' && { opacity: 0.5 }),
|
|
141
|
+
gap: theme.space.smallMedium,
|
|
105
142
|
}));
|
|
106
143
|
|
|
107
|
-
|
|
144
|
+
// Outer wrapper that owns flex-grow/shrink and provides the positioning context
|
|
145
|
+
// for StyledLabelContainerInsideTextInput (position: absolute).
|
|
146
|
+
const StyledInputContentContainer = styled(View)<{ themeHasLabel: boolean }>(
|
|
147
|
+
({ themeHasLabel }) => ({
|
|
148
|
+
flexGrow: 2,
|
|
149
|
+
flexShrink: 1,
|
|
150
|
+
alignSelf: 'stretch',
|
|
151
|
+
justifyContent: themeHasLabel ? 'flex-start' : 'center',
|
|
152
|
+
})
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
const StyledTextInputAndLabelContainer = styled(View)<{
|
|
156
|
+
themeHasLabel: boolean;
|
|
157
|
+
}>(({ theme, themeHasLabel }) => ({
|
|
108
158
|
flexDirection: 'row',
|
|
109
159
|
alignItems: 'center',
|
|
110
160
|
alignSelf: 'stretch',
|
|
111
|
-
|
|
112
|
-
|
|
161
|
+
...(themeHasLabel && {
|
|
162
|
+
paddingTop: theme.__hd__.textInput.space.inputAndLabelContainerPaddingTop,
|
|
163
|
+
}),
|
|
113
164
|
}));
|
|
114
165
|
|
|
115
166
|
const StyledErrorAndHelpTextContainer = styled(View)(({ theme }) => ({
|
|
116
|
-
|
|
117
|
-
theme.__hd__.textInput.space.errorAndHelpTextContainerHorizontalPadding,
|
|
118
|
-
minHeight: theme.__hd__.textInput.sizes.errorAndHelpTextContainerHeight,
|
|
167
|
+
minHeight: theme.__hd__.textInput.sizes.errorAndHelpTextContainerMinHeight,
|
|
119
168
|
paddingTop: theme.__hd__.textInput.space.errorAndHelpTextContainerPaddingTop,
|
|
120
169
|
}));
|
|
121
170
|
|
|
@@ -136,6 +185,7 @@ export {
|
|
|
136
185
|
StyledContainer,
|
|
137
186
|
StyledErrorContainer,
|
|
138
187
|
StyledHelperText,
|
|
188
|
+
StyledInputContentContainer,
|
|
139
189
|
StyledTextInputAndLabelContainer,
|
|
140
190
|
StyledLabelContainerInsideTextInput,
|
|
141
191
|
StyledErrorAndHelpTextContainer,
|