@codeleap/mobile 3.25.0 → 3.25.2

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 (131) hide show
  1. package/package.json +4 -6
  2. package/src/components/ActionIcon/index.tsx +37 -55
  3. package/src/components/ActionIcon/styles.ts +4 -2
  4. package/src/components/ActivityIndicator/index.tsx +64 -42
  5. package/src/components/ActivityIndicator/styles.ts +10 -1
  6. package/src/components/Autocomplete/index.tsx +54 -46
  7. package/src/components/Autocomplete/styles.ts +5 -2
  8. package/src/components/Autocomplete/types.ts +23 -13
  9. package/src/components/Avatar/index.tsx +71 -59
  10. package/src/components/Avatar/styles.ts +9 -1
  11. package/src/components/AvatarGroup/index.tsx +44 -30
  12. package/src/components/AvatarGroup/styles.ts +6 -0
  13. package/src/components/Backdrop/index.tsx +34 -51
  14. package/src/components/Backdrop/styles.ts +10 -5
  15. package/src/components/Badge/index.tsx +62 -36
  16. package/src/components/Badge/styles.ts +11 -3
  17. package/src/components/Button/index.tsx +82 -55
  18. package/src/components/Button/styles.ts +14 -13
  19. package/src/components/Calendar/index.tsx +29 -35
  20. package/src/components/Calendar/style.ts +6 -0
  21. package/src/components/Checkbox/index.tsx +64 -43
  22. package/src/components/Checkbox/styles.ts +6 -1
  23. package/src/components/ContentView/index.tsx +63 -0
  24. package/src/components/ContentView/styles.ts +8 -0
  25. package/src/components/DatePickerModal/index.tsx +65 -50
  26. package/src/components/DatePickerModal/styles.ts +10 -9
  27. package/src/components/DatePickerModal/types.ts +54 -36
  28. package/src/components/Drawer/index.tsx +28 -0
  29. package/src/components/Drawer/styles.ts +8 -0
  30. package/src/components/EmptyPlaceholder/index.tsx +63 -40
  31. package/src/components/EmptyPlaceholder/styles.ts +5 -0
  32. package/src/components/FileInput/index.tsx +49 -11
  33. package/src/components/FileInput/styles.ts +8 -0
  34. package/src/components/Grid/index.tsx +116 -84
  35. package/src/components/Grid/styles.ts +5 -0
  36. package/src/components/Icon/index.tsx +79 -44
  37. package/src/components/Icon/styles.ts +6 -0
  38. package/src/components/Image/index.tsx +78 -58
  39. package/src/components/Image/styles.ts +6 -1
  40. package/src/components/ImageView/Spotlight.tsx +4 -1
  41. package/src/components/ImageView/component.tsx +2 -1
  42. package/src/components/InputBase/index.tsx +24 -33
  43. package/src/components/InputBase/styles.ts +75 -66
  44. package/src/components/InputBase/types.ts +4 -3
  45. package/src/components/InputBase/utils.ts +4 -6
  46. package/src/components/InputLabel/index.tsx +38 -0
  47. package/src/components/InputLabel/styles.ts +7 -0
  48. package/src/components/List/PaginationIndicator.tsx +54 -0
  49. package/src/components/List/index.tsx +151 -99
  50. package/src/components/List/styles.ts +6 -0
  51. package/src/components/LoadingOverlay/index.tsx +29 -42
  52. package/src/components/LoadingOverlay/styles.ts +7 -7
  53. package/src/components/Modal/index.tsx +127 -80
  54. package/src/components/Modal/styles.ts +8 -0
  55. package/src/components/Navigation/Navigation.tsx +0 -1
  56. package/src/components/Navigation/types.ts +9 -2
  57. package/src/components/NumberIncrement/index.tsx +60 -50
  58. package/src/components/NumberIncrement/styles.ts +5 -0
  59. package/src/components/NumberIncrement/types.ts +39 -32
  60. package/src/components/Pager/index.tsx +94 -42
  61. package/src/components/Pager/styles.ts +13 -1
  62. package/src/components/RadioInput/index.tsx +57 -32
  63. package/src/components/RadioInput/styles.ts +7 -5
  64. package/src/components/RefreshControl/index.tsx +19 -39
  65. package/src/components/RefreshControl/styles.ts +6 -1
  66. package/src/components/Scroll/index.tsx +105 -89
  67. package/src/components/Scroll/styles.ts +5 -0
  68. package/src/components/Sections/index.tsx +161 -111
  69. package/src/components/Sections/styles.ts +5 -0
  70. package/src/components/SegmentedControl/Option.tsx +31 -46
  71. package/src/components/SegmentedControl/index.tsx +121 -86
  72. package/src/components/SegmentedControl/styles.ts +22 -15
  73. package/src/components/Select/index.tsx +82 -71
  74. package/src/components/Select/styles.ts +5 -3
  75. package/src/components/Select/types.ts +25 -20
  76. package/src/components/Slider/index.tsx +43 -58
  77. package/src/components/Slider/styles.ts +6 -15
  78. package/src/components/Slider/types.ts +14 -9
  79. package/src/components/Switch/index.tsx +56 -43
  80. package/src/components/Switch/styles.ts +7 -1
  81. package/src/components/Text/index.tsx +52 -56
  82. package/src/components/Text/styles.ts +7 -1
  83. package/src/components/TextInput/index.tsx +162 -49
  84. package/src/components/TextInput/styles.ts +8 -2
  85. package/src/components/Touchable/index.tsx +87 -44
  86. package/src/components/Touchable/styles.ts +9 -0
  87. package/src/components/View/index.tsx +92 -23
  88. package/src/components/View/styles.ts +6 -0
  89. package/src/components/components.ts +6 -2
  90. package/src/components/defaultStyles.ts +77 -0
  91. package/src/index.ts +0 -2
  92. package/src/modules/PressableRipple/type.ts +0 -1
  93. package/src/utils/KeyboardAware/context.tsx +2 -0
  94. package/src/utils/KeyboardAware/keyboardHooks.ts +2 -1
  95. package/src/utils/ModalManager/components.tsx +30 -1
  96. package/src/utils/ModalManager/context.tsx +4 -4
  97. package/src/utils/ModalManager/index.ts +4 -1
  98. package/src/utils/hooks.ts +1 -12
  99. package/src/Registry.ts +0 -52
  100. package/src/components/ActionIcon/types.ts +0 -15
  101. package/src/components/ActivityIndicator/types.ts +0 -9
  102. package/src/components/Avatar/types.ts +0 -23
  103. package/src/components/AvatarGroup/types.ts +0 -10
  104. package/src/components/Backdrop/types.ts +0 -14
  105. package/src/components/Badge/types.ts +0 -27
  106. package/src/components/Button/types.ts +0 -20
  107. package/src/components/Checkbox/types.ts +0 -13
  108. package/src/components/EmptyPlaceholder/types.ts +0 -21
  109. package/src/components/FileInput/types.ts +0 -27
  110. package/src/components/Grid/types.ts +0 -20
  111. package/src/components/Icon/types.ts +0 -15
  112. package/src/components/Image/types.ts +0 -18
  113. package/src/components/List/types.ts +0 -41
  114. package/src/components/LoadingOverlay/types.ts +0 -9
  115. package/src/components/Modal/types.ts +0 -41
  116. package/src/components/Pager/types.ts +0 -37
  117. package/src/components/PaginationIndicator/index.tsx +0 -51
  118. package/src/components/PaginationIndicator/styles.ts +0 -3
  119. package/src/components/PaginationIndicator/types.ts +0 -10
  120. package/src/components/RadioInput/types.ts +0 -31
  121. package/src/components/RefreshControl/types.ts +0 -9
  122. package/src/components/Scroll/types.ts +0 -21
  123. package/src/components/SearchInput/index.tsx +0 -90
  124. package/src/components/Sections/types.ts +0 -39
  125. package/src/components/SegmentedControl/types.ts +0 -31
  126. package/src/components/Switch/types.ts +0 -12
  127. package/src/components/Text/types.ts +0 -18
  128. package/src/components/TextInput/types.ts +0 -23
  129. package/src/components/Touchable/types.ts +0 -27
  130. package/src/components/View/types.ts +0 -13
  131. package/src/hooks/index.ts +0 -13
