@codeleap/web 2.4.7 → 3.1.1
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 +20 -19
- package/src/components/ActionIcon/index.tsx +59 -0
- package/src/components/ActionIcon/styles.ts +9 -0
- package/src/components/ActivityIndicator/index.tsx +78 -0
- package/src/components/ActivityIndicator/styles.ts +11 -0
- package/src/components/Button/index.tsx +125 -0
- package/src/components/Button/styles.ts +22 -0
- package/src/components/Checkbox/index.tsx +138 -0
- package/src/components/Checkbox/styles.ts +20 -0
- package/src/components/Collapse/index.tsx +87 -0
- package/src/components/Collapse/styles.ts +8 -0
- package/src/components/Drawer/index.tsx +148 -0
- package/src/components/Drawer/styles.ts +8 -0
- package/src/components/FileInput.tsx +51 -0
- package/src/components/Icon/index.tsx +53 -0
- package/src/components/Icon/styles.ts +9 -0
- package/src/components/InputBase/index.tsx +104 -0
- package/src/components/InputBase/styles.ts +167 -0
- package/src/components/InputBase/types.ts +28 -0
- package/src/components/InputBase/utils.ts +41 -0
- package/src/components/Link/index.tsx +69 -0
- package/src/components/Link/styles.ts +11 -0
- package/src/components/List/index.tsx +103 -0
- package/src/components/List/styles.ts +8 -0
- package/src/components/LoadingOverlay/index.tsx +34 -0
- package/src/components/LoadingOverlay/styles.ts +12 -0
- package/src/components/Modal/index.tsx +189 -0
- package/src/components/Modal/styles.ts +26 -0
- package/src/components/NumberIncrement/index.tsx +292 -0
- package/src/components/NumberIncrement/styles.ts +15 -0
- package/src/components/Overlay/index.tsx +42 -0
- package/src/components/Overlay/styles.ts +8 -0
- package/src/components/RadioInput/index.tsx +155 -0
- package/src/components/RadioInput/styles.ts +14 -0
- package/src/components/Scroll/index.tsx +29 -0
- package/src/components/Scroll/styles.ts +8 -0
- package/src/components/Select/index.tsx +438 -0
- package/src/components/Select/styles.ts +179 -0
- package/src/components/Select/types.ts +100 -0
- package/src/components/Slider/index.tsx +303 -0
- package/src/components/Slider/styles.ts +11 -0
- package/src/components/Switch/index.tsx +128 -0
- package/src/components/Switch/styles.ts +20 -0
- package/src/components/Text/index.tsx +62 -0
- package/src/components/Text/styles.ts +9 -0
- package/src/components/TextInput/index.tsx +253 -0
- package/src/components/TextInput/mask.tsx +165 -0
- package/src/components/TextInput/styles.ts +15 -0
- package/src/components/Tooltip/index.tsx +155 -0
- package/src/components/Tooltip/styles.ts +9 -0
- package/src/components/Touchable/index.tsx +72 -0
- package/src/components/Touchable/styles.ts +11 -0
- package/src/components/View/index.tsx +94 -0
- package/src/components/View/styles.ts +8 -0
- package/src/components/components.ts +29 -0
- package/src/components/defaultStyles.ts +51 -0
- package/src/index.ts +6 -0
- package/src/lib/OSAlert.tsx +190 -0
- package/src/lib/Toast.ts +23 -0
- package/src/lib/hooks.ts +340 -0
- package/src/lib/index.ts +2 -0
- package/src/lib/logger.ts +13 -0
- package/src/lib/utils/cookies.ts +13 -0
- package/src/lib/utils/index.ts +4 -0
- package/src/lib/utils/pollyfils/scroll.ts +65 -0
- package/src/lib/utils/stopPropagation.ts +15 -0
- package/src/types/index.ts +1 -0
- package/src/types/utility.ts +3 -0
- package/dist/components/ActivityIndicator/index.d.ts +0 -12
- package/dist/components/ActivityIndicator/index.js +0 -57
- package/dist/components/ActivityIndicator/index.js.map +0 -1
- package/dist/components/ActivityIndicator/styles.d.ts +0 -53
- package/dist/components/ActivityIndicator/styles.js +0 -22
- package/dist/components/ActivityIndicator/styles.js.map +0 -1
- package/dist/components/Button.d.ts +0 -18
- package/dist/components/Button.js +0 -67
- package/dist/components/Button.js.map +0 -1
- package/dist/components/CenterWrapper.d.ts +0 -7
- package/dist/components/CenterWrapper.js +0 -28
- package/dist/components/CenterWrapper.js.map +0 -1
- package/dist/components/Checkbox/index.d.ts +0 -12
- package/dist/components/Checkbox/index.js +0 -58
- package/dist/components/Checkbox/index.js.map +0 -1
- package/dist/components/Checkbox/styles.d.ts +0 -53
- package/dist/components/Checkbox/styles.js +0 -64
- package/dist/components/Checkbox/styles.js.map +0 -1
- package/dist/components/Collapse.d.ts +0 -20
- package/dist/components/Collapse.js +0 -68
- package/dist/components/Collapse.js.map +0 -1
- package/dist/components/ContentView.d.ts +0 -10
- package/dist/components/ContentView.js +0 -52
- package/dist/components/ContentView.js.map +0 -1
- package/dist/components/Drawer.d.ts +0 -23
- package/dist/components/Drawer.js +0 -73
- package/dist/components/Drawer.js.map +0 -1
- package/dist/components/FileInput.d.ts +0 -8
- package/dist/components/FileInput.js +0 -69
- package/dist/components/FileInput.js.map +0 -1
- package/dist/components/HorizontalScroll.d.ts +0 -3
- package/dist/components/HorizontalScroll.js +0 -42
- package/dist/components/HorizontalScroll.js.map +0 -1
- package/dist/components/Icon.d.ts +0 -8
- package/dist/components/Icon.js +0 -55
- package/dist/components/Icon.js.map +0 -1
- package/dist/components/Link.d.ts +0 -7
- package/dist/components/Link.js +0 -63
- package/dist/components/Link.js.map +0 -1
- package/dist/components/List.d.ts +0 -18
- package/dist/components/List.js +0 -52
- package/dist/components/List.js.map +0 -1
- package/dist/components/Modal/index.d.ts +0 -21
- package/dist/components/Modal/index.js +0 -116
- package/dist/components/Modal/index.js.map +0 -1
- package/dist/components/Modal/styles.d.ts +0 -56
- package/dist/components/Modal/styles.js +0 -36
- package/dist/components/Modal/styles.js.map +0 -1
- package/dist/components/Overlay.d.ts +0 -10
- package/dist/components/Overlay.js +0 -41
- package/dist/components/Overlay.js.map +0 -1
- package/dist/components/RadioInput/index.d.ts +0 -21
- package/dist/components/RadioInput/index.js +0 -55
- package/dist/components/RadioInput/index.js.map +0 -1
- package/dist/components/RadioInput/styles.d.ts +0 -54
- package/dist/components/RadioInput/styles.js +0 -44
- package/dist/components/RadioInput/styles.js.map +0 -1
- package/dist/components/RouterPage/Menu.d.ts +0 -10
- package/dist/components/RouterPage/Menu.js +0 -36
- package/dist/components/RouterPage/Menu.js.map +0 -1
- package/dist/components/RouterPage/MenuItem.d.ts +0 -12
- package/dist/components/RouterPage/MenuItem.js +0 -42
- package/dist/components/RouterPage/MenuItem.js.map +0 -1
- package/dist/components/RouterPage/Router.d.ts +0 -8
- package/dist/components/RouterPage/Router.js +0 -27
- package/dist/components/RouterPage/Router.js.map +0 -1
- package/dist/components/RouterPage/index.d.ts +0 -29
- package/dist/components/RouterPage/index.js +0 -85
- package/dist/components/RouterPage/index.js.map +0 -1
- package/dist/components/RouterPage/styles.d.ts +0 -54
- package/dist/components/RouterPage/styles.js +0 -87
- package/dist/components/RouterPage/styles.js.map +0 -1
- package/dist/components/Scroll.d.ts +0 -5
- package/dist/components/Scroll.js +0 -24
- package/dist/components/Scroll.js.map +0 -1
- package/dist/components/Select/Custom.d.ts +0 -8
- package/dist/components/Select/Custom.js +0 -104
- package/dist/components/Select/Custom.js.map +0 -1
- package/dist/components/Select/Multi.d.ts +0 -3
- package/dist/components/Select/Multi.js +0 -105
- package/dist/components/Select/Multi.js.map +0 -1
- package/dist/components/Select/Native.d.ts +0 -17
- package/dist/components/Select/Native.js +0 -44
- package/dist/components/Select/Native.js.map +0 -1
- package/dist/components/Select/index.d.ts +0 -12
- package/dist/components/Select/index.js +0 -40
- package/dist/components/Select/index.js.map +0 -1
- package/dist/components/Select/styles.d.ts +0 -5
- package/dist/components/Select/styles.js +0 -57
- package/dist/components/Select/styles.js.map +0 -1
- package/dist/components/Select/types.d.ts +0 -49
- package/dist/components/Select/types.js +0 -3
- package/dist/components/Select/types.js.map +0 -1
- package/dist/components/Slider.d.ts +0 -5
- package/dist/components/Slider.js +0 -39
- package/dist/components/Slider.js.map +0 -1
- package/dist/components/Text.d.ts +0 -9
- package/dist/components/Text.js +0 -43
- package/dist/components/Text.js.map +0 -1
- package/dist/components/TextInput.d.ts +0 -150
- package/dist/components/TextInput.js +0 -125
- package/dist/components/TextInput.js.map +0 -1
- package/dist/components/Tooltip.d.ts +0 -12
- package/dist/components/Tooltip.js +0 -122
- package/dist/components/Tooltip.js.map +0 -1
- package/dist/components/Touchable.d.ts +0 -15
- package/dist/components/Touchable.js +0 -52
- package/dist/components/Touchable.js.map +0 -1
- package/dist/components/View.d.ts +0 -10
- package/dist/components/View.js +0 -62
- package/dist/components/View.js.map +0 -1
- package/dist/components/index.d.ts +0 -24
- package/dist/components/index.js +0 -37
- package/dist/components/index.js.map +0 -1
- package/dist/index.d.ts +0 -6
- package/dist/index.js +0 -25
- package/dist/index.js.map +0 -1
- package/dist/lib/OSAlert.d.ts +0 -21
- package/dist/lib/OSAlert.js +0 -140
- package/dist/lib/OSAlert.js.map +0 -1
- package/dist/lib/Toast.d.ts +0 -13
- package/dist/lib/Toast.js +0 -32
- package/dist/lib/Toast.js.map +0 -1
- package/dist/lib/hooks.d.ts +0 -28
- package/dist/lib/hooks.js +0 -183
- package/dist/lib/hooks.js.map +0 -1
- package/dist/lib/logger.d.ts +0 -2
- package/dist/lib/logger.js +0 -16
- package/dist/lib/logger.js.map +0 -1
- package/dist/lib/utils/cookies.d.ts +0 -6
- package/dist/lib/utils/cookies.js +0 -15
- package/dist/lib/utils/cookies.js.map +0 -1
- package/dist/lib/utils/index.d.ts +0 -4
- package/dist/lib/utils/index.js +0 -23
- package/dist/lib/utils/index.js.map +0 -1
- package/dist/lib/utils/pollyfils/scroll.d.ts +0 -1
- package/dist/lib/utils/pollyfils/scroll.js +0 -66
- package/dist/lib/utils/pollyfils/scroll.js.map +0 -1
- package/dist/lib/utils/stopPropagation.d.ts +0 -1
- package/dist/lib/utils/stopPropagation.js +0 -20
- package/dist/lib/utils/stopPropagation.js.map +0 -1
- package/dist/types/utility.d.ts +0 -2
- package/dist/types/utility.js +0 -3
- package/dist/types/utility.js.map +0 -1
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { ComponentVariants, useDefaultComponentStyle, StylesOf, PropsOf } from '@codeleap/common'
|
|
3
|
+
import { View } from '../View'
|
|
4
|
+
import { SwitchPresets, SwitchComposition } from './styles'
|
|
5
|
+
import { InputBase, InputBaseDefaultOrder, InputBaseProps, selectInputBaseProps } from '../InputBase'
|
|
6
|
+
import { useAnimatedVariantStyles } from '../..'
|
|
7
|
+
import { motion } from 'framer-motion'
|
|
8
|
+
|
|
9
|
+
export * from './styles'
|
|
10
|
+
|
|
11
|
+
export type SwitchProps = Pick<
|
|
12
|
+
InputBaseProps,
|
|
13
|
+
'debugName' | 'disabled' | 'label'
|
|
14
|
+
> & {
|
|
15
|
+
variants?: ComponentVariants<typeof SwitchPresets>['variants']
|
|
16
|
+
styles?: StylesOf<SwitchComposition>
|
|
17
|
+
value: boolean
|
|
18
|
+
onValueChange: (value: boolean) => void
|
|
19
|
+
onChange?: (value: boolean) => void
|
|
20
|
+
style?: PropsOf<typeof View>['style']
|
|
21
|
+
switchOnLeft?: boolean
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const reversedOrder = [...InputBaseDefaultOrder].reverse()
|
|
25
|
+
|
|
26
|
+
export const Switch = (props: SwitchProps) => {
|
|
27
|
+
const {
|
|
28
|
+
inputBaseProps,
|
|
29
|
+
others
|
|
30
|
+
} = selectInputBaseProps(props)
|
|
31
|
+
const {
|
|
32
|
+
variants = [],
|
|
33
|
+
style = {},
|
|
34
|
+
styles = {},
|
|
35
|
+
value,
|
|
36
|
+
disabled,
|
|
37
|
+
debugName,
|
|
38
|
+
onValueChange,
|
|
39
|
+
onChange,
|
|
40
|
+
switchOnLeft,
|
|
41
|
+
} = others
|
|
42
|
+
|
|
43
|
+
const variantStyles = useDefaultComponentStyle<'u:Switch', typeof SwitchPresets>('u:Switch', {
|
|
44
|
+
variants,
|
|
45
|
+
styles,
|
|
46
|
+
rootElement: 'wrapper',
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
const trackAnimation = useAnimatedVariantStyles({
|
|
50
|
+
variantStyles,
|
|
51
|
+
animatedProperties: ['track:off','track:disabled', 'track:on', 'track:disabled-on', 'track:disabled-off'],
|
|
52
|
+
updater: () =>{
|
|
53
|
+
'worklet'
|
|
54
|
+
let disabledStyle = {}
|
|
55
|
+
if(disabled){
|
|
56
|
+
disabledStyle = value ? variantStyles['track:disabled-on'] : variantStyles['track:disabled-off']
|
|
57
|
+
}
|
|
58
|
+
const style = value ? variantStyles['track:on'] : variantStyles['track:off']
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
...style,
|
|
62
|
+
...disabledStyle
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
dependencies: [value, disabled],
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
const thumbAnimation = useAnimatedVariantStyles({
|
|
69
|
+
variantStyles,
|
|
70
|
+
animatedProperties: ['thumb:off','thumb:disabled', 'thumb:on', 'thumb:disabled-off', 'thumb:disabled-on'],
|
|
71
|
+
updater: () =>{
|
|
72
|
+
'worklet'
|
|
73
|
+
let disabledStyle = {}
|
|
74
|
+
if(disabled){
|
|
75
|
+
disabledStyle = value ? variantStyles['thumb:disabled-on'] : variantStyles['thumb:disabled-off']
|
|
76
|
+
}
|
|
77
|
+
const style = value ? variantStyles['thumb:on'] : variantStyles['thumb:off']
|
|
78
|
+
return {
|
|
79
|
+
...style,
|
|
80
|
+
...disabledStyle
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
dependencies: [value, disabled],
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
const _switchOnLeft = switchOnLeft ?? variantStyles['__props']?.switchOnLeft
|
|
87
|
+
|
|
88
|
+
const handleChange = () => {
|
|
89
|
+
if (disabled) return
|
|
90
|
+
if(onValueChange) onValueChange?.(!value)
|
|
91
|
+
if(onChange) onChange?.(!value)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return <InputBase
|
|
95
|
+
{...inputBaseProps}
|
|
96
|
+
debugName={debugName}
|
|
97
|
+
styles={{
|
|
98
|
+
...variantStyles,
|
|
99
|
+
innerWrapper: [
|
|
100
|
+
variantStyles.innerWrapper,
|
|
101
|
+
],
|
|
102
|
+
}}
|
|
103
|
+
order={_switchOnLeft ? reversedOrder : InputBaseDefaultOrder}
|
|
104
|
+
style={style}
|
|
105
|
+
disabled={disabled}
|
|
106
|
+
>
|
|
107
|
+
<motion.div
|
|
108
|
+
css={[
|
|
109
|
+
variantStyles.track,
|
|
110
|
+
disabled && variantStyles['track:disabled'],
|
|
111
|
+
]}
|
|
112
|
+
initial={false}
|
|
113
|
+
animate={trackAnimation}
|
|
114
|
+
transition={variantStyles['track:transition']}
|
|
115
|
+
onClick={handleChange}
|
|
116
|
+
>
|
|
117
|
+
<motion.div
|
|
118
|
+
css={[
|
|
119
|
+
variantStyles.thumb,
|
|
120
|
+
disabled && variantStyles['thumb:disabled'],
|
|
121
|
+
]}
|
|
122
|
+
initial={false}
|
|
123
|
+
animate={thumbAnimation}
|
|
124
|
+
transition={variantStyles['thumb:transition']}
|
|
125
|
+
/>
|
|
126
|
+
</motion.div>
|
|
127
|
+
</InputBase>
|
|
128
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
|
|
2
|
+
import { InputBaseParts, InputBaseStates } from '../InputBase'
|
|
3
|
+
|
|
4
|
+
type AnimatableParts = 'track' | 'thumb'
|
|
5
|
+
export type SwitchParts = InputBaseParts | AnimatableParts
|
|
6
|
+
|
|
7
|
+
export type SwitchAnimationStates = 'on' | 'off' | 'disabled-on' | 'disabled-off'
|
|
8
|
+
|
|
9
|
+
export type SwitchStates = InputBaseStates
|
|
10
|
+
|
|
11
|
+
export type SwitchComposition =
|
|
12
|
+
| SwitchParts
|
|
13
|
+
| `${SwitchParts}:${SwitchStates}`
|
|
14
|
+
| `${AnimatableParts}:transition`
|
|
15
|
+
| `${AnimatableParts}:${SwitchAnimationStates}`
|
|
16
|
+
| '__props'
|
|
17
|
+
|
|
18
|
+
const createSwitchStyle = createDefaultVariantFactory<SwitchComposition>()
|
|
19
|
+
|
|
20
|
+
export const SwitchPresets = includePresets((styles) => createSwitchStyle(() => ({ wrapper: styles })))
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { jsx } from '@emotion/react'
|
|
3
|
+
import {
|
|
4
|
+
ComponentVariants,
|
|
5
|
+
useCodeleapContext,
|
|
6
|
+
useDefaultComponentStyle,
|
|
7
|
+
} from '@codeleap/common'
|
|
8
|
+
import { ComponentPropsWithoutRef, ElementType } from 'react'
|
|
9
|
+
import { StylesOf } from '../../types/utility'
|
|
10
|
+
import { TextComposition, TextPresets } from './styles'
|
|
11
|
+
|
|
12
|
+
export * from './styles'
|
|
13
|
+
|
|
14
|
+
export type TextProps<T extends ElementType> = {
|
|
15
|
+
component?: T
|
|
16
|
+
text?: string
|
|
17
|
+
message?: string // is required
|
|
18
|
+
styles?: StylesOf<TextComposition>
|
|
19
|
+
debug?: boolean
|
|
20
|
+
debugName?: string
|
|
21
|
+
} & ComponentPropsWithoutRef<T> &
|
|
22
|
+
ComponentVariants<typeof TextPresets>
|
|
23
|
+
|
|
24
|
+
export const Text = <T extends ElementType>(textProps: TextProps<T>) => {
|
|
25
|
+
const {
|
|
26
|
+
variants = [],
|
|
27
|
+
responsiveVariants = {},
|
|
28
|
+
text = null,
|
|
29
|
+
children,
|
|
30
|
+
component = 'p',
|
|
31
|
+
styles,
|
|
32
|
+
message = null,
|
|
33
|
+
debug = false,
|
|
34
|
+
debugName,
|
|
35
|
+
...props
|
|
36
|
+
} = textProps
|
|
37
|
+
|
|
38
|
+
const variantStyles = useDefaultComponentStyle('Text', {
|
|
39
|
+
rootElement: 'text',
|
|
40
|
+
responsiveVariants,
|
|
41
|
+
variants,
|
|
42
|
+
styles,
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
const { logger } = useCodeleapContext()
|
|
46
|
+
|
|
47
|
+
const Component = component
|
|
48
|
+
|
|
49
|
+
if (debug) {
|
|
50
|
+
logger.log(`Text ${debugName}`, { variantStyles, text })
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
//@ts-ignore
|
|
55
|
+
<Component
|
|
56
|
+
css={[variantStyles.text, props.style]}
|
|
57
|
+
{...props}
|
|
58
|
+
>
|
|
59
|
+
{text || children}
|
|
60
|
+
</Component>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createDefaultVariantFactory, includePresets } from "@codeleap/common"
|
|
2
|
+
|
|
3
|
+
export type TextComposition = 'text'
|
|
4
|
+
|
|
5
|
+
const createTextStyle = createDefaultVariantFactory<TextComposition>()
|
|
6
|
+
|
|
7
|
+
export const TextPresets = includePresets((styles) =>
|
|
8
|
+
createTextStyle(() => ({ text: styles }))
|
|
9
|
+
)
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ComponentVariants,
|
|
3
|
+
FormTypes,
|
|
4
|
+
IconPlaceholder,
|
|
5
|
+
TextInputComposition,
|
|
6
|
+
TypeGuards,
|
|
7
|
+
useBooleanToggle,
|
|
8
|
+
useDefaultComponentStyle,
|
|
9
|
+
useValidate,
|
|
10
|
+
yup,
|
|
11
|
+
} from '@codeleap/common'
|
|
12
|
+
import React, {
|
|
13
|
+
ComponentPropsWithoutRef,
|
|
14
|
+
forwardRef,
|
|
15
|
+
useImperativeHandle,
|
|
16
|
+
useRef,
|
|
17
|
+
useState,
|
|
18
|
+
} from 'react'
|
|
19
|
+
import TextareaAutosize from 'react-autosize-textarea'
|
|
20
|
+
import InputMask from 'react-input-mask'
|
|
21
|
+
import { Touchable, TouchableProps } from '../Touchable'
|
|
22
|
+
import { StylesOf } from '../../types/utility'
|
|
23
|
+
import { InputBase, InputBaseProps, selectInputBaseProps } from '../InputBase'
|
|
24
|
+
import { TextInputPresets } from './styles'
|
|
25
|
+
import { getMaskInputProps, TextInputMaskingProps } from './mask'
|
|
26
|
+
|
|
27
|
+
export * from './styles'
|
|
28
|
+
export * from './mask'
|
|
29
|
+
|
|
30
|
+
type NativeTextInputProps = ComponentPropsWithoutRef<'input'>
|
|
31
|
+
|
|
32
|
+
export type TextInputProps =
|
|
33
|
+
Omit<InputBaseProps, 'styles' | 'variants'> &
|
|
34
|
+
Omit<NativeTextInputProps, 'value'|'crossOrigin'> & {
|
|
35
|
+
styles?: StylesOf<TextInputComposition>
|
|
36
|
+
password?: boolean
|
|
37
|
+
validate?: FormTypes.ValidatorWithoutForm<string> | yup.SchemaOf<string>
|
|
38
|
+
debugName?: string
|
|
39
|
+
visibilityToggle?: boolean
|
|
40
|
+
variants?: ComponentVariants<typeof TextInputPresets>['variants']
|
|
41
|
+
value?: NativeTextInputProps['value']
|
|
42
|
+
multiline?: boolean
|
|
43
|
+
onPress?: TouchableProps['onPress']
|
|
44
|
+
onChangeText?: (value: string) => void
|
|
45
|
+
caretColor?: string
|
|
46
|
+
focused?: boolean
|
|
47
|
+
_error?: boolean
|
|
48
|
+
rows?: number
|
|
49
|
+
masking?: TextInputMaskingProps
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const TextInput = forwardRef<HTMLInputElement, TextInputProps>((props, inputRef) => {
|
|
53
|
+
const innerInputRef = useRef<HTMLInputElement>(null)
|
|
54
|
+
|
|
55
|
+
const {
|
|
56
|
+
inputBaseProps,
|
|
57
|
+
others,
|
|
58
|
+
} = selectInputBaseProps(props)
|
|
59
|
+
|
|
60
|
+
const {
|
|
61
|
+
variants,
|
|
62
|
+
styles,
|
|
63
|
+
value,
|
|
64
|
+
validate,
|
|
65
|
+
debugName,
|
|
66
|
+
visibilityToggle,
|
|
67
|
+
password,
|
|
68
|
+
onPress,
|
|
69
|
+
multiline,
|
|
70
|
+
caretColor,
|
|
71
|
+
focused,
|
|
72
|
+
_error,
|
|
73
|
+
masking = null,
|
|
74
|
+
...textInputProps
|
|
75
|
+
} = others
|
|
76
|
+
|
|
77
|
+
const [_isFocused, setIsFocused] = useState(false)
|
|
78
|
+
|
|
79
|
+
const isFocused = _isFocused || focused
|
|
80
|
+
|
|
81
|
+
const [secureTextEntry, toggleSecureTextEntry] = useBooleanToggle(true)
|
|
82
|
+
|
|
83
|
+
const isMultiline = multiline
|
|
84
|
+
|
|
85
|
+
const isMasked = !TypeGuards.isNil(masking)
|
|
86
|
+
const maskProps = isMasked ? getMaskInputProps({ masking }) : null
|
|
87
|
+
|
|
88
|
+
const InputElement = isMasked ? InputMask : isMultiline ? TextareaAutosize : 'input'
|
|
89
|
+
|
|
90
|
+
const variantStyles = useDefaultComponentStyle<'u:TextInput', typeof TextInputPresets>('u:TextInput', {
|
|
91
|
+
variants,
|
|
92
|
+
styles,
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
useImperativeHandle(inputRef, () => {
|
|
96
|
+
return {
|
|
97
|
+
...innerInputRef.current,
|
|
98
|
+
focus: () => {
|
|
99
|
+
innerInputRef.current?.focus?.()
|
|
100
|
+
},
|
|
101
|
+
isTextInput: true,
|
|
102
|
+
}
|
|
103
|
+
}, [!!innerInputRef?.current?.focus])
|
|
104
|
+
|
|
105
|
+
const isPressable = TypeGuards.isFunction(onPress)
|
|
106
|
+
|
|
107
|
+
const validation = useValidate(
|
|
108
|
+
value,
|
|
109
|
+
TypeGuards.isFunction(maskProps?.validator) ? maskProps?.validator : validate,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
const handleBlur = React.useCallback((e: React.FocusEvent<HTMLInputElement, Element>) => {
|
|
113
|
+
validation?.onInputBlurred()
|
|
114
|
+
setIsFocused(false)
|
|
115
|
+
props?.onBlur?.(e)
|
|
116
|
+
}, [validation?.onInputBlurred, props?.onBlur])
|
|
117
|
+
|
|
118
|
+
const handleFocus = React.useCallback((e: React.FocusEvent<HTMLInputElement, Element>) => {
|
|
119
|
+
validation?.onInputFocused()
|
|
120
|
+
setIsFocused(true)
|
|
121
|
+
props?.onFocus?.(e)
|
|
122
|
+
}, [validation?.onInputFocused, props?.onFocus])
|
|
123
|
+
|
|
124
|
+
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
125
|
+
const _text = event?.target?.value
|
|
126
|
+
|
|
127
|
+
const _value = isMasked && maskProps?.notSaveFormatted
|
|
128
|
+
? maskProps?.getRawValue(_text)
|
|
129
|
+
: _text
|
|
130
|
+
|
|
131
|
+
if (props?.onChange) props?.onChange(event)
|
|
132
|
+
if (props?.onChangeText) props?.onChangeText(_value)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const isDisabled = !!inputBaseProps.disabled
|
|
136
|
+
|
|
137
|
+
const visibilityToggleProps = visibilityToggle ? {
|
|
138
|
+
onPress: toggleSecureTextEntry,
|
|
139
|
+
icon: (secureTextEntry ? 'input-visiblity:hidden' : 'input-visiblity:visible') as IconPlaceholder,
|
|
140
|
+
debugName: `${debugName} toggle visibility`,
|
|
141
|
+
} : null
|
|
142
|
+
|
|
143
|
+
const rightIcon = inputBaseProps?.rightIcon ?? visibilityToggleProps
|
|
144
|
+
|
|
145
|
+
const buttonModeProps = isPressable ? {
|
|
146
|
+
editable: false,
|
|
147
|
+
caretHidden: true,
|
|
148
|
+
} : {}
|
|
149
|
+
const rows = textInputProps?.rows ?? (
|
|
150
|
+
isMultiline ? 2 : undefined
|
|
151
|
+
)
|
|
152
|
+
const hasMultipleLines = isMultiline && (String(value)?.includes('\n') || !!rows)
|
|
153
|
+
|
|
154
|
+
const hasError = !validation.isValid || _error
|
|
155
|
+
const errorMessage = validation.message || _error
|
|
156
|
+
|
|
157
|
+
const placeholderStyles = [
|
|
158
|
+
variantStyles.placeholder,
|
|
159
|
+
isFocused && variantStyles['placeholder:focus'],
|
|
160
|
+
hasError && variantStyles['placeholder:error'],
|
|
161
|
+
isDisabled && variantStyles['placeholder:disabled'],
|
|
162
|
+
]
|
|
163
|
+
|
|
164
|
+
const selectionStyles = [
|
|
165
|
+
variantStyles.selection,
|
|
166
|
+
isFocused && variantStyles['selection:focus'],
|
|
167
|
+
hasError && variantStyles['selection:error'],
|
|
168
|
+
isDisabled && variantStyles['selection:disabled'],
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
const secureTextProps = (password && secureTextEntry) && {
|
|
172
|
+
type: 'password',
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const caretColorStyle = (caretColor || buttonModeProps.caretHidden) && {
|
|
176
|
+
caretColor: buttonModeProps.caretHidden ? 'transparent' : caretColor,
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const inputBaseAction = isPressable ? 'onPress' : 'onClick'
|
|
180
|
+
|
|
181
|
+
const _wrapperOnInputFocus = {
|
|
182
|
+
[inputBaseAction]: () => {
|
|
183
|
+
innerInputRef.current?.focus?.()
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<InputBase
|
|
189
|
+
innerWrapper={isPressable ? Touchable : undefined}
|
|
190
|
+
{...inputBaseProps}
|
|
191
|
+
debugName={debugName}
|
|
192
|
+
error={hasError ? errorMessage : null}
|
|
193
|
+
styles={{
|
|
194
|
+
...variantStyles,
|
|
195
|
+
innerWrapper: [
|
|
196
|
+
variantStyles.innerWrapper,
|
|
197
|
+
isMultiline && variantStyles['innerWrapper:multiline'],
|
|
198
|
+
hasMultipleLines && variantStyles['innerWrapper:hasMultipleLines'],
|
|
199
|
+
],
|
|
200
|
+
}}
|
|
201
|
+
innerWrapperProps={{
|
|
202
|
+
...(inputBaseProps.innerWrapperProps || {}),
|
|
203
|
+
[inputBaseAction]: () => {
|
|
204
|
+
// @ts-ignore
|
|
205
|
+
if (isMasked) innerInputRef.current?.onFocus?.()
|
|
206
|
+
innerInputRef.current?.focus?.()
|
|
207
|
+
if (isPressable) onPress?.()
|
|
208
|
+
},
|
|
209
|
+
debugName,
|
|
210
|
+
}}
|
|
211
|
+
rightIcon={rightIcon}
|
|
212
|
+
focused={isFocused}
|
|
213
|
+
wrapperProps={{
|
|
214
|
+
...(inputBaseProps.wrapperProps || {}),
|
|
215
|
+
..._wrapperOnInputFocus,
|
|
216
|
+
}}
|
|
217
|
+
>
|
|
218
|
+
<InputElement
|
|
219
|
+
editable={`${!isPressable && !isDisabled}`}
|
|
220
|
+
{...buttonModeProps}
|
|
221
|
+
{...secureTextProps}
|
|
222
|
+
{...textInputProps}
|
|
223
|
+
value={value}
|
|
224
|
+
onChange={(e) => handleChange(e)}
|
|
225
|
+
onBlur={handleBlur}
|
|
226
|
+
onFocus={handleFocus}
|
|
227
|
+
css={[
|
|
228
|
+
variantStyles.input,
|
|
229
|
+
isMultiline && variantStyles['input:multiline'],
|
|
230
|
+
isFocused && variantStyles['input:focus'],
|
|
231
|
+
hasError && variantStyles['input:error'],
|
|
232
|
+
isDisabled && variantStyles['input:disabled'],
|
|
233
|
+
hasMultipleLines && variantStyles['input:hasMultipleLines'],
|
|
234
|
+
{
|
|
235
|
+
'&::placeholder': placeholderStyles,
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
'&::selection': selectionStyles,
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
'&:focus': [
|
|
242
|
+
{ outline: 'none', borderWidth: 0, borderColor: 'transparent' },
|
|
243
|
+
isFocused && variantStyles['input:focus'],
|
|
244
|
+
caretColorStyle,
|
|
245
|
+
],
|
|
246
|
+
},
|
|
247
|
+
]}
|
|
248
|
+
{...maskProps}
|
|
249
|
+
ref={innerInputRef}
|
|
250
|
+
/>
|
|
251
|
+
</InputBase>
|
|
252
|
+
)
|
|
253
|
+
})
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { FormTypes, TypeGuards } from '@codeleap/common'
|
|
2
|
+
|
|
3
|
+
type beforeMaskedValueChangeArgs = {
|
|
4
|
+
state: {
|
|
5
|
+
value: string | undefined
|
|
6
|
+
selection: {
|
|
7
|
+
start: number
|
|
8
|
+
end: number
|
|
9
|
+
length?: number
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
userInput: null | string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type FormatChar = `[${string}]`
|
|
16
|
+
|
|
17
|
+
export type MaskProps = {
|
|
18
|
+
obfuscated?: boolean
|
|
19
|
+
mask?: string
|
|
20
|
+
placeholder?: string
|
|
21
|
+
maskChar?: string
|
|
22
|
+
formatChars?: Record<string, FormatChar>
|
|
23
|
+
alwaysShowMask?: boolean
|
|
24
|
+
validator?: FormTypes.ValidatorFunctionWithoutForm
|
|
25
|
+
maskType?: 'BRL' | 'INTERNATIONAL'
|
|
26
|
+
getRawValue?: (value: any) => string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type TextInputMaskTypeProp =
|
|
30
|
+
| 'credit-card'
|
|
31
|
+
| 'cpf'
|
|
32
|
+
| 'cnpj'
|
|
33
|
+
| 'zip-code'
|
|
34
|
+
| 'cel-phone'
|
|
35
|
+
| 'custom'
|
|
36
|
+
|
|
37
|
+
export interface TextInputMaskingProps {
|
|
38
|
+
type: TextInputMaskTypeProp
|
|
39
|
+
options?: MaskProps
|
|
40
|
+
onChangeMask?: (
|
|
41
|
+
newState: beforeMaskedValueChangeArgs['state'],
|
|
42
|
+
oldState: beforeMaskedValueChangeArgs['state'],
|
|
43
|
+
userInput: beforeMaskedValueChangeArgs['userInput']
|
|
44
|
+
) => beforeMaskedValueChangeArgs['state']
|
|
45
|
+
saveFormatted?: boolean
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
type InputMaskProps = {
|
|
49
|
+
masking: TextInputMaskingProps
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const getMaskInputProps = ({ masking }: InputMaskProps): MaskProps & { notSaveFormatted: boolean } => {
|
|
53
|
+
const {
|
|
54
|
+
type = 'custom',
|
|
55
|
+
options = {},
|
|
56
|
+
} = masking
|
|
57
|
+
|
|
58
|
+
const maskType = masking?.options?.maskType ?? 'INTERNATIONAL'
|
|
59
|
+
const phoneType = maskType === 'INTERNATIONAL' ? 'cel-phone' : 'cel-phone-brl'
|
|
60
|
+
|
|
61
|
+
const presetProps = masking?.type === 'cel-phone' ? maskPreset[phoneType] : maskPreset[type]
|
|
62
|
+
|
|
63
|
+
const isObfuscated = options?.obfuscated === true && {
|
|
64
|
+
type: 'password',
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const notSaveFormatted = (TypeGuards.isBoolean(masking?.saveFormatted) && masking?.saveFormatted === false)
|
|
68
|
+
|
|
69
|
+
const props = {
|
|
70
|
+
...presetProps,
|
|
71
|
+
...options,
|
|
72
|
+
...isObfuscated,
|
|
73
|
+
notSaveFormatted,
|
|
74
|
+
beforeMaskedValueChange: masking?.onChangeMask,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const defaultGetRawValue = (value: string) => {
|
|
78
|
+
return String(value)?.replace(/\D/g, '')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
...props,
|
|
83
|
+
validator: notSaveFormatted ? null : props?.validator,
|
|
84
|
+
getRawValue: props?.getRawValue ?? defaultGetRawValue,
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const format: Record<string, FormatChar> = {
|
|
89
|
+
number: "['0123456789']",
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const validatorRegExp = (value: string | number, regex: RegExp, error: string) => {
|
|
93
|
+
const isValid = regex.test(String(value))
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
valid: isValid,
|
|
97
|
+
message: error,
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export const maskPreset: Record<TextInputMaskTypeProp | 'cel-phone-brl', MaskProps> = {
|
|
102
|
+
'credit-card': {
|
|
103
|
+
mask: '9999 9999 9999 9999',
|
|
104
|
+
placeholder: 'xxxx xxxx xxxx xxxx',
|
|
105
|
+
formatChars: {
|
|
106
|
+
'9': format.number,
|
|
107
|
+
},
|
|
108
|
+
validator: (value: string) => {
|
|
109
|
+
return validatorRegExp(value, /^\d{4}\s?\d{4}\s?\d{4}\s?\d{4}$/, 'Invalid information')
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
'cpf': {
|
|
113
|
+
mask: '999.999.999-99',
|
|
114
|
+
placeholder: 'xxx.xxx.xxx-xx',
|
|
115
|
+
formatChars: {
|
|
116
|
+
'9': format.number,
|
|
117
|
+
},
|
|
118
|
+
validator: (value: string) => {
|
|
119
|
+
return validatorRegExp(value, /^\d{3}\.\d{3}\.\d{3}-\d{2}$/, 'Invalid CPF')
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
'cnpj': {
|
|
123
|
+
mask: '99.999.999/9999-99',
|
|
124
|
+
placeholder: 'xx.xxx.xxx/xxxx-xx',
|
|
125
|
+
formatChars: {
|
|
126
|
+
'9': format.number,
|
|
127
|
+
},
|
|
128
|
+
validator: (value: string) => {
|
|
129
|
+
return validatorRegExp(value, /^\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}$/, 'Invalid CNPJ')
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
'zip-code': {
|
|
133
|
+
mask: '99999-999',
|
|
134
|
+
placeholder: 'xxxxx-xxx',
|
|
135
|
+
formatChars: {
|
|
136
|
+
'9': format.number,
|
|
137
|
+
},
|
|
138
|
+
validator: (value: string) => {
|
|
139
|
+
return validatorRegExp(value, /^\d{5}-\d{3}$/, 'Invalid zip code')
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
'cel-phone': {
|
|
143
|
+
mask: '+999 999 999 999',
|
|
144
|
+
placeholder: '+xxx xxx xxx xxx',
|
|
145
|
+
maskType: 'INTERNATIONAL',
|
|
146
|
+
formatChars: {
|
|
147
|
+
'9': format.number,
|
|
148
|
+
},
|
|
149
|
+
validator: (value: string) => {
|
|
150
|
+
return validatorRegExp(value, /^\+\d{3}\s\d{3}\s\d{3}\s\d{3}$/, 'Invalid phone')
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
'cel-phone-brl': {
|
|
154
|
+
mask: '(99) 99999-9999',
|
|
155
|
+
placeholder: '(xx) xxxxx-xxxx',
|
|
156
|
+
maskType: 'BRL',
|
|
157
|
+
formatChars: {
|
|
158
|
+
'9': format.number,
|
|
159
|
+
},
|
|
160
|
+
validator: (value: string) => {
|
|
161
|
+
return validatorRegExp(value, /^\(?\d{2}\)?\s?9?\d{4}-\d{4}$/, 'Invalid phone')
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
'custom': {},
|
|
165
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
|
|
2
|
+
import { ActionIconParts } from '../ActionIcon'
|
|
3
|
+
import { InputBaseParts, InputBaseStates } from '../InputBase'
|
|
4
|
+
|
|
5
|
+
type TextInputParts = InputBaseParts | 'input' | 'placeholder' | 'selection'
|
|
6
|
+
export type TextInputStates = InputBaseStates | 'multiline' | 'hasMultipleLines'
|
|
7
|
+
|
|
8
|
+
export type IconParts = Exclude<ActionIconParts, 'icon' | 'icon:disabled'>
|
|
9
|
+
|
|
10
|
+
export type TextInputComposition = `${TextInputParts}:${TextInputStates}` | TextInputParts
|
|
11
|
+
|
|
12
|
+
const createTextInputStyle =
|
|
13
|
+
createDefaultVariantFactory<TextInputComposition>()
|
|
14
|
+
|
|
15
|
+
export const TextInputPresets = includePresets((styles) => createTextInputStyle(() => ({ wrapper: styles })))
|