@codeleap/mobile 2.3.0 → 2.3.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 (126) hide show
  1. package/dist/components/Button/index.d.ts +0 -1
  2. package/dist/components/Button/index.js +5 -12
  3. package/dist/components/Button/index.js.map +1 -1
  4. package/dist/components/List/styles.js +1 -1
  5. package/dist/components/List/styles.js.map +1 -1
  6. package/dist/components/Touchable/index.js +11 -9
  7. package/dist/components/Touchable/index.js.map +1 -1
  8. package/dist/utils/theme.d.ts +1 -0
  9. package/dist/utils/theme.js +7 -2
  10. package/dist/utils/theme.js.map +1 -1
  11. package/package.json +1 -1
  12. package/src/components/ActionIcon/index.tsx +32 -0
  13. package/src/components/ActionIcon/styles.ts +97 -0
  14. package/src/components/ActivityIndicator/index.tsx +50 -0
  15. package/src/components/ActivityIndicator/styles.ts +68 -0
  16. package/src/components/Animated.tsx +34 -0
  17. package/src/components/AutoComplete/index.tsx +163 -0
  18. package/src/components/AutoComplete/styles.ts +44 -0
  19. package/src/components/Backdrop/index.tsx +48 -0
  20. package/src/components/Backdrop/styles.ts +33 -0
  21. package/src/components/Button/index.tsx +154 -0
  22. package/src/components/Button/styles.ts +129 -0
  23. package/src/components/Calendar/index.tsx +65 -0
  24. package/src/components/Calendar/style.ts +35 -0
  25. package/src/components/Calendar/types.ts +102 -0
  26. package/src/components/Checkbox/index.tsx +91 -0
  27. package/src/components/Checkbox/styles.ts +81 -0
  28. package/src/components/ContentView/index.tsx +63 -0
  29. package/src/components/ContentView/styles.ts +24 -0
  30. package/src/components/Drawer/index.tsx +33 -0
  31. package/src/components/Drawer/styles.ts +43 -0
  32. package/src/components/EmptyPlaceholder/index.tsx +88 -0
  33. package/src/components/EmptyPlaceholder/styles.ts +58 -0
  34. package/src/components/FileInput/index.tsx +181 -0
  35. package/src/components/FileInput/styles.ts +15 -0
  36. package/src/components/Grid/index.tsx +117 -0
  37. package/src/components/Grid/styles.ts +11 -0
  38. package/src/components/Icon/index.tsx +69 -0
  39. package/src/components/Icon/styles.ts +57 -0
  40. package/src/components/Image/index.tsx +91 -0
  41. package/src/components/Image/styles.ts +20 -0
  42. package/src/components/ImageView/Spotlight.tsx +157 -0
  43. package/src/components/ImageView/component.tsx +38 -0
  44. package/src/components/ImageView/index.ts +2 -0
  45. package/src/components/InputLabel/index.tsx +38 -0
  46. package/src/components/InputLabel/styles.ts +19 -0
  47. package/src/components/List/PaginationIndicator.tsx +71 -0
  48. package/src/components/List/index.tsx +114 -0
  49. package/src/components/List/styles.ts +19 -0
  50. package/src/components/Modal/index.tsx +218 -0
  51. package/src/components/Modal/styles.ts +153 -0
  52. package/src/components/MultiSelect/index.tsx +138 -0
  53. package/src/components/MultiSelect/styles.ts +18 -0
  54. package/src/components/MultiSelect/types.ts +42 -0
  55. package/src/components/Navigation/Navigation.tsx +54 -0
  56. package/src/components/Navigation/constants.ts +8 -0
  57. package/src/components/Navigation/index.tsx +3 -0
  58. package/src/components/Navigation/types.ts +35 -0
  59. package/src/components/Navigation/utils.tsx +57 -0
  60. package/src/components/Pager/index.tsx +121 -0
  61. package/src/components/Pager/styles.ts +81 -0
  62. package/src/components/RadioInput/index.tsx +106 -0
  63. package/src/components/RadioInput/styles.ts +67 -0
  64. package/src/components/Scroll/index.tsx +124 -0
  65. package/src/components/Scroll/styles.ts +18 -0
  66. package/src/components/Sections/index.tsx +91 -0
  67. package/src/components/SegmentedControl/index.tsx +204 -0
  68. package/src/components/SegmentedControl/styles.ts +89 -0
  69. package/src/components/Select/index.tsx +167 -0
  70. package/src/components/Select/styles.ts +62 -0
  71. package/src/components/Select/types.ts +43 -0
  72. package/src/components/Slider/Mark.tsx +46 -0
  73. package/src/components/Slider/Thumb.tsx +29 -0
  74. package/src/components/Slider/index.tsx +130 -0
  75. package/src/components/Slider/styles.ts +76 -0
  76. package/src/components/Slider/types.ts +30 -0
  77. package/src/components/Switch/index.tsx +91 -0
  78. package/src/components/Switch/styles.ts +38 -0
  79. package/src/components/Text/index.tsx +97 -0
  80. package/src/components/Text/styles.ts +50 -0
  81. package/src/components/TextInput/index.tsx +319 -0
  82. package/src/components/TextInput/styles.ts +127 -0
  83. package/src/components/Touchable/index.tsx +174 -0
  84. package/src/components/Touchable/styles.ts +28 -0
  85. package/src/components/View/index.tsx +103 -0
  86. package/src/components/View/styles.ts +24 -0
  87. package/src/components/components.ts +42 -0
  88. package/src/components/defaultStyles.ts +62 -0
  89. package/src/components/legacy/Modal/index.tsx +163 -0
  90. package/src/components/legacy/Modal/styles.ts +125 -0
  91. package/src/components/legacy/Pager/index.tsx +242 -0
  92. package/src/components/legacy/Pager/styles.ts +51 -0
  93. package/src/components/legacy/index.ts +2 -0
  94. package/src/modules/documentPicker.ts +7 -0
  95. package/src/modules/fastImage.ts +2 -0
  96. package/src/modules/imageCropPicker.d.ts +497 -0
  97. package/src/modules/index.d.ts +682 -0
  98. package/src/modules/reactNavigation.ts +15 -0
  99. package/src/modules/textInputMask.ts +11 -0
  100. package/src/modules/types/documentPicker.d.ts +215 -0
  101. package/src/modules/types/fileTypes.ts +138 -0
  102. package/src/modules/types/textInputMask.ts +9 -0
  103. package/src/types/index.ts +1 -0
  104. package/src/types/utility.ts +9 -0
  105. package/src/utils/KeyboardAware/context.tsx +75 -0
  106. package/src/utils/KeyboardAware/index.ts +17 -0
  107. package/src/utils/KeyboardAware/keyboardHooks.ts +124 -0
  108. package/src/utils/KeyboardAware/lib/KeyboardAwareFlatList.ts +4 -0
  109. package/src/utils/KeyboardAware/lib/KeyboardAwareHOC.tsx +618 -0
  110. package/src/utils/KeyboardAware/lib/KeyboardAwareInterface.ts +13 -0
  111. package/src/utils/KeyboardAware/lib/KeyboardAwareScrollView.ts +6 -0
  112. package/src/utils/KeyboardAware/lib/KeyboardAwareSectionList.ts +6 -0
  113. package/src/utils/KeyboardAware/types.ts +159 -0
  114. package/src/utils/ModalManager/components.tsx +112 -0
  115. package/src/utils/ModalManager/context.tsx +260 -0
  116. package/src/utils/ModalManager/index.ts +16 -0
  117. package/src/utils/OSAlert.ts +180 -0
  118. package/src/utils/PermissionManager/context.tsx +302 -0
  119. package/src/utils/PermissionManager/index.ts +20 -0
  120. package/src/utils/PermissionManager/types.ts +24 -0
  121. package/src/utils/hooks.ts +163 -0
  122. package/src/utils/index.ts +11 -0
  123. package/src/utils/input.ts +51 -0
  124. package/src/utils/misc.ts +83 -0
  125. package/src/utils/notifications.ts +206 -0
  126. package/src/utils/theme.ts +58 -0