@@ -1,19 +1,50 @@
1
- import React, { useState } from 'react'
2
- import { TypeGuards, useValidate, useBooleanToggle } from '@codeleap/common'
1
+ import * as React from 'react'
2
+ import {
3
+ ComponentVariants,
4
+ FormTypes,
5
+ PropsOf,
6
+ TypeGuards,
7
+ useDefaultComponentStyle,
8
+ useValidate,
9
+ yup,
10
+ useState,
11
+ useBooleanToggle,
12
+ IconPlaceholder,
13
+ } from '@codeleap/common'
3
14
  import { forwardRef, useImperativeHandle } from 'react'
4
- import { TextInput as NativeTextInput, NativeSyntheticEvent, TextInputFocusEventData } from 'react-native'
5
- import { InputBase, selectInputBaseProps } from '../InputBase'
15
+ import { ComponentWithDefaultProps, StylesOf } from '../../types'
16
+ import { StyleSheet, TextInput as NativeTextInput, TextInputProps as NativeTextInputProps, NativeSyntheticEvent, TextInputFocusEventData } from 'react-native'
17
+ import { InputBase, InputBaseProps, selectInputBaseProps } from '../InputBase'
18
+ import { TextInputComposition, TextInputPresets } from './styles'
6
19
  import { Touchable } from '../Touchable'
