@chem-po/react-native 0.0.28 → 0.0.29

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 (73) hide show
  1. package/lib/commonjs/components/form/input/Editable.js +17 -27
  2. package/lib/commonjs/components/form/input/Editable.js.map +1 -1
  3. package/lib/commonjs/components/form/input/StandaloneInput.js +5 -1
  4. package/lib/commonjs/components/form/input/StandaloneInput.js.map +1 -1
  5. package/lib/commonjs/components/form/input/hooks/useInputStyles.js +2 -1
  6. package/lib/commonjs/components/form/input/hooks/useInputStyles.js.map +1 -1
  7. package/lib/commonjs/components/form/input/multipleSelect/index.js +19 -10
  8. package/lib/commonjs/components/form/input/multipleSelect/index.js.map +1 -1
  9. package/lib/commonjs/components/form/input/number/index.js +8 -4
  10. package/lib/commonjs/components/form/input/number/index.js.map +1 -1
  11. package/lib/commonjs/components/form/input/select/index.js +14 -4
  12. package/lib/commonjs/components/form/input/select/index.js.map +1 -1
  13. package/lib/commonjs/components/form/input/text/AutoResizeTextarea.js +54 -0
  14. package/lib/commonjs/components/form/input/text/AutoResizeTextarea.js.map +1 -0
  15. package/lib/commonjs/components/form/input/text/index.js +22 -11
  16. package/lib/commonjs/components/form/input/text/index.js.map +1 -1
  17. package/lib/commonjs/components/form/input/text/textarea.js +12 -21
  18. package/lib/commonjs/components/form/input/text/textarea.js.map +1 -1
  19. package/lib/commonjs/components/form/input/text/useWebAutoResize.js +65 -0
  20. package/lib/commonjs/components/form/input/text/useWebAutoResize.js.map +1 -0
  21. package/lib/commonjs/contexts/root.js +94 -1
  22. package/lib/commonjs/contexts/root.js.map +1 -1
  23. package/lib/module/components/form/input/Editable.js +17 -27
  24. package/lib/module/components/form/input/Editable.js.map +1 -1
  25. package/lib/module/components/form/input/StandaloneInput.js +5 -1
  26. package/lib/module/components/form/input/StandaloneInput.js.map +1 -1
  27. package/lib/module/components/form/input/hooks/useInputStyles.js +2 -1
  28. package/lib/module/components/form/input/hooks/useInputStyles.js.map +1 -1
  29. package/lib/module/components/form/input/multipleSelect/index.js +19 -10
  30. package/lib/module/components/form/input/multipleSelect/index.js.map +1 -1
  31. package/lib/module/components/form/input/number/index.js +8 -4
  32. package/lib/module/components/form/input/number/index.js.map +1 -1
  33. package/lib/module/components/form/input/select/index.js +15 -5
  34. package/lib/module/components/form/input/select/index.js.map +1 -1
  35. package/lib/module/components/form/input/text/AutoResizeTextarea.js +48 -0
  36. package/lib/module/components/form/input/text/AutoResizeTextarea.js.map +1 -0
  37. package/lib/module/components/form/input/text/index.js +22 -11
  38. package/lib/module/components/form/input/text/index.js.map +1 -1
  39. package/lib/module/components/form/input/text/textarea.js +13 -22
  40. package/lib/module/components/form/input/text/textarea.js.map +1 -1
  41. package/lib/module/components/form/input/text/useWebAutoResize.js +59 -0
  42. package/lib/module/components/form/input/text/useWebAutoResize.js.map +1 -0
  43. package/lib/module/contexts/root.js +95 -2
  44. package/lib/module/contexts/root.js.map +1 -1
  45. package/lib/typescript/components/form/input/Editable.d.ts.map +1 -1
  46. package/lib/typescript/components/form/input/StandaloneInput.d.ts +8 -6
  47. package/lib/typescript/components/form/input/StandaloneInput.d.ts.map +1 -1
  48. package/lib/typescript/components/form/input/multipleSelect/index.d.ts.map +1 -1
  49. package/lib/typescript/components/form/input/number/index.d.ts.map +1 -1
  50. package/lib/typescript/components/form/input/select/index.d.ts.map +1 -1
  51. package/lib/typescript/components/form/input/text/AutoResizeTextarea.d.ts +4 -0
  52. package/lib/typescript/components/form/input/text/AutoResizeTextarea.d.ts.map +1 -0
  53. package/lib/typescript/components/form/input/text/index.d.ts.map +1 -1
  54. package/lib/typescript/components/form/input/text/textarea.d.ts.map +1 -1
  55. package/lib/typescript/components/form/input/text/useWebAutoResize.d.ts +8 -0
  56. package/lib/typescript/components/form/input/text/useWebAutoResize.d.ts.map +1 -0
  57. package/lib/typescript/components/form/types.d.ts +2 -2
  58. package/lib/typescript/components/form/types.d.ts.map +1 -1
  59. package/lib/typescript/contexts/root.d.ts +4 -1
  60. package/lib/typescript/contexts/root.d.ts.map +1 -1
  61. package/package.json +3 -3
  62. package/src/components/form/input/Editable.tsx +16 -33
  63. package/src/components/form/input/StandaloneInput.tsx +29 -7
  64. package/src/components/form/input/hooks/useInputStyles.ts +1 -1
  65. package/src/components/form/input/multipleSelect/index.tsx +22 -19
  66. package/src/components/form/input/number/index.tsx +20 -4
  67. package/src/components/form/input/select/index.tsx +16 -4
  68. package/src/components/form/input/text/AutoResizeTextarea.tsx +45 -0
  69. package/src/components/form/input/text/index.tsx +34 -17
  70. package/src/components/form/input/text/textarea.tsx +7 -21
  71. package/src/components/form/input/text/useWebAutoResize.tsx +72 -0
  72. package/src/components/form/types.ts +6 -2
  73. package/src/contexts/root.tsx +101 -3
