@hero-design/rn-work-uikit 1.4.0 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hero-design/rn-work-uikit",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "license": "MIT",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
@@ -23,7 +23,7 @@
23
23
  "@emotion/native": "^11.9.3",
24
24
  "@emotion/primitives-core": "11.0.0",
25
25
  "@emotion/react": "^11.9.3",
26
- "@hero-design/rn": "^8.103.5",
26
+ "@hero-design/rn": "^8.103.6",
27
27
  "hero-editor": "^1.15.5"
28
28
  },
29
29
  "peerDependencies": {
@@ -32,8 +32,8 @@ exports[`DatePicker renders correctly (snapshot) 1`] = `
32
32
  ]
33
33
  }
34
34
  themeFocused={false}
35
+ themeGroupStyleEnabled={false}
35
36
  themeHasError={false}
36
- themeUseGroupStyleEnabled={false}
37
37
  >
38
38
  <View
39
39
  pointerEvents="none"
@@ -671,8 +671,8 @@ exports[`Dialog renders DatePickerAndroid when OS is android 1`] = `
671
671
  ]
672
672
  }
673
673
  themeFocused={false}
674
+ themeGroupStyleEnabled={false}
674
675
  themeHasError={false}
675
- themeUseGroupStyleEnabled={false}
676
676
  >
677
677
  <View
678
678
  pointerEvents="none"
@@ -994,8 +994,8 @@ exports[`Dialog renders DatePickerIOS when OS is iOS 1`] = `
994
994
  ]
995
995
  }
996
996
  themeFocused={false}
997
+ themeGroupStyleEnabled={false}
997
998
  themeHasError={false}
998
- themeUseGroupStyleEnabled={false}
999
999
  >
1000
1000
  <View
1001
1001
  pointerEvents="none"
@@ -37,8 +37,8 @@ exports[`FormGroup 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"
@@ -199,6 +199,14 @@ exports[`FormGroup should render: xxx 1`] = `
199
199
  }
200
200
  allowFontScaling={false}
201
201
  editable={true}
202
+ inputProps={
203
+ {
204
+ "textStyle": {
205
+ "borderBottomLeftRadius": 0,
206
+ "borderBottomRightRadius": 0,
207
+ },
208
+ }
209
+ }
202
210
  onBlur={[Function]}
203
211
  onChangeText={[Function]}
204
212
  onFocus={[Function]}
@@ -290,8 +298,8 @@ exports[`FormGroup should render: xxx 1`] = `
290
298
  }
291
299
  testID="text-input-2"
292
300
  themeFocused={false}
301
+ themeGroupStyleEnabled={true}
293
302
  themeHasError={true}
294
- themeUseGroupStyleEnabled={true}
295
303
  >
296
304
  <View
297
305
  pointerEvents="none"
@@ -480,6 +488,13 @@ exports[`FormGroup should render: xxx 1`] = `
480
488
  }
481
489
  allowFontScaling={false}
482
490
  editable={true}
491
+ inputProps={
492
+ {
493
+ "textStyle": {
494
+ "borderRadius": 0,
495
+ },
496
+ }
497
+ }
483
498
  onBlur={[Function]}
484
499
  onChangeText={[Function]}
485
500
  onFocus={[Function]}
@@ -650,8 +665,8 @@ exports[`FormGroup should render: xxx 1`] = `
650
665
  ]
651
666
  }
652
667
  themeFocused={false}
668
+ themeGroupStyleEnabled={true}
653
669
  themeHasError={false}
654
- themeUseGroupStyleEnabled={true}
655
670
  >
656
671
  <View
657
672
  pointerEvents="none"