7
- import { MaskedTextInput } from '../../modules/textInputMask'
8
- import { AnyRecord, AppIcon, IJSX, StyledComponentProps, StyledComponentWithProps } from '@codeleap/styles'
9
- import { TextInputProps } from './types'
10
- import { MobileStyleRegistry } from '../../Registry'
11
- import { useStylesFor } from '../../hooks'
20
+ import { MaskedTextInput, TextInputMaskProps } from '../../modules/textInputMask'
12
21
 
13
22
  export * from './styles'
14
- export * from './types'
15
23
 
16
- export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inputRef) => {
24
+ export type TextInputProps =
25
+ Omit<InputBaseProps, 'styles' | 'variants'> &
26
+ NativeTextInputProps &
27
+ {
28
+ styles?: StylesOf<TextInputComposition>
29
+ password?: boolean
30
+ validate?: FormTypes.ValidatorFunctionWithoutForm | yup.SchemaOf<string>
31
+ debugName: string
32
+ visibilityToggle?: boolean
33
+ masking?: FormTypes.TextField['masking']
34
+ variants?: ComponentVariants<typeof TextInputPresets>['variants']
35
+ onChangeMask?: TextInputMaskProps['onChangeText']
36
+ visibleIcon?: IconPlaceholder
37
+ hiddenIcon?: IconPlaceholder
38
+ _error?: string
39
+ } & Pick<PropsOf<typeof Touchable>, 'onPress'>
40
+
41
+ const defaultProps: Partial<TextInputProps> = {
42
+ hiddenIcon: 'input-visiblity:hidden' as IconPlaceholder,
43
+ visibleIcon: 'input-visiblity:visible' as IconPlaceholder,
44
+ }
45
+
46
+ const TextInputComponent = forwardRef<NativeTextInput, TextInputProps>((props, inputRef) => {
47
+
17
48
  const innerInputRef = React.useRef<NativeTextInput>(null)
18
49
 
19
50
  const [isFocused, setIsFocused] = useState(false)
@@ -27,17 +58,18 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
27
58
  })
28
59
 
29
60
  const {
61
+ variants,
62
+ styles,
30
63
  value,
31
64
  validate,
32
65
  debugName,
33
- visibilityToggle,
66
+ visibilityToggle = false,
34
67
  masking,
35
68
  password,
36
69
  onChangeMask,
37
70
  onPress,
38
71
  visibleIcon,
39
72
  hiddenIcon,
40
- style,
41
73
  _error = null,
42
74
  ...textInputProps
43
75
  } = others
@@ -48,7 +80,11 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
48
80
 
49
81
  const InputElement = isMasked ? MaskedTextInput : NativeTextInput
50
82
 
51
- const styles = useStylesFor(TextInput.styleRegistryName, style)
83
+ const variantStyles = useDefaultComponentStyle<'u:TextInput', typeof TextInputPresets>('u:TextInput', {
84
+ variants,
85
+ styles,
86
+ transform: StyleSheet.flatten,
87
+ })
52
88
 
53
89
  // @ts-expect-error - React's ref type system is weird
54
90
  useImperativeHandle(inputRef, () => {
@@ -78,6 +114,7 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
78
114
  }, [validation.onInputFocused, props.onFocus])
79
115
 
80
116
  const handleMaskChange = (masked, unmasked) => {
117
+
81
118
  if (textInputProps.onChangeText) textInputProps.onChangeText(masking?.saveFormatted ? masked : masked)
82
119
  if (onChangeMask) onChangeMask(masked, unmasked)
83
120
  }
@@ -86,24 +123,22 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
86
123
  const isDisabled = !!inputBaseProps.disabled
87
124
 
88
125
  const placeholderTextColor = [
89
- [isDisabled, styles['placeholder:disabled']],
90
- [!validation.isValid, styles['placeholder:error']],
91
- [isFocused, styles['placeholder:focus']],
92
- [true, styles?.placeholder],
93
- // @ts-expect-error
126
+ [isDisabled, variantStyles['placeholder:disabled']],
127
+ [!validation.isValid, variantStyles['placeholder:error']],
128
+ [isFocused, variantStyles['placeholder:focus']],
129
+ [true, variantStyles.placeholder],
94
130
  ].find(([x]) => x)?.[1]?.color
95
131
 
96
132
  const selectionColor = [
97
- [isDisabled, styles['selection:disabled']],
98
- [!validation.isValid, styles['selection:error']],
99
- [isFocused, styles['selection:focus']],
100
- [true, styles?.selection],
101
- // @ts-expect-error
133
+ [isDisabled, variantStyles['selection:disabled']],
134
+ [!validation.isValid, variantStyles['selection:error']],
135
+ [isFocused, variantStyles['selection:focus']],
136
+ [true, variantStyles.selection],
102
137
  ].find(([x]) => x)?.[1]?.color
103
138
 
104
139
  const visibilityToggleProps = visibilityToggle ? {
105
140
  onPress: toggleSecureTextEntry,
106
- icon: (secureTextEntry ? hiddenIcon : visibleIcon) as AppIcon,
141
+ icon: (secureTextEntry ? hiddenIcon : visibleIcon) as IconPlaceholder,
107
142
  debugName: `${debugName} toggle visibility`,
108
143
  } : null
109
144
 
@@ -112,32 +147,35 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
112
147
  const maskingExtraProps = isMasked ? {
113
148
  onChangeText: handleMaskChange,
114
149
  ref: null,
150
+
115
151
  refInput: (inputRef) => {
152
+ // console.log(inputRef)
116
153
  if (!!inputRef) {
117
154
  innerInputRef.current = inputRef
155
+
118
156
  }
119
157
  },
120
158
  ...masking,
121
159
  } : {}
122
160
 
123
161
  const buttonModeProps = isPressable ? {
162
+ // pointerEvents: 'none',
124
163
  editable: false,
125
164
  caretHidden: true,
126
165
  } : {}
127
166
 
128
167
  const hasMultipleLines = isMultiline && value?.includes('\n')
129
-
130
168
  return <InputBase
131
169
  {...inputBaseProps}
132
170
  innerWrapper={isPressable ? Touchable : undefined}
133
171
  debugName={debugName}
134
172
  error={(validation.isValid && !_error) ? null : _error || validation.message}
135
- style={{
136
- ...styles,
173
+ styles={{
174
+ ...variantStyles,
137
175
  innerWrapper: [
138
- styles?.innerWrapper,
139
- isMultiline && styles['innerWrapper:multiline'],
140
- hasMultipleLines && styles['innerWrapper:hasMultipleLines'],
176
+ variantStyles.innerWrapper,
177
+ isMultiline && variantStyles['innerWrapper:multiline'],
178
+ hasMultipleLines && variantStyles['innerWrapper:hasMultipleLines'],
141
179
  ],
142
180
  }}
143
181
  innerWrapperProps={{
@@ -150,6 +188,7 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
150
188
  focused={isFocused}
151
189
  >
152
190
  <InputElement
191
+
153
192
  allowFontScaling={false}
154
193
  editable={!isPressable && !isDisabled}
155
194
  {...buttonModeProps}
@@ -162,32 +201,106 @@ export const TextInput = forwardRef<NativeTextInput, TextInputProps>((props, inp
162
201
  onBlur={handleBlur}
163
202
  onFocus={handleFocus}
164
203
  style={[
165
- styles?.input,
166
- isMultiline && styles['input:multiline'],
167
- isFocused && styles['input:focused'],
168
- !validation.isValid && styles['input:error'],
169
- isDisabled && styles['input:disabled'],
170
- hasMultipleLines && styles['input:hasMultipleLines'],
204
+ variantStyles.input,
205
+ isMultiline && variantStyles['input:multiline'],
206
+ isFocused && variantStyles['input:focused'],
207
+ !validation.isValid && variantStyles['input:error'],
208
+ isDisabled && variantStyles['input:disabled'],
209
+ hasMultipleLines && variantStyles['input:hasMultipleLines'],
171
210
  ]}
172
211
  ref={innerInputRef}
173
212
  pointerEvents={isPressable ? 'none' : undefined}
174
213
  {...maskingExtraProps}
175
214
  />
176
215
  </InputBase>
177
- }) as StyledComponentWithProps<TextInputProps>
216
+ })
178
217
 
179
- TextInput.styleRegistryName = 'TextInput'
180
- TextInput.elements = [...InputBase.elements, 'input', 'placeholder', 'selection']
181
- TextInput.rootElement = 'wrapper'
218
+ export type SearchInputProps = {
219
+ onTypingChange: (isTyping: boolean) => void
220
+ onSearchChange: (search: string) => void
221
+ onValueChange?: (search: string) => void
222
+ onClear?: () => void
223
+ debugName: string
224
+ debounce?: number
225
+ clearIcon?: IconPlaceholder
226
+ searchIcon?: IconPlaceholder
227
+ placeholder: string
228
+ } & Partial<TextInputProps>
229
+
230
+ export const SearchInput: ComponentWithDefaultProps<SearchInputProps> = (props) => {
231
+ const {
232
+ debugName,
233
+ onClear,
234
+ onSearchChange,
235
+ onTypingChange,
236
+ clearIcon,
237
+ searchIcon,
238
+ debounce,
239
+ placeholder,
240
+ value,
241
+ onValueChange,
242
+ ...others
243
+ } = {
244
+ ...SearchInput.defaultProps,
245
+ ...props,
246
+ }
182
247
 
183
- TextInput.withVariantTypes = <S extends AnyRecord>(styles: S) => {
184
- return TextInput as (props: StyledComponentProps<TextInputProps, typeof styles>) => IJSX
248
+ const [search, setSearch] = !TypeGuards.isNil(value) && !!onValueChange ? [value, onValueChange] : useState('')
249
+
250
+ const setSearchTimeout = React.useRef<NodeJS.Timeout | null>(null)
251
+
252
+ const handleChangeSearch = (value: string) => {
253
+ setSearch(value)
254
+
255
+ if (TypeGuards.isNil(debounce)) {
256
+ onSearchChange?.(value)
257
+ } else {
258
+ if (setSearchTimeout.current) {
259
+ clearTimeout(setSearchTimeout.current)
260
+ }
261
+
262
+ setSearchTimeout.current = setTimeout(() => {
263
+
264
+ onSearchChange(value)
265
+ onTypingChange?.(false)
266
+ }, debounce ?? 0)
267
+ }
268
+
269
+ }
270
+
271
+ const handleClear = () => {
272
+ setSearch('')
273
+ onSearchChange?.('')
274
+ onClear?.()
275
+ }
276
+
277
+ return (
278
+ <TextInput
279
+ value={search}
280
+ onChangeText={(value) => {
281
+ onTypingChange?.(true)
282
+ handleChangeSearch(value)
283
+ }}
284
+ placeholder={placeholder}
285
+ debugName={`Search ${debugName}`}
286
+ rightIcon={!!search.trim() && {
287
+ name: clearIcon,
288
+ onPress: handleClear,
289
+ }}
290
+ leftIcon={{
291
+ name: searchIcon,
292
+ }}
293
+ {...others}
294
+ />
295
+ )
185
296
  }
186
297
 
187
- TextInput.defaultProps = {
188
- hiddenIcon: 'input-visiblity:hidden' as AppIcon,
189
- visibleIcon: 'input-visiblity:visible' as AppIcon,
190
- visibilityToggle: false,
191
- } as Partial<TextInputProps>
298
+ export const TextInput = TextInputComponent as ComponentWithDefaultProps<TextInputProps>
299
+
300
+ TextInput.defaultProps = defaultProps
192
301
 
193
- MobileStyleRegistry.registerComponent(TextInput)
302
+ SearchInput.defaultProps = {
303
+ debounce: null,
304
+ clearIcon: 'x' as IconPlaceholder,
305
+ searchIcon: 'search' as IconPlaceholder,
306
+ }
@@ -1,7 +1,13 @@
1
- import { InputBaseStates, InputBaseParts } from '../InputBase'
1
+ import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
2
+ import { InputBaseComposition, InputBaseStates, InputBaseParts } from '../InputBase'
2
3
 
3
- type TextInputParts = InputBaseParts | 'input' | 'placeholder' | 'selection'
4
4
 
5
+ type TextInputParts = InputBaseParts | 'input' | 'placeholder' | 'selection'
5
6
  export type TextInputStates = InputBaseStates | 'multiline' | 'hasMultipleLines' | 'pressable'
6
7
 
7
8
  export type TextInputComposition = `${TextInputParts}:${TextInputStates}` | TextInputParts
9
+
10
+ const createTextInputStyle =
11
+ createDefaultVariantFactory<TextInputComposition>()
12
+
13
+ export const TextInputPresets = includePresets((styles) => createTextInputStyle(() => ({ wrapper: styles })))
@@ -1,20 +1,65 @@
1
- import React, { forwardRef } from 'react'
2
- import { TypeGuards, onMount, useGlobalContext } from '@codeleap/common'
3
- import { Pressable, StyleSheet, View as RNView, Insets, Platform } from 'react-native'
1
+ import * as React from 'react'
2
+ import { forwardRef } from 'react'
3
+ import {
4
+ ComponentVariants,
5
+ useDefaultComponentStyle,
6
+
7
+ useCodeleapContext,
8
+ AnyFunction,
9
+ TypeGuards,
10
+ onMount,
11
+ } from '@codeleap/common'
12
+ import { Pressable, StyleSheet, View as RNView, Insets, Platform, PressableProps, ViewStyle, StyleProp } from 'react-native'
13
+ import { TouchableComposition, TouchablePresets } from './styles'
14
+ import { StylesOf } from '../../types'
4
15
  import { View } from '../View'
5
- import { TouchableFeedbackConfig, usePressableFeedback } from '../../utils'
16
+ import { usePressableFeedback } from '../../utils'
6
17
  import { Keyboard } from 'react-native'
18
+
7
19
  import { PressableRipple } from '../../modules/PressableRipple'
8
- import { AnyRecord, IJSX, StyledComponentProps, StyledComponentWithProps } from '@codeleap/styles'
9
- import { TouchableProps } from './types'
10
- import { MobileStyleRegistry } from '../../Registry'
11
- import { useStylesFor } from '../../hooks'
20
+ export type TouchableProps =
21
+ Omit<
22
+ PressableProps,
23
+ 'onPress' | 'children' | 'style'
24
+ > & {
25
+ variants?: ComponentVariants<typeof TouchablePresets>['variants']
26
+ component?: any
27
+ ref?: React.Ref<RNView>
28
+ debugName: string
29
+ activeOpacity?: number
30
+ debugComponent?: string
31
+ onPress?: AnyFunction
32
+ noFeedback?: boolean
33
+ debounce?: number
34
+ leadingDebounce?: boolean
35
+ styles?: StylesOf<TouchableComposition>
36
+ setPressed?: (param: boolean) => void
37
+ rippleDisabled?: boolean
38
+ children?: React.ReactNode
39
+ style?: StyleProp<ViewStyle>
40
+ analyticsEnabled?: boolean
41
+ analyticsName?: string
42
+ analyticsData?: Record<string, any>
43
+ dismissKeyboard?: boolean
44
+ }
12
45
 
13
46
  export * from './styles'
14
- export * from './types'
15
-
16
- export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref) => {
47
+ const defaultProps: Partial<TouchableProps> = {
48
+ variants: [],
49
+ debounce: 500,
50
+ noFeedback: false,
51
+ rippleDisabled: false,
52
+ analyticsEnabled: false,
53
+ analyticsName: null,
54
+ analyticsData: {},
55
+ dismissKeyboard: true,
56
+ }
57
+ const _Touchable = forwardRef<
58
+ RNView,
59
+ TouchableProps
60
+ >((touchableProps, ref) => {
17
61
  const {
62
+ variants = [],
18
63
  children,
19
64
  onPress,
20
65
  style,
@@ -23,6 +68,7 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
23
68
  debounce,
24
69
  leadingDebounce,
25
70
  noFeedback,
71
+ styles,
26
72
  setPressed,
27
73
  rippleDisabled,
28
74
  analyticsEnabled,
@@ -31,7 +77,7 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
31
77
  dismissKeyboard,
32
78
  ...props
33
79
  } = {
34
- ...Touchable.defaultProps,
80
+ ...defaultProps,
35
81
  ...touchableProps,
36
82
  }
37
83
 
@@ -45,17 +91,26 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
45
91
  }
46
92
  })
47
93
 
48
- const styles = useStylesFor(Touchable.styleRegistryName, style)
94
+ const variantStyles = useDefaultComponentStyle<'u:Touchable', typeof TouchablePresets>('u:Touchable', {
95
+ variants,
96
+ transform: StyleSheet.flatten,
97
+ rootElement: 'wrapper',
98
+ styles,
99
+ })
49
100
 
50
- const { logger } = useGlobalContext()
101
+ const { logger } = useCodeleapContext()
51
102
 
52
103
  const press = () => {
53
- if (!onPress) return
54
-
104
+ if (!onPress) {
105
+ logger.warn('No onPress passed to touchable', {
106
+ touchableProps,
107
+ }, 'User Interaction')
108
+ return
109
+ }
55
110
  const _onPress = () => {
56
111
  logger.log(
57
112
  `<${debugComponent || 'Touchable'}/> pressed`,
58
- debugName,
113
+ debugName || variants,
59
114
  'User interaction',
60
115
  )
61
116
  if (dismissKeyboard) {
@@ -68,9 +123,8 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
68
123
  }
69
124
  }
70
125
 
71
- onPress()
126
+ onPress && onPress()
72
127
  }
73
-
74
128
  if (TypeGuards.isNumber(debounce)) {
75
129
  if (pressed.current) {
76
130
  return
@@ -85,9 +139,10 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
85
139
  } else {
86
140
  _onPress()
87
141
  }
142
+
88
143
  }
89
144
 
90
- const _styles = StyleSheet.flatten([styles?.wrapper, props?.disabled && styles?.['wrapper:disabled']])
145
+ const _styles = StyleSheet.flatten([variantStyles.wrapper, props?.disabled && variantStyles['wrapper:disabled'], style])
91
146
 
92
147
  const disableFeedback = !onPress || noFeedback
93
148
 
@@ -95,7 +150,7 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
95
150
  hightlightPropertyIn: 'backgroundColor',
96
151
  hightlightPropertyOut: 'backgroundColor',
97
152
  disabled: disableFeedback,
98
- feedbackConfig: styles?.feedback as TouchableFeedbackConfig,
153
+ feedbackConfig: variantStyles?.feedback,
99
154
  })
100
155
 
101
156
  const Wrapper = View
@@ -110,6 +165,7 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
110
165
  'bottom!',
111
166
  'position!',
112
167
  'transform!',
168
+ // 'flex!',
113
169
  ]