@@ -3,6 +3,7 @@ import {
3
3
  SelectField,
4
4
  useBackgroundColor,
5
5
  useBorderColor,
6
+ useColorMode,
6
7
  useIconColor,
7
8
  usePlaceholderColor,
8
9
  } from '@chem-po/react'
@@ -29,6 +30,7 @@ const BaseSelectComponent = <T extends SelectField>(
29
30
  } = field
30
31
  const { onChange, value, onFocus, onBlur } = input
31
32
  const { active } = meta
33
+ const colorMode = useColorMode()
32
34
 
33
35
  const inputRef = useRef<IDropdownRef>(null)
34
36
  const {
@@ -70,8 +72,18 @@ const BaseSelectComponent = <T extends SelectField>(
70
72
  ref={inputRef}
71
73
  style={[inputStyles, { borderColor }]}
72
74
  placeholderStyle={[text, { color: placeholderColor }]}
75
+ containerStyle={{
76
+ backgroundColor: menuBg,
77
+ borderWidth: 0,
78
+ borderColor: 'transparent',
79
+ boxShadow: `0 0 10px ${borderColor}`,
80
+ }}
73
81
  selectedTextStyle={text}
74
- inputSearchStyle={[styles.inputSearch, text]}
82
+ inputSearchStyle={[
83
+ styles.inputSearch,
84
+ text,
85
+ { backgroundColor: selectedOptionBg, borderColor: 'transparent' },
86
+ ]}
75
87
  iconStyle={styles.iconStyle}
76
88
  data={options}
77
89
  search={searchable}
@@ -95,7 +107,7 @@ const BaseSelectComponent = <T extends SelectField>(
95
107
  <RenderOptionText
96
108
  value={item.value}
97
109
  option={item}
98
- colorMode="light"
110
+ colorMode={colorMode}
99
111
  isSelected={!!selected}
100
112
  size={size}
101
113
  />
@@ -108,13 +120,13 @@ const BaseSelectComponent = <T extends SelectField>(
108
120
  size={iconSize}
109
121
  color={iconColor}
110
122
  />
111
- {optional && value ? (
123
+ {optional && value && !inEditable ? (
112
124
  <InputClearButton
113
125
  size={clearButtonSize}
114
126
  onPress={() => {
115
127
  onChange(null)
116
128
  }}
117
- isActive={!!value}
129
+ isActive
118
130
  />
119
131
  ) : null}
120
132
  </View>
@@ -0,0 +1,45 @@
1
+ import { forwardRef } from 'react'
2
+ import { StyleSheet, TextInput, TextInputProps } from 'react-native'
3
+
4
+ import { useIconColor, useTextColor } from '@chem-po/react'
5
+
6
+ import React from 'react'
7
+ import { useWebAutoResize } from './useWebAutoResize'
8
+
9
+ export const AutoResizeTextarea = forwardRef<TextInput, TextInputProps>(
10
+ ({ style, value, onChangeText, ...props }, ref) => {
11
+ const textColor = useTextColor()
12
+
13
+ const { handleChange, height, setHeight } = useWebAutoResize(onChangeText, style)
14
+
15
+ const iconColor = useIconColor()
16
+
17
+ return (
18
+ <TextInput
19
+ ref={ref}
20
+ cursorColor={iconColor}
21
+ onContentSizeChange={e => {
22
+ setHeight(e.nativeEvent.contentSize.height)
23
+ }}
24
+ multiline
25
+ style={[styles.textarea, { color: textColor, height }, style]}
26
+ value={value}
27
+ onChangeText={handleChange}
28
+ {...props}
29
+ />
30
+ )
31
+ },
32
+ )
33
+ const styles = StyleSheet.create({
34
+ textarea: {
35
+ width: '100%',
36
+ minHeight: 18,
37
+ backgroundColor: 'transparent',
38
+ textAlignVertical: 'top',
39
+ outlineWidth: 0,
40
+ },
41
+ inEditable: {
42
+ paddingHorizontal: 0,
43
+ paddingVertical: 0,
44
+ },
45
+ })
@@ -8,12 +8,16 @@ import { useInputStyles } from '../hooks/useInputStyles'
8
8
  import { TextAreaComponent } from './textarea'
9
9
 
10
10
  export const TextComponent = forwardRef<InputRef, FieldProps<TextField>>(
11
- ({ input, inEditable, meta, field, style, formSize }, ref) => {
11
+ ({ input, inEditable, meta, field, style, formSize, inputStyle }, ref) => {
12
12
  const { placeholder, type } = field
13
13
  const [isHidden, setIsHidden] = useState(type === 'password')
14
14
  const { value, onChange, ...inputProps } = input
15
15
  const inputRef = useRef<TextInput>(null)
16
- const { container: inputStyles } = useInputStyles(inEditable, field.size, formSize)
16
+ const { container: conatinerStyles, text: inputStyles } = useInputStyles(
17
+ inEditable,
18
+ field.size,
19
+ formSize,
20
+ )
17
21
 
18
22
  useImperativeHandle(ref, () => ({
19
23
  focus: () => {
@@ -26,31 +30,44 @@ export const TextComponent = forwardRef<InputRef, FieldProps<TextField>>(
26
30
 
27
31
  const placeholderColor = usePlaceholderColor()
28
32
  const color = useTextColor()
29
- const body =
30
- type === 'textarea' ? (
31
- <TextAreaComponent inEditable={inEditable} field={field} input={input} meta={meta} />
32
- ) : (
33
- <TextInput
34
- ref={inputRef}
35
- style={[inputStyles, { color }, style]}
36
- secureTextEntry={isHidden}
37
- placeholderTextColor={placeholderColor}
38
- placeholder={placeholder}
39
- value={value ?? ''}
40
- onChangeText={onChange}
41
- {...inputProps}
33
+
34
+ if (type === 'textarea') {
35
+ return (
36
+ <TextAreaComponent
37
+ ref={ref}
38
+ formSize={formSize}
39
+ inputStyle={inputStyle}
40
+ inEditable={inEditable}
41
+ field={field}
42
+ style={style}
43
+ input={input}
44
+ meta={meta}
42
45
  />
43
46
  )
47
+ }
48
+
49
+ const body = (
50
+ <TextInput
51
+ ref={inputRef}
52
+ style={[inputStyles, { color }, inputStyle]}
53
+ secureTextEntry={isHidden}
54
+ placeholderTextColor={placeholderColor}
55
+ placeholder={placeholder}
56
+ value={value ?? ''}
57
+ onChangeText={onChange}
58
+ {...inputProps}
59
+ />
60
+ )
44
61
 
45
62
  return type === 'password' ? (
46
- <View style={styles.passwordContainer}>
63
+ <View style={[conatinerStyles, styles.passwordContainer, style]}>
47
64
  {body}
48
65
  <TouchableOpacity style={styles.eyeIcon} onPress={() => setIsHidden(!isHidden)}>
49
66
  <Ionicons name={isHidden ? 'eye' : 'eye-off'} size={20} color="#666" />
50
67
  </TouchableOpacity>
51
68
  </View>
52
69
  ) : (
53
- body
70
+ <View style={[conatinerStyles, style]}>{body}</View>
54
71
  )
55
72
  },
56
73
  )
@@ -1,14 +1,15 @@
1
1
  import { InputRef } from '@chem-po/core'
2
2
  import { TextField, usePlaceholderColor, useTextColor } from '@chem-po/react'
3
3
  import React, { forwardRef, useImperativeHandle, useRef } from 'react'
4
- import { StyleSheet, TextInput, View } from 'react-native'
4
+ import { TextInput, View } from 'react-native'
5
5
  import { FieldProps } from '../../types'
6
6
  import { useInputStyles } from '../hooks/useInputStyles'
7
+ import { AutoResizeTextarea } from './AutoResizeTextarea'
7
8
 
8
9
  export const TextAreaComponent = forwardRef<InputRef, FieldProps<TextField>>(
9
- ({ input, field, inEditable, formSize }, ref) => {
10
+ ({ input, field, inEditable, formSize, inputStyle, style }, ref) => {
10
11
  const inputRef = useRef<TextInput>(null)
11
- const { container: inputStyles } = useInputStyles(inEditable, field.size, formSize)
12
+ const { text, container } = useInputStyles(inEditable, field.size, formSize)
12
13
  const { value, onChange, ...inputProps } = input
13
14
 
14
15
  useImperativeHandle(ref, () => ({
@@ -24,15 +25,13 @@ export const TextAreaComponent = forwardRef<InputRef, FieldProps<TextField>>(
24
25
  const color = useTextColor()
25
26
 
26
27
  return (
27
- <View style={inputStyles}>
28
- <TextInput
28
+ <View style={[container, style]}>
29
+ <AutoResizeTextarea
29
30
  ref={inputRef}
30
- style={[styles.textarea, inEditable && styles.inEditable, { color }]}
31
+ style={[{ color, ...text }, inputStyle]}
31
32
  placeholder={field.placeholder}
32
33
  placeholderTextColor={placeholderColor}
33
34
  multiline
34
- maxLength={200}
35
- textAlignVertical="top"
36
35
  value={value ?? ''}
37
36
  onChangeText={onChange}
38
37
  {...inputProps}
@@ -43,16 +42,3 @@ export const TextAreaComponent = forwardRef<InputRef, FieldProps<TextField>>(
43
42
  )
44
43
 
45
44
  TextAreaComponent.displayName = 'TextAreaComponent'
46
-
47
- const styles = StyleSheet.create({
48
- textarea: {
49
- width: '100%',
50
- minHeight: 80,
51
- backgroundColor: 'transparent',
52
- textAlignVertical: 'top',
53
- },
54
- inEditable: {
55
- paddingHorizontal: 0,
56
- paddingVertical: 0,
57
- },
58
- })
@@ -0,0 +1,72 @@
1
+ import { useEffect, useMemo, useRef, useState } from 'react'
2
+ import { Platform, StyleProp, StyleSheet, TextStyle } from 'react-native'
3
+
4
+ // creates a span element with the text and style and returns the height
5
+ const getWebTextHeight = (text: string, spanRef: React.RefObject<HTMLSpanElement | null>) => {
6
+ if (!spanRef.current) return null
7
+ const span = spanRef.current
8
+ span.innerText = `${text}\n`
9
+ document.body.appendChild(span)
10
+ const height = span.offsetHeight
11
+ document.body.removeChild(span)
12
+ return height
13
+ }
14
+
15
+ const updateSpanStyle = (span: HTMLSpanElement, style: TextStyle | undefined) => {
16
+ span.style.whiteSpace = 'pre-wrap'
17
+ if (style?.fontFamily) {
18
+ span.style.fontFamily = style.fontFamily
19
+ }
20
+ if (style?.fontSize) {
21
+ span.style.fontSize = style.fontSize.toString() + 'px'
22
+ }
23
+ if (style?.fontWeight) {
24
+ span.style.fontWeight = style.fontWeight.toString()
25
+ }
26
+ if (style?.lineHeight) {
27
+ span.style.lineHeight = style.lineHeight.toString()
28
+ }
29
+ if (style?.letterSpacing) {
30
+ span.style.letterSpacing = style.letterSpacing.toString()
31
+ }
32
+ if (style?.textAlign) {
33
+ span.style.textAlign = style.textAlign
34
+ }
35
+ }
36
+
37
+ export const useWebAutoResize = (
38
+ onChangeText: ((e: string) => void) | undefined,
39
+ style: StyleProp<TextStyle> | undefined,
40
+ ) => {
41
+ const [height, setHeight] = useState(18)
42
+ const spanRef = useRef<HTMLSpanElement>(
43
+ Platform.OS === 'web' ? document.createElement('span') : null,
44
+ )
45
+
46
+ useEffect(() => {
47
+ if (Platform.OS === 'web' && spanRef.current) {
48
+ updateSpanStyle(spanRef.current, {
49
+ ...StyleSheet.flatten(style),
50
+ })
51
+ }
52
+ }, [style])
53
+ const handleChange = useMemo(
54
+ () =>
55
+ Platform.OS === 'web'
56
+ ? (e: string) => {
57
+ if (spanRef.current) {
58
+ const height = getWebTextHeight(e, spanRef)
59
+ setHeight(height ?? 18)
60
+ if (onChangeText) onChangeText(e)
61
+ }
62
+ }
63
+ : onChangeText,
64
+ [onChangeText],
65
+ )
66
+ return {
67
+ getWebTextHeight,
68
+ handleChange,
69
+ height,
70
+ setHeight,
71
+ }
72
+ }
@@ -1,4 +1,8 @@
1
1
  import { BaseFieldProps, Field } from '@chem-po/react'
2
- import { StyleProp } from 'react-native'
2
+ import { StyleProp, TextStyle, ViewStyle } from 'react-native'
3
3
 
4
- export type FieldProps<T extends Field> = BaseFieldProps<StyleProp<any>, T>
4
+ export type FieldProps<
5
+ T extends Field,
6
+ ContainerStyle extends ViewStyle = ViewStyle,
7
+ InputStyle extends TextStyle = TextStyle,
8
+ > = BaseFieldProps<StyleProp<ContainerStyle>, StyleProp<InputStyle>, T>
@@ -1,24 +1,121 @@
1
1
  import { BackendAdapterInterface, ColorMode, Theme } from '@chem-po/core'
2
- import { ChempoProps, ChempoProvider } from '@chem-po/react'
2
+ import { ChempoProps, ChempoProvider, useTheme } from '@chem-po/react'
3
3
  import React, { PropsWithChildren, useMemo } from 'react'
4
4
  import { NotifierWrapper } from 'react-native-notifier'
5
+ import { configureFonts, PaperProvider, Props as PaperProviderProps } from 'react-native-paper'
5
6
  import { en, registerTranslation } from 'react-native-paper-dates'
7
+ import { MD3Type, MD3TypescaleKey } from 'react-native-paper/lib/typescript/types'
6
8
  import { nativeToast } from '../constants/toast'
7
9
  import { useThemeState } from '../hooks/useThemeState'
8
10
  import { initializeScreen } from '../store/useScreen'
9
11
 
10
12
  registerTranslation('en', en)
11
13
 
14
+ export type FontConfig = Partial<Record<MD3TypescaleKey, Partial<MD3Type>>>
12
15
  export interface ChempoNativeProviderProps<BackendAdapter extends BackendAdapterInterface>
13
16
  extends PropsWithChildren<Pick<ChempoProps<BackendAdapter>, 'backendAdapter' | 'assets'>> {
14
17
  theme?: Theme
18
+ fonts?: FontConfig
15
19
  initialColorMode?: ColorMode
16
20
  }
21
+ const createPaperTheme = (
22
+ theme: Theme,
23
+ fonts: FontConfig | undefined,
24
+ colorMode: ColorMode,
25
+ ): PaperProviderProps['theme'] => {
26
+ const { colors } = theme
27
+
28
+ return {
29
+ dark: colorMode === 'dark',
30
+ colors: {
31
+ primary: colors.accent[200],
32
+ onPrimary: colors.text[900],
33
+ primaryContainer: colors.accent[500],
34
+ onPrimaryContainer: colors.text[300],
35
+
36
+ secondary: colors.background[150],
37
+ onSecondary: colors.text[100],
38
+ secondaryContainer: colors.background[50],
39
+ onSecondaryContainer: colors.text[150],
40
+
41
+ tertiary: colors.accent[600],
42
+ onTertiary: colors.text[50],
43
+ tertiaryContainer: colors.accent[300],
44
+ onTertiaryContainer: colors.text[700],
45
+
46
+ error: colors.error[500],
47
+ onError: colors.text[50],
48
+ errorContainer: colors.error[100],
49
+ onErrorContainer: colors.error[900],
50
+
51
+ background: colors.background[50],
52
+ onBackground: colors.text[100],
53
+ surface: colors.background[100],
54
+ onSurface: colors.text[100],
55
+ surfaceVariant: colors.background[200],
56
+ onSurfaceVariant: colors.text[250],
57
+ outline: colors.text[500],
58
+ outlineVariant: colors.accent[300],
59
+
60
+ surfaceDisabled: colors.background[200],
61
+ onSurfaceDisabled: colors.text[400],
62
+ backdrop: '#000000aa', // 60% opacity
63
+
64
+ inverseSurface: colors.background[900],
65
+ inverseOnSurface: colors.text[50],
66
+ inversePrimary: colors.accent[200],
67
+ shadow: '#00000099',
68
+ scrim: '#00000099', // Semi-transparent dark overlay
69
+
70
+ elevation: {
71
+ level0: 'transparent',
72
+ level1: colors.background[100],
73
+ level2: colors.background[200],
74
+ level3: colors.background[300],
75
+ level4: colors.background[400],
76
+ level5: colors.background[500],
77
+ },
78
+ },
79
+ roundness: 4,
80
+ animation: {
81
+ scale: 1.0,
82
+ },
83
+ fonts: configureFonts({
84
+ config: {
85
+ ...fonts,
86
+ bodyLarge: {
87
+ fontSize: 18,
88
+ ...fonts?.bodyLarge,
89
+ },
90
+ bodyMedium: {
91
+ fontSize: 17,
92
+ ...fonts?.bodyMedium,
93
+ },
94
+ bodySmall: {
95
+ fontSize: 15,
96
+ ...fonts?.bodySmall,
97
+ },
98
+ },
99
+ }),
100
+ }
101
+ }
102
+
103
+ const ChempoPaperProvider = ({ children, fonts }: PropsWithChildren<{ fonts?: FontConfig }>) => {
104
+ const { theme, colorMode } = useTheme()
105
+
106
+ const paperTheme = useMemo(
107
+ () => createPaperTheme(theme, fonts, colorMode),
108
+ [theme, fonts, colorMode],
109
+ )
110
+ return <PaperProvider theme={paperTheme}>{children}</PaperProvider>
111
+ }
17
112
  export const ChempoNativeProvider = <
18
113
  BackendAdapter extends BackendAdapterInterface<any, any, any, any, any, any>,
19
114
  >({
20
115
  theme: themeProp,
21
116
  initialColorMode,
117
+ children,
118
+ fonts,
22
119
  ...props
23
120
  }: ChempoNativeProviderProps<BackendAdapter>) => {
24
121
  const useThemeProps = useMemo(
@@ -32,8 +129,9 @@ export const ChempoNativeProvider = <
32
129
  toast={nativeToast}
33
130
  theme={theme}
34
131
  initializeScreen={initializeScreen}
35
- {...props}
36
- />
132
+ {...props}>
133
+ <ChempoPaperProvider fonts={fonts}>{children}</ChempoPaperProvider>
134
+ </ChempoProvider>
37
135
  </NotifierWrapper>
38
136
  )
39
137
  }