@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.
Files changed (44) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/lib/index.js +19933 -735
  3. package/package.json +3 -2
  4. package/src/components/DatePicker/__tests__/__snapshots__/index.spec.tsx.snap +3 -3
  5. package/src/components/FormGroup/__tests__/__snapshots__/index.spec.tsx.snap +903 -0
  6. package/src/components/FormGroup/__tests__/index.spec.tsx +306 -0
  7. package/src/components/FormGroup/__tests__/utils.spec.ts +73 -0
  8. package/src/components/FormGroup/index.tsx +106 -0
  9. package/src/components/FormGroup/utils.ts +67 -0
  10. package/src/components/RichTextEditor/EditorEvent.ts +7 -0
  11. package/src/components/RichTextEditor/EditorToolbar.tsx +216 -0
  12. package/src/components/RichTextEditor/MentionList.tsx +99 -0
  13. package/src/components/RichTextEditor/RichTextEditor.tsx +88 -0
  14. package/src/components/RichTextEditor/RichTextEditorInput.tsx +292 -0
  15. package/src/components/RichTextEditor/StyledRichTextEditor.tsx +15 -0
  16. package/src/components/RichTextEditor/StyledToolbar.ts +32 -0
  17. package/src/components/RichTextEditor/__mocks__/hero-editor.js +3 -0
  18. package/src/components/RichTextEditor/__mocks__/heroEditorApp.ts +2 -0
  19. package/src/components/RichTextEditor/__tests__/EditorToolbar.spec.tsx +144 -0
  20. package/src/components/RichTextEditor/__tests__/MentionList.spec.tsx +105 -0
  21. package/src/components/RichTextEditor/__tests__/RichTextEditorInput.spec.tsx +136 -0
  22. package/src/components/RichTextEditor/__tests__/__snapshots__/EditorToolbar.spec.tsx.snap +414 -0
  23. package/src/components/RichTextEditor/__tests__/__snapshots__/MentionList.spec.tsx.snap +13 -0
  24. package/src/components/RichTextEditor/constants.ts +9 -0
  25. package/src/{hero-editor.d.ts → components/RichTextEditor/hero-editor.d.ts} +6 -0
  26. package/src/components/RichTextEditor/heroEditorApp.ts +3 -0
  27. package/src/components/RichTextEditor/index.tsx +20 -0
  28. package/src/components/RichTextEditor/types.ts +87 -0
  29. package/src/components/RichTextEditor/utils/events.ts +31 -0
  30. package/src/components/RichTextEditor/utils/rnWebView.tsx +30 -0
  31. package/src/components/Select/__tests__/__snapshots__/index.spec.tsx.snap +24 -2
  32. package/src/components/Select/index.tsx +11 -10
  33. package/src/components/TextInput/Group/__tests__/__snapshots__/index.spec.tsx.snap +3 -3
  34. package/src/components/TextInput/Group/index.tsx +6 -1
  35. package/src/components/TextInput/InputComponent.tsx +59 -18
  36. package/src/components/TextInput/InputRow.tsx +13 -7
  37. package/src/components/TextInput/StyledTextInput.tsx +3 -3
  38. package/src/components/TextInput/__tests__/__snapshots__/index.spec.tsx.snap +17 -17
  39. package/src/components/TextInput/index.tsx +22 -13
  40. package/src/components/TextInput/types.ts +30 -5
  41. package/src/index.ts +3 -1
  42. package/src/utils/hooks.ts +10 -0
  43. package/stats/1.5.0/rn-work-uikit-stats.html +4844 -0
  44. 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
- function Select<V, T extends SelectOptionType<V> = SelectOptionType<V>>(
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
- Select.Multi = function <
17
- V,
18
- T extends SelectOptionType<V> = SelectOptionType<V>
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
- enableGroupStyle: true,
94
+ groupStyleEnabled: true,
90
95
  });
91
96
  }),
92
97
  [childrenArray, theme]
@@ -1,9 +1,52 @@
1
- import React from 'react';
2
- import { TextInput as RNTextInput } from 'react-native';
3
- import type { TextInputProps as NativeTextInputProps } from 'react-native';
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 { TextInputVariant } from './types';
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?: (inputProps: NativeTextInputProps) => React.ReactNode;
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<RNTextInput, InputComponentProps>(
85
+ const InputComponent = React.forwardRef<TextInputRef, InputComponentProps>(
40
86
  ({ variant, nativeInputProps, renderInputValue }, ref) => {
41
- const theme = useTheme();
42
-
43
- return renderInputValue ? (
44
- // Custom input renderer provided
45
- <>{renderInputValue(nativeInputProps)}</>
46
- ) : (
47
- // Default styled input with theme and variant support
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 { TextInput as RNTextInput, View } from 'react-native';
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 { TextInputVariant } from './types';
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?: (inputProps: NativeTextInputProps) => React.ReactNode;
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<RNTextInput, InputRowProps>(
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: NativeSyntheticEvent<TextInputFocusEventData>) => {
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: NativeSyntheticEvent<TextInputFocusEventData>) => {
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
- themeUseGroupStyleEnabled: boolean;
30
- }>(({ theme, themeFocused, themeHasError, themeUseGroupStyleEnabled }) => ({
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
- ...(themeUseGroupStyleEnabled && {
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, TextInput as RNTextInput } from 'react-native';
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
- enableGroupStyle = false,
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<RNTextInput | null>(null);
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: NativeSyntheticEvent<TextInputFocusEventData>) => {
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: NativeSyntheticEvent<TextInputFocusEventData>) => {
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
- // Create container style without background color
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
- themeUseGroupStyleEnabled={enableGroupStyle}
295
+ themeGroupStyleEnabled={groupStyleEnabled}
287
296
  testID={testID}
288
297
  >
289
298
  {/*
@@ -1,9 +1,11 @@
1
1
  import type {
2
- TextInputProps as NativeTextInputProps,
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 interface TextInputProps extends NativeTextInputProps {
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?: (inputProps: NativeTextInputProps) => React.ReactNode;
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
- enableGroupStyle?: boolean;
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 };
@@ -0,0 +1,10 @@
1
+ import { useEffect } from 'react';
2
+
3
+ export const useDeprecation = (message: string, cond = true) => {
4
+ useEffect(() => {
5
+ // eslint-disable-next-line no-console
6
+ if (cond) {
7
+ console.warn(message);
8
+ }
9
+ }, [message, cond]);
10
+ };