114
170
 
115
171
  const radiusKey = [
@@ -137,7 +193,6 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
137
193
  return key.startsWith(k)
138
194
  }
139
195
  }
140
-
141
196
  Object.entries(_styles).forEach(([key, value]) => {
142
197
  if (radiusKey.some(k => match(k, key))) {
143
198
  wrapperStyle[key] = value
@@ -156,12 +211,10 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
156
211
  pressableStyle[key] = value
157
212
  }
158
213
  })
159
-
160
214
  if (wrapperStyle.position === 'absolute') {
161
215
  pressableStyle.width = '100%'
162
216
  pressableStyle.height = '100%'
163
217
  }
164
-
165
218
  wrapperStyle.overflow = 'visible'
166
219
 
167
220
  return {
@@ -181,12 +234,15 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
181
234
  const disableRipple = disableFeedback || rippleDisabled || Platform.OS !== 'android'
182
235
 
183
236
  return (
184
- <Wrapper style={wrapperStyle} hitSlop={hitSlop}>
237
+ <Wrapper style={[wrapperStyle]} hitSlop={hitSlop}>
185
238
  {!disableRipple ? (
186
239
  <PressableRipple
187
240
  onPress={press}
241
+ style={[
242
+ pressableStyle,
243
+ variantStyles.pressable,
244
+ ]}
188
245
  {...props}
189
- style={[pressableStyle, styles?.pressable]}
190
246
  rippleFades={false}
191
247
  rippleDuration={350}
192
248
  rippleOpacity={0.1}
@@ -203,7 +259,7 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
203
259
  style={({ pressed }) => ([
204
260
  pressableStyle,
205
261
  getFeedbackStyle(pressed),
206
- styles?.pressable,
262
+ variantStyles.pressable,
207
263
  ])}
208
264
  {...props}
209
265
  ref={ref}
@@ -213,23 +269,10 @@ export const Touchable = forwardRef<RNView, TouchableProps>((touchableProps, ref
213
269
  )}
214
270
  </Wrapper>
215
271
  )
216
- }) as StyledComponentWithProps<TouchableProps>
217
-
218
- Touchable.styleRegistryName = 'Touchable'
219
- Touchable.elements = ['wrapper', 'feedback', 'pressable']
220
- Touchable.rootElement = 'wrapper'
272
+ })
221
273
 