@@ -812,6 +827,14 @@ exports[`FormGroup should render: xxx 1`] = `
812
827
  }
813
828
  allowFontScaling={false}
814
829
  editable={true}
830
+ inputProps={
831
+ {
832
+ "textStyle": {
833
+ "borderTopLeftRadius": 0,
834
+ "borderTopRightRadius": 0,
835
+ },
836
+ }
837
+ }
815
838
  onBlur={[Function]}
816
839
  onChangeText={[Function]}
817
840
  onFocus={[Function]}
@@ -1,9 +1,11 @@
1
1
  import React from 'react';
2
2
  import { within } from '@testing-library/react-native';
3
- import renderWithTheme from '../../../../testUtils/renderWithTheme';
4
- import FormGroup from '..';
5
- import TextInput from '../../TextInput';
6
3
  import theme from '../../../theme';
4
+ import TextInput from '../../TextInput';
5
+ import Select from '../../Select';
6
+ import FormGroup from '..';
7
+ import renderWithTheme from '../../../../testUtils/renderWithTheme';
8
+ import { noop } from '../../../utils/functions';
7
9
 
8
10
  describe('FormGroup', () => {
9
11
  it('should render', () => {
@@ -176,4 +178,129 @@ describe('FormGroup', () => {
176
178
  );
177
179
  expect(borderKeys).toHaveLength(0);
178
180
  });
181
+
182
+ it('renders enhanced TextInput/Select components with correct styles', () => {
183
+ const { getByTestId } = renderWithTheme(
184
+ <FormGroup>
185
+ <TextInput
186
+ label="Enhanced Text Input"
187
+ value="Enhanced Text Input"
188
+ testID="enhanced-text-input"
189
+ />
190
+ <Select
191
+ label="Enhanced Select"
192
+ value="option1"
193
+ testID="enhanced-select"
194
+ onConfirm={noop}
195
+ options={[
196
+ { text: 'Option 1', value: 'option1' },
197
+ { text: 'Option 2', value: 'option2' },
198
+ ]}
199
+ />
200
+ </FormGroup>
201
+ );
202
+
203
+ // Enhanced TextInput should have correct border styling
204
+ expect(
205
+ within(getByTestId('enhanced-text-input'))
206
+ .getByTestId('text-input-border')
207
+ .props.style.flat()
208
+ ).toEqual(
209
+ expect.arrayContaining([
210
+ expect.objectContaining({
211
+ borderBottomLeftRadius: 0,
212
+ borderBottomRightRadius: 0,
213
+ }),
214
+ ])
215
+ );
216
+
217
+ // Enhanced Select should have correct border styling
218
+ expect(
219
+ within(getByTestId('enhanced-select'))
220
+ .getByTestId('text-input-border')
221
+ .props.style.flat()
222
+ ).toEqual(
223
+ expect.arrayContaining([
224
+ expect.objectContaining({
225
+ borderTopLeftRadius: 0,
226
+ borderTopRightRadius: 0,
227
+ }),
228
+ ])
229
+ );
230
+ });
231
+
232
+ it('renders mixed components (TextInput, Select, Select.Multi) with correct styles', () => {
233
+ const { getByTestId } = renderWithTheme(
234
+ <FormGroup>
235
+ <TextInput
236
+ label="Text Input"
237
+ value="Text Input"
238
+ testID="mixed-text-input"
239
+ />
240
+ <Select
241
+ label="Single Select"
242
+ value="option1"
243
+ testID="mixed-select"
244
+ onConfirm={noop}
245
+ options={[
246
+ { text: 'Option 1', value: 'option1' },
247
+ { text: 'Option 2', value: 'option2' },
248
+ ]}
249
+ />
250
+ <Select.Multi
251
+ label="Multi Select"
252
+ value={['option1', 'option2']}
253
+ testID="mixed-select-multi"
254
+ onConfirm={noop}
255
+ footerLabel="Confirm"
256
+ options={[
257
+ { text: 'Option 1', value: 'option1' },
258
+ { text: 'Option 2', value: 'option2' },
259
+ { text: 'Option 3', value: 'option3' },
260
+ ]}
261
+ />
262
+ </FormGroup>
263
+ );
264
+
265
+ // TextInput should have top border radius removed
266
+ expect(
267
+ within(getByTestId('mixed-text-input'))
268
+ .getByTestId('text-input-border')
269
+ .props.style.flat()
270
+ ).toEqual(
271
+ expect.arrayContaining([
272
+ expect.objectContaining({
273
+ borderBottomLeftRadius: 0,
274
+ borderBottomRightRadius: 0,
275
+ }),
276
+ ])
277
+ );
278
+
279
+ // Select should have no border radius (middle component)
280
+ expect(
281
+ within(getByTestId('mixed-select'))
282
+ .getByTestId('text-input-border')
283
+ .props.style.flat()
284
+ ).toEqual(
285
+ expect.arrayContaining([
286
+ expect.objectContaining({
287
+ borderRadius: 0,
288
+ }),
289
+ ])
290
+ );
291
+
292
+ // Select.Multi should have bottom border radius removed
293
+ expect(
294
+ within(getByTestId('mixed-select-multi'))
295
+ .getByTestId('text-input-border')
296
+ .props.style.flat()
297
+ ).toEqual(
298
+ expect.arrayContaining([
299
+ expect.objectContaining({
300
+ borderTopLeftRadius: 0,
301
+ borderTopRightRadius: 0,
302
+ }),
303
+ ])
304
+ );
305
+ });
179
306
  });
@@ -1,4 +1,4 @@
1
- import React, { ReactNode, useMemo } from 'react';
1
+ import React, { ReactElement, 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';
@@ -6,7 +6,7 @@ import { generateBorderStyle, generateMarginStyle } from './utils';
6
6
  export interface FormGroupProps extends ViewProps {
7
7
  /**
8
8
  * The children of the FormGroup. In order for the group styling to work,
9
- * they must be either HD form components (TextInput, Select, Pickers,...) or enhanced HD form components
9
+ * they must be either HD form components (TextInput, Select, Pickers,...) or enhanced HD input components
10
10
  * that supports the corresponding interface.
11
11
  *
12
12
  * Example:
@@ -33,15 +33,15 @@ export interface FormGroupProps extends ViewProps {
33
33
  const FormGroup = ({ children, style, testID, ...props }: FormGroupProps) => {
34
34
  const theme = useTheme();
35
35
  const childrenArray = React.Children.toArray(children).filter(
36
- React.isValidElement
36
+ (child): child is ReactElement => React.isValidElement(child)
37
37
  );
38
38
 
39
39
  // If there are multiple children, inject styles to group them together.
40
40
  const groupedChildren = useMemo(
41
41
  () =>
42
42
  childrenArray.map((child, index) => {
43
- const rawChildStyle = (child as React.ReactElement).props.style;
44
- const rawChildTextStyle = (child as React.ReactElement).props.textStyle;
43
+ const rawChildStyle = child.props.style;
44
+ const rawChildTextStyle = child.props.textStyle;
45
45
 
46
46
  // Handle array styles by flattening them first
47
47
  const childStyle = StyleSheet.flatten(rawChildStyle);
@@ -77,11 +77,20 @@ const FormGroup = ({ children, style, testID, ...props }: FormGroupProps) => {
77
77
  }),
78
78
  };
79
79
 
80
- return React.cloneElement(child as React.ReactElement, {
80
+ return React.cloneElement(child, {
81
81
  style: mergedStyle,
82
82
  textStyle: mergedTextStyle,
83
83
  // Internal text input prop to allow for different styling
84
- enableGroupStyle: true,
84
+ groupStyleEnabled: true,
85
+
86
+ // For HD components that uses FormGroup
87
+ inputProps: {
88
+ ...child.props.inputProps,
89
+ textStyle: {
90
+ ...child.props.inputProps?.textStyle,
91
+ ...mergedTextStyle,
92
+ },
93
+ },
85
94
  });
86
95
  }),
87
96
  [childrenArray, theme]
@@ -11,6 +11,7 @@ import React, {
11
11
  import type { Ref } from 'react';
12
12
  import { WebView } from 'react-native-webview';
13
13
 
14
+ import { View } from 'react-native';
14
15
  import { isAndroid } from '../../utils/helpers';
15
16
  import { emitter } from './EditorEvent';
16
17
  import * as Events from './utils/events';
@@ -268,17 +269,22 @@ const RichTextEditorInput = forwardRef<
268
269
  );
269
270
 
270
271
  return (
271
- <StyledWebView
272
- ref={webview}
273
- testID="webview"
274
- originWhitelist={['*']}
275
- height={webviewHeight}
276
- source={{ html }}
277
- onMessage={onMessage}
278
- scrollEnabled={false}
279
- hideKeyboardAccessoryView
280
- keyboardDisplayRequiresUserAction={false}
281
- />
272
+ <View
273
+ style={{
274
+ height: webviewHeight,
275
+ }}
276
+ >
277
+ <StyledWebView
278
+ ref={webview}
279
+ testID="webview"
280
+ originWhitelist={['*']}
281
+ source={{ html }}
282
+ onMessage={onMessage}
283
+ scrollEnabled={false}
284
+ hideKeyboardAccessoryView
285
+ keyboardDisplayRequiresUserAction={false}
286
+ />
287
+ </View>
282
288
  );
283
289
  }
284
290
  );
@@ -6,10 +6,7 @@ export const StyledWrapper = styled(View)(({ theme }) => ({
6
6
  marginBottom: theme.__hd__.richTextEditor.space.wrapperMarginBottom,
7
7
  }));
8
8
 
9
- export const StyledWebView = styled(WebView)<{
10
- height: number | undefined;
11
- }>(({ height, theme }) => ({
12
- height,
9
+ export const StyledWebView = styled(WebView)(({ theme }) => ({
13
10
  minHeight: theme.__hd__.richTextEditor.sizes.editorMinHeight,
14
11
  backgroundColor: 'transparent',
15
12
  textAlignVertical: 'center',
@@ -7,6 +7,17 @@ exports[`MultiSelect renders correctly (snapshot) 1`] = `
7
7
  >