@@ -0,0 +1,89 @@
1
+ import { createDefaultVariantFactory, includePresets, StylesOf } from '@codeleap/common'
2
+ import { InputLabelComposition } from '../InputLabel'
3
+ import { TouchableStylesGen } from '../Touchable'
4
+
5
+ export type SegmentedControlStates = 'selected'
6
+
7
+ export type SegmentedControlComposition =
8
+ 'selectedBubble' |
9
+ 'wrapper' |
10
+ 'scroll' |
11
+ 'scrollContent' |
12
+ 'text' |
13
+ `text:${SegmentedControlStates}` |
14
+ 'button' |
15
+ 'buttonFeedback' |
16
+ `button:${SegmentedControlStates}` |
17
+ `label${Capitalize<InputLabelComposition>}`
18
+
19
+ export type SegmentedControlStylesGen<TCSS = any> =
20
+ StylesOf<
21
+ Exclude<SegmentedControlComposition, 'buttonFeedback'>
22
+ > & {
23
+ buttonFeedback?: TouchableStylesGen['feedback']
24
+ }
25
+
26
+ const createSegmentedControlStyle = createDefaultVariantFactory<
27
+ SegmentedControlComposition,
28
+ SegmentedControlStylesGen
29
+ >()
30
+
31
+ const presets = includePresets((style) => createSegmentedControlStyle(() => ({ scrollContent: style })))
32
+
33
+ export const SegmentedControlStyles = {
34
+ ...presets,
35
+ default: createSegmentedControlStyle((theme) => {
36
+
37
+ return {
38
+ buttonFeedback: {
39
+ type: 'opacity',
40
+ value: 0.5,
41
+ },
42
+ text: {
43
+ color: theme.colors.text,
44
+ },
45
+ 'text:selected': {
46
+ color: theme.colors.white,
47
+ },
48
+ scroll: {
49
+ height: theme.values.buttons.default.height,
50
+ // borderRadius: Theme.borderRadius.large,
51
+ },
52
+ scrollContent: {
53
+ // borderRadius: Theme.borderRadius.large,
54
+ ...theme.presets.row,
55
+ ...theme.spacing.paddingHorizontal(2),
56
+ ...theme.presets.alignStretch,
57
+ },
58
+ button: {
59
+ backgroundColor: 'transparent',
60
+ ...theme.presets.alignCenter,
61
+ ...theme.presets.justifyCenter,
62
+
63
+ borderRadius: theme.borderRadius.large,
64
+ ...theme.spacing.padding(1),
65
+ minHeight: '100%',
66
+
67
+ },
68
+ selectedBubble: {
69
+ position: 'absolute',
70
+ zIndex: -1,
71
+ ...theme.spacing.padding(2),
72
+ // maxHeight: 50,
73
+ // minHeight: 50,
74
+ top: 0,
75
+ bottom: 0,
76
+ borderRadius: theme.borderRadius.large,
77
+ backgroundColor: theme.colors.primary,
78
+ },
79
+ wrapper: {
80
+ borderRadius: theme.borderRadius.large,
81
+ backgroundColor: theme.colors.backgroundSecondary,
82
+ ...theme.presets.row,
83
+ position: 'relative',
84
+ },
85
+
86
+ }
87
+
88
+ }),
89
+ }
@@ -0,0 +1,167 @@
1
+ import { IconPlaceholder,
2
+ getNestedStylesByKey,
3
+ useDefaultComponentStyle,
4
+ TypeGuards } from '@codeleap/common'
5
+ import React, { useMemo } from 'react'
6
+ import { StyleSheet } from 'react-native'
7
+ import { List } from '../List'
8
+ import { Text } from '../Text'
9
+ import { TextInput } from '../TextInput'
10
+ import { Touchable } from '../Touchable'
11
+ import { SelectStyles } from './styles'
12
+ import { CustomSelectProps } from './types'
13
+ import { ModalManager } from '../../utils'
14
+ import { Icon } from '../Icon'
15
+
16
+ export const SelectItem = ({ item, icon = null, isSelected, styles, onPress }) => {
17
+ return <Touchable style={[
18
+ styles.itemWrapper,
19
+ isSelected && styles['itemWrapper:selected'],
20
+ ]} onPress={onPress} debugName={`Select ${item.value}`}>
21
+ <Text text={item.label} style={[
22
+ styles.itemText,
23
+ isSelected && styles['itemText:selected'],
24
+ ]}/>
25
+ {icon ? <Icon name={icon} style={[styles?.itemIcon, isSelected && styles?.['itemIcon:selected']]}/> : null}
26
+ </Touchable>
27
+ }
28
+
29
+ export * from './styles'
30
+ export const Select = <T extends string|number = string>(selectProps:CustomSelectProps<T>) => {
31
+ const {
32
+ value,
33
+ onValueChange,
34
+ label,
35
+ styles = {},
36
+ options,
37
+ style,
38
+ variants,
39
+ renderItem,
40
+ closeOnSelect = true,
41
+ listProps,
42
+ placeholder = 'Select',
43
+ arrowIconName = 'selectArrow',
44
+ clearIconName = 'close',
45
+ clearable = false,
46
+ selectedIcon = 'selectMarker',
47
+ inputProps = {},
48
+ hideInput = false,
49
+
50
+ ...drawerProps
51
+ } = selectProps
52
+
53
+ const variantStyles = useDefaultComponentStyle<'u:Select', typeof SelectStyles>('u:Select', {
54
+ transform: StyleSheet.flatten,
55
+ rootElement: 'inputWrapper',
56
+ styles,
57
+ variants,
58
+ })
59
+
60
+ const inputStyles = useMemo(
61
+ () => getNestedStylesByKey('input', variantStyles),
62
+ [variantStyles],
63
+ )
64
+
65
+ const close = () => drawerProps?.toggle?.()
66
+
67
+ const select = (value) => {
68
+
69
+ onValueChange(value)
70
+ if (closeOnSelect) {
71
+ close?.()
72
+ }
73
+ }
74
+
75
+ const selectedLabel:string = useMemo(() => {
76
+ const current = options.find(o => o.value === value)
77
+
78
+ const display = current?.label ?? placeholder
79
+
80
+ return TypeGuards.isString(display) ? display : ''
81
+ }, [value, placeholder, options])
82
+ const Item = renderItem || SelectItem
83
+
84
+ const renderListItem = ({ item }) => {
85
+ return <Item
86
+ isSelected={value === item.value}
87
+ item={item}
88
+ onPress={() => select(item.value)}
89
+ icon={selectedIcon}
90
+ styles={variantStyles}
91
+ />
92
+ }
93
+ const isEmpty = TypeGuards.isNil(value)
94
+ const showClearIcon = !isEmpty && clearable
95
+
96
+ const inputIcon = showClearIcon ? clearIconName : arrowIconName
97
+
98
+ const onPressInputIcon = () => {
99
+ if (showClearIcon) {
100
+ onValueChange(null)
101
+ } else {
102
+ close?.()
103
+ }
104
+
105
+ }
106
+
107
+ return <>
108
+ {
109
+ !hideInput && (
110
+ <TextInput
111
+ caretHidden
112
+ value={selectedLabel}
113
+ rightIcon={{
114
+ icon: inputIcon as IconPlaceholder,
115
+ onPress: onPressInputIcon,
116
+ noFeedback: true,
117
+ }}
118
+ editable={false}
119
+ touchableWrapper
120
+ onPress={close}
121
+ wrapperProps={{
122
+ debugName: 'Select',
123
+
124
+ }}
125
+ pointerEvents={'none'}
126
+ label={label}
127
+ debugName={'Select input'}
128
+ styles={inputStyles}
129
+ style={style}
130
+ {...inputProps}
131
+ />
132
+ )
133
+ }
134
+
135
+ <ModalManager.Drawer
136
+ scroll={false}
137
+ title={label}
138
+ keyboardAware={{
139
+ baseStyleProp: 'style',
140
+ adapt: 'paddingBottom',
141
+ enabled: true,
142
+ enableOnAndroid: true,
143
+ }}
144
+ {...drawerProps}
145
+ styles={variantStyles}
146
+ >
147
+ <List<CustomSelectProps<any>['options']>
148
+ data={options}
149
+ style={variantStyles.list}
150
+ contentContainerStyle={variantStyles.listContent}
151
+ keyExtractor={(i) => i.value}
152
+ renderItem={renderListItem}
153
+ keyboardAware={{
154
+ baseStyleProp: 'style',
155
+ adapt: 'maxHeight',
156
+ enabled: true,
157
+ enableOnAndroid: true,
158
+ }}
159
+ {...listProps}
160
+ />
161
+ </ModalManager.Drawer>
162
+
163
+ </>
164
+ }
165
+
166
+ export * from './styles'
167
+ export * from './types'
@@ -0,0 +1,62 @@
1
+ import { createDefaultVariantFactory, TextInputComposition } from '@codeleap/common'
2
+ import { DrawerComposition, DrawerStyles } from '../Drawer'
3
+ type ItemStates = '' | ':selected'
4
+ export type SelectComposition =
5
+ DrawerComposition |
6
+ `input${TextInputComposition}` |
7
+ 'list' |
8
+ 'listContent' |
9
+ `itemWrapper${ItemStates}` |
10
+ `itemText${ItemStates}` |
11
+ 'scroll' |
12
+ 'scrollContent' |
13
+ `itemIcon${ItemStates}`
14
+
15
+ const createSelectStyle = createDefaultVariantFactory<SelectComposition>()
16
+
17
+ export const SelectStyles = {
18
+ ...DrawerStyles,
19
+ default: createSelectStyle((theme) => {
20
+ const defaultStyle = DrawerStyles.default(theme)
21
+
22
+ return {
23
+ ...defaultStyle,
24
+ box: {
25
+ ...theme.spacing.paddingHorizontal(0),
26
+
27
+ },
28
+ itemWrapper: {
29
+ ...theme.presets.row,
30
+ ...theme.presets.justifySpaceBetween,
31
+ ...theme.presets.alignCenter,
32
+ ...theme.spacing.padding(1.4),
33
+ height: 50,
34
+ },
35
+ 'itemWrapper:selected': {
36
+ backgroundColor: theme.colors.primary,
37
+ },
38
+ 'itemText:selected': {
39
+ color: theme.colors.white,
40
+
41
+ },
42
+ 'itemIcon:selected': {
43
+ color: theme.colors.white,
44
+ ...theme.sized(3),
45
+ },
46
+ itemIcon: {
47
+ width: 0,
48
+ height: 0,
49
+ },
50
+ list: {
51
+ height: 'auto',
52
+
53
+ maxHeight: theme.values.window.height * 0.75,
54
+
55
+ },
56
+ // listContent: {
57
+ // paddingBottom: theme.values.safeAreaTop,
58
+ // },
59
+
60
+ }
61
+ }),
62
+ }
@@ -0,0 +1,43 @@
1
+ import {
2
+ ComponentVariants,
3
+ FormTypes,
4
+ IconPlaceholder,
5
+ } from '@codeleap/common'
6
+ import { StylesOf } from '../../types/utility'
7
+ import { GetKeyboardAwarePropsOptions } from '../../utils'
8
+ import { DrawerProps } from '../Drawer'
9
+ import { FlatListProps } from '../List'
10
+ import { TextInputProps } from '../TextInput'
11
+ import { SelectComposition, SelectStyles } from './styles'
12
+
13
+ export type SelectRenderFNProps<T> = & {
14
+ styles: StylesOf<SelectComposition>
15
+ onPress: () => void
16
+ isSelected?: boolean
17
+ item: FormTypes.Options<T>[number]
18
+ }
19
+
20
+ export type SelectRenderFN<T> = (props: SelectRenderFNProps<T>) => JSX.Element
21
+
22
+ type SelectDrawerProps = Omit<DrawerProps, 'variants' | 'styles'>
23
+
24
+ export type CustomSelectProps<T> = SelectDrawerProps & {
25
+ value: T
26
+ placeholder?: FormTypes.Label
27
+ label?: FormTypes.Label
28
+ options?: FormTypes.Options<T>
29
+ onValueChange?: (value: T) => void
30
+ renderItem?: SelectRenderFN<T>
31
+ styles?: StylesOf<SelectComposition>
32
+ style?: any
33
+ hideInput?: boolean
34
+ selectedIcon?: IconPlaceholder
35
+ arrowIconName?: IconPlaceholder
36
+ closeOnSelect?: boolean
37
+ inputProps?: Partial<TextInputProps>
38
+ listProps?: Partial<FlatListProps>
39
+ clearable?: boolean
40
+ clearIconName?: IconPlaceholder
41
+ keyboardAware?: GetKeyboardAwarePropsOptions
42
+ } & ComponentVariants<typeof SelectStyles>
43
+
@@ -0,0 +1,46 @@
1
+ import React from 'react'
2
+ import { StyleProp } from 'react-native'
3
+ import { Text } from '../Text'
4
+ import { View } from '../View'
5
+ import { SliderMarkProps } from './types'
6
+ export const SliderMark: React.FC<SliderMarkProps> = ({
7
+ index,
8
+ sliderProps,
9
+ styles,
10
+ variantStyles,
11
+ }) => {
12
+ const { labels = [], showMarks } = sliderProps
13
+
14
+ const l = labels?.[index] || ''
15
+
16
+ const isFirst = index === 0
17
+ const isLast = index === labels.length - 1
18
+
19
+ const centerAdjustWord = -(l.length * 2)
20
+
21
+ const markStyles: StyleProp<any> = {}
22
+
23
+ const labelStyles: StyleProp<any> = {}
24
+
25
+ if (!isFirst && !isLast) {
26
+ labelStyles.left = centerAdjustWord
27
+ }
28
+
29
+ if (isLast) {
30
+ labelStyles.right = -20
31
+ markStyles.right = -10
32
+ }
33
+ return (
34
+ <>
35
+ {showMarks ? (
36
+ <View style={[markStyles, variantStyles.mark, styles.mark]} />
37
+ ) : null}
38
+ {l ? (
39
+ <Text
40
+ style={[labelStyles, variantStyles.trackLabels, styles.trackLabels]}
41
+ text={l}
42
+ />
43
+ ) : null}
44
+ </>
45
+ )
46
+ }
@@ -0,0 +1,29 @@
1
+ import React from 'react'
2
+ import { StyleSheet } from 'react-native'
3
+ import { Text } from '../Text'
4
+ import { View } from '../View'
5
+ export const ThumbTooltip = ({ children, visible, styles, variantStyles }) => {
6
+ return (
7
+ <View
8
+ style={[
9
+ StyleSheet.flatten([variantStyles.tooltip, styles.tooltip]),
10
+ visible
11
+ ? StyleSheet.flatten([
12
+ variantStyles['tooltip:visible'],
13
+ styles['tooltip:visible'],
14
+ ])
15
+ : StyleSheet.flatten([
16
+ variantStyles['tooltip:hidden'],
17
+ styles['tooltip:hidden'],
18
+ ]),
19
+ ]}
20
+ >
21
+ <Text
22
+ style={[variantStyles.tooltipText, styles.tooltipText]}
23
+ text={children}
24
+ />
25
+ <View style={[variantStyles.tooltipArrow, styles.tooltipArrow]} />
26
+ </View>
27
+ )
28
+ }
29
+
@@ -0,0 +1,130 @@
1
+ import { SliderMark } from './Mark'
2
+ import { ThumbTooltip } from './Thumb'
3
+ import * as React from 'react'
4
+ import { Slider as RNSlider } from '@miblanchard/react-native-slider'
5
+
6
+ import { useRef } from 'react'
7
+ import { StyleSheet } from 'react-native'
8
+ import { View } from '../View'
9
+ import {
10
+ getNestedStylesByKey,
11
+ useDefaultComponentStyle,
12
+ } from '@codeleap/common'
13
+
14
+ import { SliderProps } from './types'
15
+ import { InputLabel } from '../InputLabel'
16
+ import { SliderStyles } from './styles'
17
+
18
+ export * from './styles'
19
+
20
+ export const Slider: React.FC<SliderProps> = (sliderProps) => {
21
+ const [tooltipVisible, setTooltipVisible] = React.useState(false)
22
+
23
+ const {
24
+ debounce,
25
+ onValueChange,
26
+ labels,
27
+ value,
28
+ label,
29
+ valueOverThumb,
30
+ formatTooltip,
31
+ styles = {},
32
+ style,
33
+ tooltipVisibilityWindow = 830,
34
+ variants,
35
+ ...props
36
+ } = sliderProps
37
+
38
+ const changeDebounce = typeof debounce === 'number' ? debounce : 100
39
+
40
+ const debounceTimeout = useRef(null)
41
+ const toggleTooltipTimeout = useRef(null)
42
+ const valueRef = useRef(value)
43
+
44
+ const variantStyles = useDefaultComponentStyle<'u:Slider', typeof SliderStyles>('u:Slider', {
45
+ variants,
46
+ styles,
47
+ transform: StyleSheet.flatten,
48
+ })
49
+
50
+ function setValue() {
51
+ onValueChange(valueRef.current)
52
+ }
53
+
54
+ function onChange(val) {
55
+ let eventValue = val
56
+
57
+ if (Array.isArray(val) && typeof value === 'number') {
58
+ eventValue = val[0]
59
+ }
60
+
61
+ if (eventValue === value) return
62
+
63
+ valueRef.current = eventValue as number
64
+
65
+ if (debounceTimeout.current) clearTimeout(debounceTimeout.current)
66
+
67
+ debounceTimeout.current = setTimeout(() => {
68
+ setValue()
69
+ }, changeDebounce)
70
+ }
71
+
72
+ return (
73
+ <View style={[variantStyles.wrapper, style]}>
74
+ <InputLabel label={label} styles={getNestedStylesByKey('label', variantStyles)} />
75
+ <RNSlider
76
+ value={value}
77
+ onSlidingStart={() => {
78
+ if (toggleTooltipTimeout.current) { clearTimeout(toggleTooltipTimeout.current) }
79
+
80
+ setTooltipVisible(true)
81
+ }}
82
+ onSlidingComplete={() => {
83
+ toggleTooltipTimeout.current = setTimeout(
84
+ () => setTooltipVisible(false),
85
+ tooltipVisibilityWindow,
86
+ )
87
+ }}
88
+ onValueChange={onChange}
89
+ renderAboveThumbComponent={(idx) => {
90
+ if (!valueOverThumb) return null
91
+ const thisValue = Array.isArray(value) ? value[idx] : value
92
+ return (
93
+ <ThumbTooltip
94
+ visible={tooltipVisible}
95
+ variantStyles={variantStyles}
96
+ styles={styles}
97
+ >
98
+ {formatTooltip ? formatTooltip(thisValue) : thisValue.toString()}
99
+ </ThumbTooltip>
100
+ )
101
+ }}
102
+ renderTrackMarkComponent={(idx) => (
103
+ <SliderMark
104
+ index={idx}
105
+ sliderProps={sliderProps}
106
+ styles={styles}
107
+ variantStyles={variantStyles}
108
+ />
109
+ )}
110
+ maximumValue={labels ? labels.length - 1 : 10}
111
+ trackMarks={labels ? Object.keys(labels).map((z) => parseInt(z)) : []}
112
+ containerStyle={
113
+ [variantStyles.inputContainer] as any
114
+ }
115
+ thumbStyle={
116
+ StyleSheet.flatten([variantStyles.handle]) as any
117
+ }
118
+ trackStyle={[variantStyles.track] as any}
119
+ minimumTrackTintColor={
120
+ StyleSheet.flatten([
121
+ variantStyles.selectedTrack,
122
+
123
+ ])?.backgroundColor
124
+ }
125
+ {...props}
126
+ />
127
+ </View>
128
+ )
129
+ }
130
+
@@ -0,0 +1,76 @@
1
+ import { assignTextStyle, createDefaultVariantFactory, includePresets } from '@codeleap/common'
2
+ import { InputLabelComposition } from '../InputLabel'
3
+
4
+ export type SliderComposition =
5
+ | 'wrapper'
6
+ | 'handle'
7
+ | 'track'
8
+ | `label${Capitalize<InputLabelComposition>}`
9
+ | 'selectedTrack'
10
+ | 'inputContainer'
11
+ | 'tooltip'
12
+ | 'tooltip:visible'
13
+ | 'tooltip:hidden'
14
+ | 'trackLabels'
15
+ | 'mark'
16
+ | 'tooltipArrow'
17
+ | 'tooltipText'
18
+
19
+ const createSliderStyle = createDefaultVariantFactory<SliderComposition>()
20
+
21
+ const presets = includePresets((styles) => createSliderStyle(() => ({ wrapper: styles })),
22
+ )
23
+
24
+ export const SliderStyles = {
25
+ ...presets,
26
+ default: createSliderStyle((theme) => ({
27
+ wrapper: {},
28
+ handle: {
29
+ backgroundColor: theme.colors.primary,
30
+ },
31
+ selectedTrack: {
32
+ backgroundColor: theme.colors.primary,
33
+ },
34
+ track: {
35
+ backgroundColor: theme.colors.gray,
36
+ },
37
+ tooltip: {
38
+ padding: theme.spacing.value(0.5),
39
+ backgroundColor: theme.colors.primary,
40
+ position: 'relative',
41
+ borderRadius: theme.borderRadius.small,
42
+ },
43
+ 'tooltip:visible': {
44
+ opacity: 1,
45
+ },
46
+ 'tooltip:hidden': {
47
+ opacity: 0,
48
+ },
49
+ mark: {
50
+ position: 'absolute',
51
+ backgroundColor: theme.colors.primary,
52
+ borderRadius: 29,
53
+ height: 10,
54
+ width: 10,
55
+ top: -5,
56
+ },
57
+ trackLabels: {
58
+ position: 'absolute',
59
+ top: 8,
60
+ ...assignTextStyle('p3')(theme).text,
61
+ },
62
+ tooltipArrow: {
63
+ height: 6,
64
+ width: 6,
65
+ position: 'absolute',
66
+ backgroundColor: theme.colors.primary,
67
+ transform: [{ rotate: '45deg' }],
68
+ bottom: -3,
69
+ left: '50%',
70
+ },
71
+ tooltipText: {
72
+ color: theme.colors.white,
73
+ ...assignTextStyle('p3')(theme).text,
74
+ },
75
+ })),
76
+ }
@@ -0,0 +1,30 @@
1
+ import { ComponentVariants, Form } from '@codeleap/common'
2
+
3
+ import {
4
+ SliderComposition, SliderStyles,
5
+ } from './styles'
6
+
7
+ import { SliderProps as RNSliderProps } from '@miblanchard/react-native-slider/lib/types'
8
+ import { StylesOf } from '../../types'
9
+ import { ViewProps } from '../View'
10
+ export type SliderProps = Partial<Omit<RNSliderProps, 'value' | 'onValueChange'>> & {
11
+ debounce?: number
12
+ labels: string[]
13
+ value: number
14
+ valueOverThumb?: boolean
15
+ showMarks?: boolean
16
+ onValueChange: (val: number) => void
17
+ label: Form.Label
18
+ formatTooltip?: (val: number) => React.ReactNode
19
+ variants?: ComponentVariants<typeof SliderStyles>['variants']
20
+ styles?: StylesOf<SliderComposition>
21
+ style?: ViewProps['style']
22
+ tooltipVisibilityWindow?: number
23
+ }
24
+
25
+ export type SliderMarkProps = {
26
+ sliderProps: SliderProps
27
+ index: number
28
+ styles: SliderProps['styles']
29
+ variantStyles: SliderProps['styles']
30
+ }