222
- Touchable.withVariantTypes = <S extends AnyRecord>(styles: S) => {
223
- return Touchable as (props: StyledComponentProps<TouchableProps, typeof styles>) => IJSX
274
+ export const Touchable = _Touchable as ((props: TouchableProps) => JSX.Element) & {
275
+ defaultProps: Partial<TouchableProps>
224
276
  }
225
277
 
226
- Touchable.defaultProps = {
227
- debounce: 500,
228
- noFeedback: false,
229
- rippleDisabled: false,
230
- analyticsEnabled: false,
231
- analyticsName: null,
232
- dismissKeyboard: true,
233
- } as Partial<TouchableProps>
234
-
235
- MobileStyleRegistry.registerComponent(Touchable)
278
+ Touchable.defaultProps = defaultProps
@@ -1,3 +1,4 @@
1
+ import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
1
2
  import { StylesOf } from '../../types'
2
3
  import { TouchableFeedbackConfig } from '../../utils'
3
4
 
@@ -6,3 +7,11 @@ export type TouchableComposition = 'wrapper' | 'wrapper:disabled' | 'feedback' |
6
7
  export type TouchableStylesGen<TCSS = any> = StylesOf<Exclude<TouchableComposition, 'feedback'>> & {
7
8
  feedback?: TouchableFeedbackConfig
8
9
  }
10
+
11
+ const createTouchableStyle = createDefaultVariantFactory<
12
+ TouchableComposition,
13
+ TouchableStylesGen
14
+ >()
15
+
16
+ export const TouchablePresets = includePresets((styles) => createTouchableStyle(() => ({ wrapper: styles, pressable: styles })))
17
+