8
8
  <TouchableOpacity
9
9
  onPress={[Function]}
10
+ style={
11
+ [
12
+ [
13
+ {},
14
+ ],
15
+ undefined,
16
+ ]
17
+ }
18
+ testID="multi-select-touchable-opacity"
19
+ themeGroupStyleEnabled={false}
20
+ themeHasError={false}
10
21
  >
11
22
  <View
12
23
  pointerEvents="none"
@@ -34,8 +45,8 @@ exports[`MultiSelect renders correctly (snapshot) 1`] = `
34
45
  ]
35
46
  }
36
47
  themeFocused={false}
48
+ themeGroupStyleEnabled={false}
37
49
  themeHasError={false}
38
- themeUseGroupStyleEnabled={false}
39
50
  >
40
51
  <View
41
52
  pointerEvents="none"
@@ -693,6 +704,17 @@ exports[`Select renders correctly (snapshot) 1`] = `
693
704
  >
694
705
  <TouchableOpacity
695
706
  onPress={[Function]}
707
+ style={
708
+ [
709
+ [
710
+ {},
711
+ ],
712
+ undefined,
713
+ ]
714
+ }
715
+ testID="single-select-touchable-opacity"
716
+ themeGroupStyleEnabled={false}
717
+ themeHasError={false}
696
718
  >
697
719
  <View
698
720
  pointerEvents="none"
@@ -720,8 +742,8 @@ exports[`Select renders correctly (snapshot) 1`] = `
720
742
  ]
721
743
  }
722
744
  themeFocused={false}
745
+ themeGroupStyleEnabled={false}
723
746
  themeHasError={false}
724
- themeUseGroupStyleEnabled={false}
725
747
  >
726
748
  <View
727
749
  pointerEvents="none"
@@ -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]
@@ -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
  }));