@hero-design/rn-work-uikit 1.3.1 → 1.5.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 +28 -0
- package/lib/index.js +19933 -735
- package/package.json +3 -2
- package/src/components/DatePicker/__tests__/__snapshots__/index.spec.tsx.snap +3 -3
- package/src/components/FormGroup/__tests__/__snapshots__/index.spec.tsx.snap +903 -0
- package/src/components/FormGroup/__tests__/index.spec.tsx +306 -0
- package/src/components/FormGroup/__tests__/utils.spec.ts +73 -0
- package/src/components/FormGroup/index.tsx +106 -0
- package/src/components/FormGroup/utils.ts +67 -0
- package/src/components/RichTextEditor/EditorEvent.ts +7 -0
- package/src/components/RichTextEditor/EditorToolbar.tsx +216 -0
- package/src/components/RichTextEditor/MentionList.tsx +99 -0
- package/src/components/RichTextEditor/RichTextEditor.tsx +88 -0
- package/src/components/RichTextEditor/RichTextEditorInput.tsx +292 -0
- package/src/components/RichTextEditor/StyledRichTextEditor.tsx +15 -0
- package/src/components/RichTextEditor/StyledToolbar.ts +32 -0
- package/src/components/RichTextEditor/__mocks__/hero-editor.js +3 -0
- package/src/components/RichTextEditor/__mocks__/heroEditorApp.ts +2 -0
- package/src/components/RichTextEditor/__tests__/EditorToolbar.spec.tsx +144 -0
- package/src/components/RichTextEditor/__tests__/MentionList.spec.tsx +105 -0
- package/src/components/RichTextEditor/__tests__/RichTextEditorInput.spec.tsx +136 -0
- package/src/components/RichTextEditor/__tests__/__snapshots__/EditorToolbar.spec.tsx.snap +414 -0
- package/src/components/RichTextEditor/__tests__/__snapshots__/MentionList.spec.tsx.snap +13 -0
- package/src/components/RichTextEditor/constants.ts +9 -0
- package/src/{hero-editor.d.ts → components/RichTextEditor/hero-editor.d.ts} +6 -0
- package/src/components/RichTextEditor/heroEditorApp.ts +3 -0
- package/src/components/RichTextEditor/index.tsx +20 -0
- package/src/components/RichTextEditor/types.ts +87 -0
- package/src/components/RichTextEditor/utils/events.ts +31 -0
- package/src/components/RichTextEditor/utils/rnWebView.tsx +30 -0
- package/src/components/Select/__tests__/__snapshots__/index.spec.tsx.snap +24 -2
- package/src/components/Select/index.tsx +11 -10
- package/src/components/TextInput/Group/__tests__/__snapshots__/index.spec.tsx.snap +3 -3
- package/src/components/TextInput/Group/index.tsx +6 -1
- package/src/components/TextInput/InputComponent.tsx +59 -18
- package/src/components/TextInput/InputRow.tsx +13 -7
- package/src/components/TextInput/StyledTextInput.tsx +3 -3
- package/src/components/TextInput/__tests__/__snapshots__/index.spec.tsx.snap +17 -17
- package/src/components/TextInput/index.tsx +22 -13
- package/src/components/TextInput/types.ts +30 -5
- package/src/index.ts +3 -1
- package/src/utils/hooks.ts +10 -0
- package/stats/1.5.0/rn-work-uikit-stats.html +4844 -0
- package/stats/1.3.1/rn-work-uikit-stats.html +0 -4844
|
@@ -1,23 +1,24 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import {
|
|
3
2
|
Select as InternalSelect,
|
|
4
3
|
MultiSelectProps,
|
|
5
|
-
SingleSelectProps,
|
|
6
4
|
SelectOptionType,
|
|
5
|
+
SingleSelectProps,
|
|
7
6
|
} from '@hero-design/rn';
|
|
7
|
+
import React from 'react';
|
|
8
8
|
import TextInput from '../TextInput';
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
const Select = <V, T extends SelectOptionType<V> = SelectOptionType<V>>(
|
|
11
11
|
props: SingleSelectProps<V, T>
|
|
12
|
-
) {
|
|
12
|
+
) => {
|
|
13
13
|
return <InternalSelect {...props} TextInputComponent={TextInput} />;
|
|
14
|
-
}
|
|
14
|
+
};
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
V,
|
|
18
|
-
|
|
19
|
-
>(props: MultiSelectProps<V, T>) {
|
|
16
|
+
const MultiSelect = <V, T extends SelectOptionType<V> = SelectOptionType<V>>(
|
|
17
|
+
props: MultiSelectProps<V, T>
|
|
18
|
+
) => {
|
|
20
19
|
return <InternalSelect.Multi {...props} TextInputComponent={TextInput} />;
|
|
21
20
|
};
|
|
22
21
|
|
|
23
|
-
export default Select
|
|
22
|
+
export default Object.assign(Select, {
|
|
23
|
+
Multi: MultiSelect,
|
|
24
|
+
});
|
|
@@ -37,8 +37,8 @@ exports[`TextInputGroup should render: xxx 1`] = `
|
|
|
37
37
|
]
|
|
38
38
|
}
|
|
39
39
|
themeFocused={false}
|
|
40
|
+
themeGroupStyleEnabled={true}
|
|
40
41
|
themeHasError={false}
|
|
41
|
-
themeUseGroupStyleEnabled={true}
|
|
42
42
|
>
|
|
43
43
|
<View
|
|
44
44
|
pointerEvents="none"
|
|
@@ -290,8 +290,8 @@ exports[`TextInputGroup should render: xxx 1`] = `
|
|
|
290
290
|
}
|
|
291
291
|
testID="text-input-2"
|
|
292
292
|
themeFocused={false}
|
|
293
|
+
themeGroupStyleEnabled={true}
|
|
293
294
|
themeHasError={true}
|
|
294
|
-
themeUseGroupStyleEnabled={true}
|
|
295
295
|
>
|
|
296
296
|
<View
|
|
297
297
|
pointerEvents="none"
|
|
@@ -650,8 +650,8 @@ exports[`TextInputGroup should render: xxx 1`] = `
|
|
|
650
650
|
]
|
|
651
651
|
}
|
|
652
652
|
themeFocused={false}
|
|
653
|
+
themeGroupStyleEnabled={true}
|
|
653
654
|
themeHasError={false}
|
|
654
|
-
themeUseGroupStyleEnabled={true}
|
|
655
655
|
>
|
|
656
656
|
<View
|
|
657
657
|
pointerEvents="none"
|
|
@@ -2,6 +2,7 @@ import React, { ReactNode, useMemo } from 'react';
|
|
|
2
2
|
import { StyleProp, StyleSheet, ViewProps, ViewStyle } from 'react-native';
|
|
3
3
|
import { Box, useTheme } from '@hero-design/rn';
|
|
4
4
|
import { generateBorderStyle, generateMarginStyle } from './utils';
|
|
5
|
+
import { useDeprecation } from '../../../utils/hooks';
|
|
5
6
|
|
|
6
7
|
export interface TextInputGroupProps extends ViewProps {
|
|
7
8
|
/**
|
|
@@ -36,6 +37,10 @@ const TextInputGroup = ({
|
|
|
36
37
|
testID,
|
|
37
38
|
...props
|
|
38
39
|
}: TextInputGroupProps) => {
|
|
40
|
+
useDeprecation(
|
|
41
|
+
'TextInput.Group is deprecated. Please use FormGroup instead.',
|
|
42
|
+
true
|
|
43
|
+
);
|
|
39
44
|
const theme = useTheme();
|
|
40
45
|
const childrenArray = React.Children.toArray(children).filter(
|
|
41
46
|
React.isValidElement
|
|
@@ -86,7 +91,7 @@ const TextInputGroup = ({
|
|
|
86
91
|
style: mergedStyle,
|
|
87
92
|
textStyle: mergedTextStyle,
|
|
88
93
|
// Internal text input prop to allow for different styling
|
|
89
|
-
|
|
94
|
+
groupStyleEnabled: true,
|
|
90
95
|
});
|
|
91
96
|
}),
|
|
92
97
|
[childrenArray, theme]
|
|
@@ -1,9 +1,52 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
import React, { useImperativeHandle, useRef } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
TextInput as RNTextInput,
|
|
4
|
+
TextInputProps as RNTextInputProps,
|
|
5
|
+
} from 'react-native';
|
|
4
6
|
import { StyledTextInput } from './StyledTextInput';
|
|
5
7
|
import { useTheme } from '../../theme';
|
|
6
|
-
import type {
|
|
8
|
+
import type {
|
|
9
|
+
NativeTextInputProps,
|
|
10
|
+
TextInputRef,
|
|
11
|
+
TextInputVariant,
|
|
12
|
+
} from './types';
|
|
13
|
+
|
|
14
|
+
interface DefaultTextInputProps {
|
|
15
|
+
variant: TextInputVariant;
|
|
16
|
+
/** Native TextInput props */
|
|
17
|
+
nativeInputProps: NativeTextInputProps;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const DefaultTextInput = React.forwardRef<TextInputRef, DefaultTextInputProps>(
|
|
21
|
+
({ variant, nativeInputProps }, ref) => {
|
|
22
|
+
const theme = useTheme();
|
|
23
|
+
const inputRef = useRef<RNTextInput>(null);
|
|
24
|
+
useImperativeHandle(
|
|
25
|
+
ref,
|
|
26
|
+
() => ({
|
|
27
|
+
focus: () => inputRef.current?.focus(),
|
|
28
|
+
blur: () => inputRef.current?.blur(),
|
|
29
|
+
clear: () => inputRef.current?.clear(),
|
|
30
|
+
isFocused: () => inputRef.current?.isFocused() ?? false,
|
|
31
|
+
setNativeProps: (props: RNTextInputProps) => {
|
|
32
|
+
inputRef.current?.setNativeProps(props);
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
[]
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// Default styled input with theme and variant support
|
|
39
|
+
return (
|
|
40
|
+
<StyledTextInput
|
|
41
|
+
{...nativeInputProps}
|
|
42
|
+
themeVariant={variant}
|
|
43
|
+
multiline={variant === 'textarea' || nativeInputProps.multiline}
|
|
44
|
+
ref={inputRef}
|
|
45
|
+
placeholderTextColor={theme.__hd__.textInput.colors.placeholder}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
);
|
|
7
50
|
|
|
8
51
|
export interface InputComponentProps {
|
|
9
52
|
/** Input type ('text' or 'textarea') */
|
|
@@ -11,7 +54,10 @@ export interface InputComponentProps {
|
|
|
11
54
|
/** All props passed to the underlying TextInput */
|
|
12
55
|
nativeInputProps: NativeTextInputProps;
|
|
13
56
|
/** Optional custom input renderer function */
|
|
14
|
-
renderInputValue?: (
|
|
57
|
+
renderInputValue?: (
|
|
58
|
+
inputProps: NativeTextInputProps,
|
|
59
|
+
ref?: React.ForwardedRef<TextInputRef>
|
|
60
|
+
) => React.ReactNode;
|
|
15
61
|
}
|
|
16
62
|
|
|
17
63
|
/**
|
|
@@ -36,21 +82,16 @@ export interface InputComponentProps {
|
|
|
36
82
|
*
|
|
37
83
|
* @param props - The component props (see InputComponentProps interface for details)
|
|
38
84
|
*/
|
|
39
|
-
const InputComponent = React.forwardRef<
|
|
85
|
+
const InputComponent = React.forwardRef<TextInputRef, InputComponentProps>(
|
|
40
86
|
({ variant, nativeInputProps, renderInputValue }, ref) => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
<StyledTextInput
|
|
49
|
-
{...nativeInputProps}
|
|
50
|
-
themeVariant={variant}
|
|
51
|
-
multiline={variant === 'textarea' || nativeInputProps.multiline}
|
|
87
|
+
if (renderInputValue) {
|
|
88
|
+
return <>{renderInputValue({ ...nativeInputProps }, ref)}</>;
|
|
89
|
+
}
|
|
90
|
+
return (
|
|
91
|
+
<DefaultTextInput
|
|
92
|
+
variant={variant}
|
|
93
|
+
nativeInputProps={nativeInputProps}
|
|
52
94
|
ref={ref}
|
|
53
|
-
placeholderTextColor={theme.__hd__.textInput.colors.placeholder}
|
|
54
95
|
/>
|
|
55
96
|
);
|
|
56
97
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import React, { useCallback, useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { View } from 'react-native';
|
|
3
3
|
import type {
|
|
4
4
|
NativeSyntheticEvent,
|
|
5
|
-
TextInputProps as NativeTextInputProps,
|
|
6
5
|
TextInputFocusEventData,
|
|
7
6
|
} from 'react-native';
|
|
8
7
|
import { IconName } from '@hero-design/rn';
|
|
@@ -10,7 +9,11 @@ import { StyledInputRow } from './StyledTextInput';
|
|
|
10
9
|
import PrefixComponent from './PrefixComponent';
|
|
11
10
|
import InputComponent from './InputComponent';
|
|
12
11
|
import type { State } from './StyledTextInput';
|
|
13
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
NativeTextInputProps,
|
|
14
|
+
TextInputRef,
|
|
15
|
+
TextInputVariant,
|
|
16
|
+
} from './types';
|
|
14
17
|
|
|
15
18
|
interface InputRowProps {
|
|
16
19
|
/** Current state of the input (focused, error, disabled, etc.) */
|
|
@@ -22,7 +25,10 @@ interface InputRowProps {
|
|
|
22
25
|
/** Native TextInput props passed to the input component */
|
|
23
26
|
nativeInputProps: NativeTextInputProps;
|
|
24
27
|
/** Optional custom render function for input value */
|
|
25
|
-
renderInputValue?: (
|
|
28
|
+
renderInputValue?: (
|
|
29
|
+
inputProps: NativeTextInputProps,
|
|
30
|
+
ref?: React.ForwardedRef<TextInputRef>
|
|
31
|
+
) => React.ReactNode;
|
|
26
32
|
/** Whether the input value is empty */
|
|
27
33
|
isEmptyValue: boolean;
|
|
28
34
|
/** Whether the input should be visible when not focused and empty. Defaults to true. */
|
|
@@ -52,7 +58,7 @@ interface InputRowProps {
|
|
|
52
58
|
* 1. Conditionally visible prefix component (icon or custom element)
|
|
53
59
|
* 2. Conditionally visible input component (TextInput or custom rendered input)
|
|
54
60
|
*/
|
|
55
|
-
const InputRow = React.forwardRef<
|
|
61
|
+
const InputRow = React.forwardRef<TextInputRef, InputRowProps>(
|
|
56
62
|
(
|
|
57
63
|
{
|
|
58
64
|
state,
|
|
@@ -75,7 +81,7 @@ const InputRow = React.forwardRef<RNTextInput, InputRowProps>(
|
|
|
75
81
|
|
|
76
82
|
// Simplified callback functions (removed unnecessary memoization for simple cases)
|
|
77
83
|
const handleFocus = useCallback(
|
|
78
|
-
(event
|
|
84
|
+
(event?: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
79
85
|
setIsFocused(true);
|
|
80
86
|
nativeInputProps.onFocus?.(event);
|
|
81
87
|
},
|
|
@@ -83,7 +89,7 @@ const InputRow = React.forwardRef<RNTextInput, InputRowProps>(
|
|
|
83
89
|
);
|
|
84
90
|
|
|
85
91
|
const handleBlur = useCallback(
|
|
86
|
-
(event
|
|
92
|
+
(event?: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
87
93
|
setIsFocused(false);
|
|
88
94
|
nativeInputProps.onBlur?.(event);
|
|
89
95
|
},
|
|
@@ -26,14 +26,14 @@ const getZIndexByState = ({
|
|
|
26
26
|
const StyledContainer = styled(Pressable)<{
|
|
27
27
|
themeFocused: boolean;
|
|
28
28
|
themeHasError: boolean;
|
|
29
|
-
|
|
30
|
-
}>(({ theme, themeFocused, themeHasError,
|
|
29
|
+
themeGroupStyleEnabled: boolean;
|
|
30
|
+
}>(({ theme, themeFocused, themeHasError, themeGroupStyleEnabled }) => ({
|
|
31
31
|
width: '100%',
|
|
32
32
|
flexDirection: 'row',
|
|
33
33
|
paddingHorizontal: theme.__hd__.textInput.space.containerPadding,
|
|
34
34
|
minHeight: theme.__hd__.textInput.sizes.containerMinHeight,
|
|
35
35
|
marginTop: theme.__hd__.textInput.space.containerMarginTop,
|
|
36
|
-
...(
|
|
36
|
+
...(themeGroupStyleEnabled && {
|
|
37
37
|
zIndex: getZIndexByState({ themeFocused, themeHasError }),
|
|
38
38
|
}),
|
|
39
39
|
}));
|
|
@@ -24,8 +24,8 @@ exports[`TextInput when user applies custom styling should respect user-provided
|
|
|
24
24
|
]
|
|
25
25
|
}
|
|
26
26
|
themeFocused={false}
|
|
27
|
+
themeGroupStyleEnabled={false}
|
|
27
28
|
themeHasError={false}
|
|
28
|
-
themeUseGroupStyleEnabled={false}
|
|
29
29
|
>
|
|
30
30
|
<View
|
|
31
31
|
pointerEvents="none"
|
|
@@ -380,8 +380,8 @@ exports[`TextInput when user chooses textarea variant should provide multiline t
|
|
|
380
380
|
]
|
|
381
381
|
}
|
|
382
382
|
themeFocused={false}
|
|
383
|
+
themeGroupStyleEnabled={false}
|
|
383
384
|
themeHasError={false}
|
|
384
|
-
themeUseGroupStyleEnabled={false}
|
|
385
385
|
>
|
|
386
386
|
<View
|
|
387
387
|
pointerEvents="none"
|
|
@@ -659,8 +659,8 @@ exports[`TextInput when user encounters a disabled field should display content
|
|
|
659
659
|
]
|
|
660
660
|
}
|
|
661
661
|
themeFocused={false}
|
|
662
|
+
themeGroupStyleEnabled={false}
|
|
662
663
|
themeHasError={false}
|
|
663
|
-
themeUseGroupStyleEnabled={false}
|
|
664
664
|
>
|
|
665
665
|
<View
|
|
666
666
|
pointerEvents="none"
|
|
@@ -937,8 +937,8 @@ exports[`TextInput when user encounters a read-only field should display content
|
|
|
937
937
|
]
|
|
938
938
|
}
|
|
939
939
|
themeFocused={false}
|
|
940
|
+
themeGroupStyleEnabled={false}
|
|
940
941
|
themeHasError={false}
|
|
941
|
-
themeUseGroupStyleEnabled={false}
|
|
942
942
|
>
|
|
943
943
|
<View
|
|
944
944
|
pointerEvents="none"
|
|
@@ -1299,8 +1299,8 @@ exports[`TextInput when user has entered text should show the input content and
|
|
|
1299
1299
|
]
|
|
1300
1300
|
}
|
|
1301
1301
|
themeFocused={false}
|
|
1302
|
+
themeGroupStyleEnabled={false}
|
|
1302
1303
|
themeHasError={false}
|
|
1303
|
-
themeUseGroupStyleEnabled={false}
|
|
1304
1304
|
>
|
|
1305
1305
|
<View
|
|
1306
1306
|
pointerEvents="none"
|
|
@@ -1661,8 +1661,8 @@ exports[`TextInput when user interacts with placeholder text starting from empty
|
|
|
1661
1661
|
]
|
|
1662
1662
|
}
|
|
1663
1663
|
themeFocused={false}
|
|
1664
|
+
themeGroupStyleEnabled={false}
|
|
1664
1665
|
themeHasError={false}
|
|
1665
|
-
themeUseGroupStyleEnabled={false}
|
|
1666
1666
|
>
|
|
1667
1667
|
<View
|
|
1668
1668
|
pointerEvents="none"
|
|
@@ -1980,8 +1980,8 @@ exports[`TextInput when user needs programmatic control should provide ref metho
|
|
|
1980
1980
|
]
|
|
1981
1981
|
}
|
|
1982
1982
|
themeFocused={false}
|
|
1983
|
+
themeGroupStyleEnabled={false}
|
|
1983
1984
|
themeHasError={false}
|
|
1984
|
-
themeUseGroupStyleEnabled={false}
|
|
1985
1985
|
>
|
|
1986
1986
|
<View
|
|
1987
1987
|
pointerEvents="none"
|
|
@@ -2258,8 +2258,8 @@ exports[`TextInput when user provides default values starting with pre-filled co
|
|
|
2258
2258
|
]
|
|
2259
2259
|
}
|
|
2260
2260
|
themeFocused={false}
|
|
2261
|
+
themeGroupStyleEnabled={false}
|
|
2261
2262
|
themeHasError={false}
|
|
2262
|
-
themeUseGroupStyleEnabled={false}
|
|
2263
2263
|
>
|
|
2264
2264
|
<View
|
|
2265
2265
|
pointerEvents="none"
|
|
@@ -2613,8 +2613,8 @@ exports[`TextInput when user provides default values when both default and contr
|
|
|
2613
2613
|
]
|
|
2614
2614
|
}
|
|
2615
2615
|
themeFocused={false}
|
|
2616
|
+
themeGroupStyleEnabled={false}
|
|
2616
2617
|
themeHasError={false}
|
|
2617
|
-
themeUseGroupStyleEnabled={false}
|
|
2618
2618
|
>
|
|
2619
2619
|
<View
|
|
2620
2620
|
pointerEvents="none"
|
|
@@ -2969,8 +2969,8 @@ exports[`TextInput when user sees a loading state should show loading indicator
|
|
|
2969
2969
|
]
|
|
2970
2970
|
}
|
|
2971
2971
|
themeFocused={false}
|
|
2972
|
+
themeGroupStyleEnabled={false}
|
|
2972
2973
|
themeHasError={false}
|
|
2973
|
-
themeUseGroupStyleEnabled={false}
|
|
2974
2974
|
>
|
|
2975
2975
|
<View
|
|
2976
2976
|
pointerEvents="none"
|
|
@@ -3350,8 +3350,8 @@ exports[`TextInput when user sees a required field should indicate the field is
|
|
|
3350
3350
|
]
|
|
3351
3351
|
}
|
|
3352
3352
|
themeFocused={false}
|
|
3353
|
+
themeGroupStyleEnabled={false}
|
|
3353
3354
|
themeHasError={false}
|
|
3354
|
-
themeUseGroupStyleEnabled={false}
|
|
3355
3355
|
>
|
|
3356
3356
|
<View
|
|
3357
3357
|
pointerEvents="none"
|
|
@@ -3682,8 +3682,8 @@ exports[`TextInput when user sees a textarea with character count should display
|
|
|
3682
3682
|
]
|
|
3683
3683
|
}
|
|
3684
3684
|
themeFocused={false}
|
|
3685
|
+
themeGroupStyleEnabled={false}
|
|
3685
3686
|
themeHasError={false}
|
|
3686
|
-
themeUseGroupStyleEnabled={false}
|
|
3687
3687
|
>
|
|
3688
3688
|
<View
|
|
3689
3689
|
pointerEvents="none"
|
|
@@ -4081,8 +4081,8 @@ exports[`TextInput when user sees a textarea with character count should hide ch
|
|
|
4081
4081
|
]
|
|
4082
4082
|
}
|
|
4083
4083
|
themeFocused={false}
|
|
4084
|
+
themeGroupStyleEnabled={false}
|
|
4084
4085
|
themeHasError={false}
|
|
4085
|
-
themeUseGroupStyleEnabled={false}
|
|
4086
4086
|
>
|
|
4087
4087
|
<View
|
|
4088
4088
|
pointerEvents="none"
|
|
@@ -4447,8 +4447,8 @@ exports[`TextInput when user sees an empty input field should display label and
|
|
|
4447
4447
|
]
|
|
4448
4448
|
}
|
|
4449
4449
|
themeFocused={false}
|
|
4450
|
+
themeGroupStyleEnabled={false}
|
|
4450
4451
|
themeHasError={false}
|
|
4451
|
-
themeUseGroupStyleEnabled={false}
|
|
4452
4452
|
>
|
|
4453
4453
|
<View
|
|
4454
4454
|
pointerEvents="none"
|
|
@@ -4808,8 +4808,8 @@ exports[`TextInput when user sees an error state should display error message to
|
|
|
4808
4808
|
]
|
|
4809
4809
|
}
|
|
4810
4810
|
themeFocused={false}
|
|
4811
|
+
themeGroupStyleEnabled={false}
|
|
4811
4812
|
themeHasError={true}
|
|
4812
|
-
themeUseGroupStyleEnabled={false}
|
|
4813
4813
|
>
|
|
4814
4814
|
<View
|
|
4815
4815
|
pointerEvents="none"
|
|
@@ -5185,8 +5185,8 @@ exports[`TextInput when user sees helper text should display guidance text to as
|
|
|
5185
5185
|
]
|
|
5186
5186
|
}
|
|
5187
5187
|
themeFocused={false}
|
|
5188
|
+
themeGroupStyleEnabled={false}
|
|
5188
5189
|
themeHasError={false}
|
|
5189
|
-
themeUseGroupStyleEnabled={false}
|
|
5190
5190
|
>
|
|
5191
5191
|
<View
|
|
5192
5192
|
pointerEvents="none"
|
|
@@ -5504,8 +5504,8 @@ exports[`TextInput when user sees input with custom prefix and suffix elements s
|
|
|
5504
5504
|
]
|
|
5505
5505
|
}
|
|
5506
5506
|
themeFocused={false}
|
|
5507
|
+
themeGroupStyleEnabled={false}
|
|
5507
5508
|
themeHasError={false}
|
|
5508
|
-
themeUseGroupStyleEnabled={false}
|
|
5509
5509
|
>
|
|
5510
5510
|
<View
|
|
5511
5511
|
pointerEvents="none"
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React, { forwardRef, useCallback } from 'react';
|
|
2
|
-
import { StyleSheet
|
|
2
|
+
import { StyleSheet } from 'react-native';
|
|
3
3
|
import type {
|
|
4
|
-
TextInputProps as NativeTextInputProps,
|
|
5
4
|
StyleProp,
|
|
6
5
|
ViewStyle,
|
|
7
6
|
NativeSyntheticEvent,
|
|
8
7
|
TextInputFocusEventData,
|
|
8
|
+
ColorValue,
|
|
9
9
|
} from 'react-native';
|
|
10
10
|
import {
|
|
11
11
|
StyledInputWrapper,
|
|
@@ -23,8 +23,10 @@ import FloatingLabel from './FloatingLabel';
|
|
|
23
23
|
import InputRow from './InputRow';
|
|
24
24
|
import type {
|
|
25
25
|
InternalTextInputProps,
|
|
26
|
+
NativeTextInputProps,
|
|
26
27
|
TextInputHandles,
|
|
27
28
|
TextInputProps,
|
|
29
|
+
TextInputRef,
|
|
28
30
|
} from './types';
|
|
29
31
|
import Group from './Group';
|
|
30
32
|
|
|
@@ -89,6 +91,17 @@ const extractBorderStyles = (style: StyleProp<ViewStyle>) => {
|
|
|
89
91
|
return borderStyles;
|
|
90
92
|
};
|
|
91
93
|
|
|
94
|
+
// Create container style without background color using a helper function
|
|
95
|
+
const getContainerStyle = (
|
|
96
|
+
style: StyleProp<ViewStyle>,
|
|
97
|
+
customBackgroundColor?: ColorValue
|
|
98
|
+
) => {
|
|
99
|
+
const flattenedStyle = style ? { ...StyleSheet.flatten(style) } : {};
|
|
100
|
+
if (customBackgroundColor) {
|
|
101
|
+
delete flattenedStyle.backgroundColor;
|
|
102
|
+
}
|
|
103
|
+
return flattenedStyle;
|
|
104
|
+
};
|
|
92
105
|
/**
|
|
93
106
|
* TextInput Layout Structure:
|
|
94
107
|
*
|
|
@@ -149,7 +162,7 @@ export const InternalTextInput = forwardRef<
|
|
|
149
162
|
allowFontScaling = false,
|
|
150
163
|
variant = 'text',
|
|
151
164
|
accessibilityLabel,
|
|
152
|
-
|
|
165
|
+
groupStyleEnabled = false,
|
|
153
166
|
...nativeProps
|
|
154
167
|
}: InternalTextInputProps,
|
|
155
168
|
ref?: React.Ref<TextInputHandles>
|
|
@@ -171,7 +184,7 @@ export const InternalTextInput = forwardRef<
|
|
|
171
184
|
|
|
172
185
|
const theme = useTheme();
|
|
173
186
|
|
|
174
|
-
const innerTextInput = React.useRef<
|
|
187
|
+
const innerTextInput = React.useRef<TextInputRef | null>(null);
|
|
175
188
|
React.useImperativeHandle(
|
|
176
189
|
ref,
|
|
177
190
|
() => ({
|
|
@@ -182,7 +195,7 @@ export const InternalTextInput = forwardRef<
|
|
|
182
195
|
},
|
|
183
196
|
clear: () => innerTextInput.current?.clear(),
|
|
184
197
|
setNativeProps: (args: NativeTextInputProps) =>
|
|
185
|
-
innerTextInput.current?.setNativeProps(args),
|
|
198
|
+
innerTextInput.current?.setNativeProps?.(args),
|
|
186
199
|
isFocused: () => innerTextInput.current?.isFocused() || false,
|
|
187
200
|
blur: () => innerTextInput.current?.blur(),
|
|
188
201
|
}),
|
|
@@ -198,7 +211,7 @@ export const InternalTextInput = forwardRef<
|
|
|
198
211
|
|
|
199
212
|
// Simplified callback functions (removed unnecessary memoization for simple cases)
|
|
200
213
|
const handleFocus = useCallback(
|
|
201
|
-
(event
|
|
214
|
+
(event?: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
202
215
|
setIsFocused(true);
|
|
203
216
|
onFocus?.(event);
|
|
204
217
|
},
|
|
@@ -206,7 +219,7 @@ export const InternalTextInput = forwardRef<
|
|
|
206
219
|
);
|
|
207
220
|
|
|
208
221
|
const handleBlur = useCallback(
|
|
209
|
-
(event
|
|
222
|
+
(event?: NativeSyntheticEvent<TextInputFocusEventData>) => {
|
|
210
223
|
setIsFocused(false);
|
|
211
224
|
onBlur?.(event);
|
|
212
225
|
},
|
|
@@ -265,11 +278,7 @@ export const InternalTextInput = forwardRef<
|
|
|
265
278
|
accessibilityLabel,
|
|
266
279
|
};
|
|
267
280
|
|
|
268
|
-
|
|
269
|
-
const containerStyle = style ? { ...StyleSheet.flatten(style) } : {};
|
|
270
|
-
if (customBackgroundColor) {
|
|
271
|
-
delete containerStyle.backgroundColor;
|
|
272
|
-
}
|
|
281
|
+
const containerStyle = getContainerStyle(style, customBackgroundColor);
|
|
273
282
|
|
|
274
283
|
const isDisabledOrReadonly = state === 'disabled' || state === 'readonly';
|
|
275
284
|
|
|
@@ -283,7 +292,7 @@ export const InternalTextInput = forwardRef<
|
|
|
283
292
|
}}
|
|
284
293
|
themeFocused={isFocused}
|
|
285
294
|
themeHasError={!!error}
|
|
286
|
-
|
|
295
|
+
themeGroupStyleEnabled={groupStyleEnabled}
|
|
287
296
|
testID={testID}
|
|
288
297
|
>
|
|
289
298
|
{/*
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
TextInputProps as
|
|
2
|
+
TextInputProps as RNTextInputProps,
|
|
3
3
|
StyleProp,
|
|
4
4
|
ViewStyle,
|
|
5
5
|
TextStyle,
|
|
6
6
|
TextInput as RNTextInput,
|
|
7
|
+
NativeSyntheticEvent,
|
|
8
|
+
TextInputFocusEventData,
|
|
7
9
|
} from 'react-native';
|
|
8
10
|
import type { IconName } from '@hero-design/rn';
|
|
9
11
|
|
|
@@ -14,7 +16,27 @@ export type TextInputHandles = Pick<
|
|
|
14
16
|
|
|
15
17
|
export type TextInputVariant = 'text' | 'textarea';
|
|
16
18
|
|
|
17
|
-
export
|
|
19
|
+
export type NativeTextInputProps = Omit<
|
|
20
|
+
RNTextInputProps,
|
|
21
|
+
'onFocus' | 'onBlur'
|
|
22
|
+
> & {
|
|
23
|
+
onFocus?: (
|
|
24
|
+
event?: NativeSyntheticEvent<TextInputFocusEventData>
|
|
25
|
+
) => void | undefined;
|
|
26
|
+
onBlur?: (
|
|
27
|
+
event?: NativeSyntheticEvent<TextInputFocusEventData>
|
|
28
|
+
) => void | undefined;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export interface TextInputRef {
|
|
32
|
+
focus: () => void;
|
|
33
|
+
blur: () => void;
|
|
34
|
+
clear: () => void;
|
|
35
|
+
isFocused: () => boolean;
|
|
36
|
+
setNativeProps?: (props: RNTextInputProps) => void;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type TextInputProps = NativeTextInputProps & {
|
|
18
40
|
/**
|
|
19
41
|
* Field label.
|
|
20
42
|
*/
|
|
@@ -83,7 +105,10 @@ export interface TextInputProps extends NativeTextInputProps {
|
|
|
83
105
|
/**
|
|
84
106
|
* Customise input value renderer
|
|
85
107
|
*/
|
|
86
|
-
renderInputValue?: (
|
|
108
|
+
renderInputValue?: (
|
|
109
|
+
inputProps: NativeTextInputProps,
|
|
110
|
+
ref?: React.ForwardedRef<TextInputRef>
|
|
111
|
+
) => React.ReactNode;
|
|
87
112
|
/**
|
|
88
113
|
* Component ref.
|
|
89
114
|
*/
|
|
@@ -92,11 +117,11 @@ export interface TextInputProps extends NativeTextInputProps {
|
|
|
92
117
|
* Component variant.
|
|
93
118
|
*/
|
|
94
119
|
variant?: TextInputVariant;
|
|
95
|
-
}
|
|
120
|
+
};
|
|
96
121
|
|
|
97
122
|
export interface InternalTextInputProps extends TextInputProps {
|
|
98
123
|
/**
|
|
99
124
|
* Whether to use the group style.
|
|
100
125
|
*/
|
|
101
|
-
|
|
126
|
+
groupStyleEnabled?: boolean;
|
|
102
127
|
}
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,8 @@ import TextInput from './components/TextInput';
|
|
|
3
3
|
import Select from './components/Select';
|
|
4
4
|
import DatePicker from './components/DatePicker';
|
|
5
5
|
import TimePicker from './components/TimePicker';
|
|
6
|
+
import FormGroup from './components/FormGroup';
|
|
7
|
+
import RichTextEditor from './components/RichTextEditor';
|
|
6
8
|
|
|
7
9
|
export * from '@hero-design/rn';
|
|
8
10
|
|
|
@@ -17,4 +19,4 @@ export {
|
|
|
17
19
|
} from './theme';
|
|
18
20
|
|
|
19
21
|
export { default as theme } from './theme';
|
|
20
|
-
export { TextInput, Select, DatePicker, TimePicker };
|
|
22
|
+
export { TextInput, Select, DatePicker, TimePicker, FormGroup, RichTextEditor };
|