@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.
Files changed (212) hide show
  1. package/package.json +20 -19
  2. package/src/components/ActionIcon/index.tsx +59 -0
  3. package/src/components/ActionIcon/styles.ts +9 -0
  4. package/src/components/ActivityIndicator/index.tsx +78 -0
  5. package/src/components/ActivityIndicator/styles.ts +11 -0
  6. package/src/components/Button/index.tsx +125 -0
  7. package/src/components/Button/styles.ts +22 -0
  8. package/src/components/Checkbox/index.tsx +138 -0
  9. package/src/components/Checkbox/styles.ts +20 -0
  10. package/src/components/Collapse/index.tsx +87 -0
  11. package/src/components/Collapse/styles.ts +8 -0
  12. package/src/components/Drawer/index.tsx +148 -0
  13. package/src/components/Drawer/styles.ts +8 -0
  14. package/src/components/FileInput.tsx +51 -0
  15. package/src/components/Icon/index.tsx +53 -0
  16. package/src/components/Icon/styles.ts +9 -0
  17. package/src/components/InputBase/index.tsx +104 -0
  18. package/src/components/InputBase/styles.ts +167 -0
  19. package/src/components/InputBase/types.ts +28 -0
  20. package/src/components/InputBase/utils.ts +41 -0
  21. package/src/components/Link/index.tsx +69 -0
  22. package/src/components/Link/styles.ts +11 -0
  23. package/src/components/List/index.tsx +103 -0
  24. package/src/components/List/styles.ts +8 -0
  25. package/src/components/LoadingOverlay/index.tsx +34 -0
  26. package/src/components/LoadingOverlay/styles.ts +12 -0
  27. package/src/components/Modal/index.tsx +189 -0
  28. package/src/components/Modal/styles.ts +26 -0
  29. package/src/components/NumberIncrement/index.tsx +292 -0
  30. package/src/components/NumberIncrement/styles.ts +15 -0
  31. package/src/components/Overlay/index.tsx +42 -0
  32. package/src/components/Overlay/styles.ts +8 -0
  33. package/src/components/RadioInput/index.tsx +155 -0
  34. package/src/components/RadioInput/styles.ts +14 -0
  35. package/src/components/Scroll/index.tsx +29 -0
  36. package/src/components/Scroll/styles.ts +8 -0
  37. package/src/components/Select/index.tsx +438 -0
  38. package/src/components/Select/styles.ts +179 -0
  39. package/src/components/Select/types.ts +100 -0
  40. package/src/components/Slider/index.tsx +303 -0
  41. package/src/components/Slider/styles.ts +11 -0
  42. package/src/components/Switch/index.tsx +128 -0
  43. package/src/components/Switch/styles.ts +20 -0
  44. package/src/components/Text/index.tsx +62 -0
  45. package/src/components/Text/styles.ts +9 -0
  46. package/src/components/TextInput/index.tsx +253 -0
  47. package/src/components/TextInput/mask.tsx +165 -0
  48. package/src/components/TextInput/styles.ts +15 -0
  49. package/src/components/Tooltip/index.tsx +155 -0
  50. package/src/components/Tooltip/styles.ts +9 -0
  51. package/src/components/Touchable/index.tsx +72 -0
  52. package/src/components/Touchable/styles.ts +11 -0
  53. package/src/components/View/index.tsx +94 -0
  54. package/src/components/View/styles.ts +8 -0
  55. package/src/components/components.ts +29 -0
  56. package/src/components/defaultStyles.ts +51 -0
  57. package/src/index.ts +6 -0
  58. package/src/lib/OSAlert.tsx +190 -0
  59. package/src/lib/Toast.ts +23 -0
  60. package/src/lib/hooks.ts +340 -0
  61. package/src/lib/index.ts +2 -0
  62. package/src/lib/logger.ts +13 -0
  63. package/src/lib/utils/cookies.ts +13 -0
  64. package/src/lib/utils/index.ts +4 -0
  65. package/src/lib/utils/pollyfils/scroll.ts +65 -0
  66. package/src/lib/utils/stopPropagation.ts +15 -0
  67. package/src/types/index.ts +1 -0
  68. package/src/types/utility.ts +3 -0
  69. package/dist/components/ActivityIndicator/index.d.ts +0 -12
  70. package/dist/components/ActivityIndicator/index.js +0 -57
  71. package/dist/components/ActivityIndicator/index.js.map +0 -1
  72. package/dist/components/ActivityIndicator/styles.d.ts +0 -53
  73. package/dist/components/ActivityIndicator/styles.js +0 -22
  74. package/dist/components/ActivityIndicator/styles.js.map +0 -1
  75. package/dist/components/Button.d.ts +0 -18
  76. package/dist/components/Button.js +0 -67
  77. package/dist/components/Button.js.map +0 -1
  78. package/dist/components/CenterWrapper.d.ts +0 -7
  79. package/dist/components/CenterWrapper.js +0 -28
  80. package/dist/components/CenterWrapper.js.map +0 -1
  81. package/dist/components/Checkbox/index.d.ts +0 -12
  82. package/dist/components/Checkbox/index.js +0 -58
  83. package/dist/components/Checkbox/index.js.map +0 -1
  84. package/dist/components/Checkbox/styles.d.ts +0 -53
  85. package/dist/components/Checkbox/styles.js +0 -64
  86. package/dist/components/Checkbox/styles.js.map +0 -1
  87. package/dist/components/Collapse.d.ts +0 -20
  88. package/dist/components/Collapse.js +0 -68
  89. package/dist/components/Collapse.js.map +0 -1
  90. package/dist/components/ContentView.d.ts +0 -10
  91. package/dist/components/ContentView.js +0 -52
  92. package/dist/components/ContentView.js.map +0 -1
  93. package/dist/components/Drawer.d.ts +0 -23
  94. package/dist/components/Drawer.js +0 -73
  95. package/dist/components/Drawer.js.map +0 -1
  96. package/dist/components/FileInput.d.ts +0 -8
  97. package/dist/components/FileInput.js +0 -69
  98. package/dist/components/FileInput.js.map +0 -1
  99. package/dist/components/HorizontalScroll.d.ts +0 -3
  100. package/dist/components/HorizontalScroll.js +0 -42
  101. package/dist/components/HorizontalScroll.js.map +0 -1
  102. package/dist/components/Icon.d.ts +0 -8
  103. package/dist/components/Icon.js +0 -55
  104. package/dist/components/Icon.js.map +0 -1
  105. package/dist/components/Link.d.ts +0 -7
  106. package/dist/components/Link.js +0 -63
  107. package/dist/components/Link.js.map +0 -1
  108. package/dist/components/List.d.ts +0 -18
  109. package/dist/components/List.js +0 -52
  110. package/dist/components/List.js.map +0 -1
  111. package/dist/components/Modal/index.d.ts +0 -21
  112. package/dist/components/Modal/index.js +0 -116
  113. package/dist/components/Modal/index.js.map +0 -1
  114. package/dist/components/Modal/styles.d.ts +0 -56
  115. package/dist/components/Modal/styles.js +0 -36
  116. package/dist/components/Modal/styles.js.map +0 -1
  117. package/dist/components/Overlay.d.ts +0 -10
  118. package/dist/components/Overlay.js +0 -41
  119. package/dist/components/Overlay.js.map +0 -1
  120. package/dist/components/RadioInput/index.d.ts +0 -21
  121. package/dist/components/RadioInput/index.js +0 -55
  122. package/dist/components/RadioInput/index.js.map +0 -1
  123. package/dist/components/RadioInput/styles.d.ts +0 -54
  124. package/dist/components/RadioInput/styles.js +0 -44
  125. package/dist/components/RadioInput/styles.js.map +0 -1
  126. package/dist/components/RouterPage/Menu.d.ts +0 -10
  127. package/dist/components/RouterPage/Menu.js +0 -36
  128. package/dist/components/RouterPage/Menu.js.map +0 -1
  129. package/dist/components/RouterPage/MenuItem.d.ts +0 -12
  130. package/dist/components/RouterPage/MenuItem.js +0 -42
  131. package/dist/components/RouterPage/MenuItem.js.map +0 -1
  132. package/dist/components/RouterPage/Router.d.ts +0 -8
  133. package/dist/components/RouterPage/Router.js +0 -27
  134. package/dist/components/RouterPage/Router.js.map +0 -1
  135. package/dist/components/RouterPage/index.d.ts +0 -29
  136. package/dist/components/RouterPage/index.js +0 -85
  137. package/dist/components/RouterPage/index.js.map +0 -1
  138. package/dist/components/RouterPage/styles.d.ts +0 -54
  139. package/dist/components/RouterPage/styles.js +0 -87
  140. package/dist/components/RouterPage/styles.js.map +0 -1
  141. package/dist/components/Scroll.d.ts +0 -5
  142. package/dist/components/Scroll.js +0 -24
  143. package/dist/components/Scroll.js.map +0 -1
  144. package/dist/components/Select/Custom.d.ts +0 -8
  145. package/dist/components/Select/Custom.js +0 -104
  146. package/dist/components/Select/Custom.js.map +0 -1
  147. package/dist/components/Select/Multi.d.ts +0 -3
  148. package/dist/components/Select/Multi.js +0 -105
  149. package/dist/components/Select/Multi.js.map +0 -1
  150. package/dist/components/Select/Native.d.ts +0 -17
  151. package/dist/components/Select/Native.js +0 -44
  152. package/dist/components/Select/Native.js.map +0 -1
  153. package/dist/components/Select/index.d.ts +0 -12
  154. package/dist/components/Select/index.js +0 -40
  155. package/dist/components/Select/index.js.map +0 -1
  156. package/dist/components/Select/styles.d.ts +0 -5
  157. package/dist/components/Select/styles.js +0 -57
  158. package/dist/components/Select/styles.js.map +0 -1
  159. package/dist/components/Select/types.d.ts +0 -49
  160. package/dist/components/Select/types.js +0 -3
  161. package/dist/components/Select/types.js.map +0 -1
  162. package/dist/components/Slider.d.ts +0 -5
  163. package/dist/components/Slider.js +0 -39
  164. package/dist/components/Slider.js.map +0 -1
  165. package/dist/components/Text.d.ts +0 -9
  166. package/dist/components/Text.js +0 -43
  167. package/dist/components/Text.js.map +0 -1
  168. package/dist/components/TextInput.d.ts +0 -150
  169. package/dist/components/TextInput.js +0 -125
  170. package/dist/components/TextInput.js.map +0 -1
  171. package/dist/components/Tooltip.d.ts +0 -12
  172. package/dist/components/Tooltip.js +0 -122
  173. package/dist/components/Tooltip.js.map +0 -1
  174. package/dist/components/Touchable.d.ts +0 -15
  175. package/dist/components/Touchable.js +0 -52
  176. package/dist/components/Touchable.js.map +0 -1
  177. package/dist/components/View.d.ts +0 -10
  178. package/dist/components/View.js +0 -62
  179. package/dist/components/View.js.map +0 -1
  180. package/dist/components/index.d.ts +0 -24
  181. package/dist/components/index.js +0 -37
  182. package/dist/components/index.js.map +0 -1
  183. package/dist/index.d.ts +0 -6
  184. package/dist/index.js +0 -25
  185. package/dist/index.js.map +0 -1
  186. package/dist/lib/OSAlert.d.ts +0 -21
  187. package/dist/lib/OSAlert.js +0 -140
  188. package/dist/lib/OSAlert.js.map +0 -1
  189. package/dist/lib/Toast.d.ts +0 -13
  190. package/dist/lib/Toast.js +0 -32
  191. package/dist/lib/Toast.js.map +0 -1
  192. package/dist/lib/hooks.d.ts +0 -28
  193. package/dist/lib/hooks.js +0 -183
  194. package/dist/lib/hooks.js.map +0 -1
  195. package/dist/lib/logger.d.ts +0 -2
  196. package/dist/lib/logger.js +0 -16
  197. package/dist/lib/logger.js.map +0 -1
  198. package/dist/lib/utils/cookies.d.ts +0 -6
  199. package/dist/lib/utils/cookies.js +0 -15
  200. package/dist/lib/utils/cookies.js.map +0 -1
  201. package/dist/lib/utils/index.d.ts +0 -4
  202. package/dist/lib/utils/index.js +0 -23
  203. package/dist/lib/utils/index.js.map +0 -1
  204. package/dist/lib/utils/pollyfils/scroll.d.ts +0 -1
  205. package/dist/lib/utils/pollyfils/scroll.js +0 -66
  206. package/dist/lib/utils/pollyfils/scroll.js.map +0 -1
  207. package/dist/lib/utils/stopPropagation.d.ts +0 -1
  208. package/dist/lib/utils/stopPropagation.js +0 -20
  209. package/dist/lib/utils/stopPropagation.js.map +0 -1
  210. package/dist/types/utility.d.ts +0 -2
  211. package/dist/types/utility.js +0 -3
  212. package/dist/types/utility.js.map +0 -1
@@ -0,0 +1,42 @@
1
+ import {
2
+ ComponentVariants,
3
+ SmartOmit,
4
+ StylesOf,
5
+ useDefaultComponentStyle,
6
+ } from '@codeleap/common'
7
+ import { Touchable, TouchableProps } from '../Touchable'
8
+ import { View, ViewProps } from '../View'
9
+ import { OverlayComposition, OverlayPresets } from './styles'
10
+
11
+ export type OverlayProps = {
12
+ visible?: boolean
13
+ styles?: StylesOf<OverlayComposition>
14
+ onPress?: TouchableProps<'div'>['onClick']
15
+ } & ComponentVariants<typeof OverlayPresets> &
16
+ Partial<SmartOmit<ViewProps<'div'>, 'variants' | 'responsiveVariants'>>
17
+
18
+ export * from './styles'
19
+
20
+ export const Overlay: React.FC<OverlayProps> = (overlayProps) => {
21
+ const { visible, responsiveVariants, variants, styles, ...props } =
22
+ overlayProps
23
+
24
+ const variantStyles = useDefaultComponentStyle('Overlay', {
25
+ variants,
26
+ responsiveVariants,
27
+ styles,
28
+ })
29
+
30
+ const Component = props.onClick || props.onPress ? Touchable : View
31
+
32
+ return (
33
+ <Component
34
+ css={{
35
+ ...variantStyles.wrapper,
36
+ transition: 'opacity 0.2s ease',
37
+ ...(visible ? variantStyles['wrapper:visible'] : {}),
38
+ }}
39
+ {...props}
40
+ />
41
+ )
42
+ }
@@ -0,0 +1,8 @@
1
+ import { createDefaultVariantFactory, includePresets } from "@codeleap/common";
2
+ import { ViewComposition } from "../View";
3
+
4
+ export type OverlayComposition = ViewComposition
5
+
6
+ const createOverlayStyle = createDefaultVariantFactory<OverlayComposition>()
7
+
8
+ export const OverlayPresets = includePresets((styles) => createOverlayStyle(() => ({ wrapper: styles })))
@@ -0,0 +1,155 @@
1
+ import * as React from 'react'
2
+ import { ReactNode } from 'react'
3
+ import { Text } from '../Text'
4
+ import { Touchable } from '../Touchable'
5
+ import {
6
+ ComponentVariants,
7
+ FormTypes,
8
+ StylesOf,
9
+ TypeGuards,
10
+ useDefaultComponentStyle,
11
+ } from '@codeleap/common'
12
+ import { View } from '../View'
13
+ import { RadioInputComposition, RadioInputPresets } from './styles'
14
+ import { InputBase, InputBaseProps, selectInputBaseProps } from '../InputBase'
15
+
16
+ export * from './styles'
17
+
18
+ type WrapperProps = InputBaseProps
19
+
20
+ type RadioOption<T> = FormTypes.Options<T>[number] & {
21
+ disabled?: boolean
22
+ }
23
+
24
+ export type RadioGroupProps<T extends string|number> = WrapperProps & {
25
+ options: RadioOption<T>[]
26
+ value: T
27
+ onValueChange(value: T): void
28
+ label: ReactNode
29
+ styles?: StylesOf<RadioInputComposition>
30
+ variants?: ComponentVariants<typeof RadioInputPresets>['variants']
31
+ }
32
+
33
+ type OptionProps<T extends string|number> = {
34
+ item: RadioOption<T>
35
+ selected: boolean
36
+ onSelect(): void
37
+ styles?: StylesOf<RadioInputComposition>
38
+ debugName?: string
39
+ disabled?: boolean
40
+ separator?: boolean
41
+ }
42
+
43
+ const Option = <T extends string|number>(props: OptionProps<T>) => {
44
+ const {
45
+ debugName,
46
+ item,
47
+ disabled,
48
+ styles,
49
+ selected,
50
+ onSelect,
51
+ separator = false,
52
+ } = props
53
+
54
+ const isDisabled = disabled || item.disabled
55
+
56
+ const getStyle = (key) => {
57
+ if(isDisabled && selected) {
58
+ return styles[`${key}:selectedDisabled`]
59
+ }
60
+ if(isDisabled) {
61
+ return styles[`${key}:disabled`]
62
+ }
63
+ if(selected) {
64
+ return styles[`${key}:selected`]
65
+ }
66
+ return styles[key]
67
+ }
68
+
69
+ const label = TypeGuards.isString(item.label) ? <Text
70
+ css={[
71
+ styles.optionLabel,
72
+ getStyle('optionLabel'),
73
+ ]}
74
+ text={item.label}
75
+ /> : item.label
76
+
77
+ return <>
78
+ <Touchable
79
+ debugName={`${debugName} option ${item.value}`}
80
+ css={[
81
+ styles.optionWrapper,
82
+ getStyle('optionWrapper'),
83
+ ]}
84
+ onPress={onSelect}
85
+ disabled={isDisabled}
86
+ >
87
+ <View
88
+ css={[
89
+ styles.optionIndicator,
90
+ getStyle('optionIndicator'),
91
+ ]}
92
+
93
+ >
94
+ <View
95
+ css={[
96
+ styles.optionIndicatorInner,
97
+ getStyle('optionIndicatorInner'),
98
+ ]}
99
+ />
100
+ </View>
101
+ {label}
102
+
103
+ </Touchable>
104
+ {separator && <View style={styles.optionSeparator} />}
105
+ </>
106
+ }
107
+
108
+ export const RadioGroup = <T extends string|number>(
109
+ props: RadioGroupProps<T>,
110
+ ) => {
111
+ const {
112
+ inputBaseProps,
113
+ others
114
+ } = selectInputBaseProps(props)
115
+
116
+ const {
117
+ options,
118
+ value,
119
+ onValueChange,
120
+ variants,
121
+ styles,
122
+ disabled,
123
+ debugName,
124
+ } = others
125
+
126
+ const variantStyles = useDefaultComponentStyle<'u:RadioInput', typeof RadioInputPresets>('u:RadioInput', {
127
+ variants,
128
+ styles,
129
+ })
130
+
131
+ return <InputBase
132
+ {...inputBaseProps}
133
+ disabled={disabled}
134
+ styles={{
135
+ ...variantStyles,
136
+ innerWrapper: [
137
+ variantStyles.innerWrapper,
138
+ ],
139
+ }}
140
+ debugName={debugName}
141
+ >
142
+ {options?.map((item, idx) => (
143
+ <Option
144
+ debugName={debugName}
145
+ item={item}
146
+ key={idx}
147
+ disabled={disabled}
148
+ styles={variantStyles}
149
+ selected={value === item.value}
150
+ onSelect={() => onValueChange(item.value)}
151
+ separator={idx < options.length - 1}
152
+ />
153
+ ))}
154
+ </InputBase>
155
+ }
@@ -0,0 +1,14 @@
1
+ import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
2
+ import { IconLessInputBaseParts } from '../InputBase'
3
+
4
+ type OptionParts = 'wrapper' | 'label' | 'indicator' | 'indicatorInner' | 'separator'
5
+ type OptionStates = 'selected' | 'disabled' | 'selectedDisabled'
6
+
7
+ type OptionComposition = `${OptionParts}:${OptionStates}` | OptionParts
8
+
9
+ export type RadioInputComposition = IconLessInputBaseParts | `${IconLessInputBaseParts}:disabled` | `option${Capitalize<OptionComposition>}`
10
+
11
+ const createRadioStyle =
12
+ createDefaultVariantFactory<RadioInputComposition>()
13
+
14
+ export const RadioInputPresets = includePresets(style => createRadioStyle(() => ({ wrapper: style })))
@@ -0,0 +1,29 @@
1
+ /** @jsx jsx */
2
+ import {
3
+ ElementType,
4
+ forwardRef,
5
+ ReactElement,
6
+ Ref,
7
+ } from 'react'
8
+ import { View, ViewProps } from '../View'
9
+
10
+ export const ScrollCP = <T extends ElementType = 'div'>(
11
+ props: ViewProps<T>,
12
+ ref: Ref<any>,
13
+ ) => {
14
+
15
+ return (
16
+ <View
17
+ {...props}
18
+ ref={ref}
19
+ scroll
20
+ />
21
+
22
+ )
23
+ }
24
+
25
+ export * from './styles'
26
+
27
+ export const Scroll = forwardRef(ScrollCP) as <T extends ElementType = 'div'>(
28
+ props: ViewProps<T>
29
+ ) => ReactElement
@@ -0,0 +1,8 @@
1
+ import { createDefaultVariantFactory, includePresets } from "@codeleap/common";
2
+ import { ViewComposition } from "../View";
3
+
4
+ export type ScrollCompostion = ViewComposition
5
+
6
+ const createScrollStyle = createDefaultVariantFactory<ScrollCompostion>()
7
+
8
+ export const ScrollPresets = includePresets((styles) => createScrollStyle(() => ({ wrapper: styles })))
@@ -0,0 +1,438 @@
1
+ import React, { useRef, forwardRef, useImperativeHandle } from 'react'
2
+ import { FormTypes, useValidate, useState, TypeGuards, onUpdate } from '@codeleap/common'
3
+ import _Select, { components, MenuListProps, MenuProps, MultiValueProps, NoticeProps } from 'react-select'
4
+ import Async from 'react-select/async'
5
+ import { useSelectStyles } from './styles'
6
+ import { LoadingIndicatorProps, PlaceholderProps, SelectProps, TCustomOption } from './types'
7
+ import { InputBase, selectInputBaseProps } from '../InputBase'
8
+ import { Button } from '../Button'
9
+ import { Text } from '../Text'
10
+ import { View } from '../View'
11
+ import { ActivityIndicator } from '../ActivityIndicator'
12
+ import { CSSInterpolation } from '@emotion/css'
13
+ import { Icon } from '../Icon'
14
+
15
+ export * from './styles'
16
+ export * from './types'
17
+
18
+ const DefaultOption = (props: TCustomOption & { component: (props: TCustomOption) => JSX.Element }) => {
19
+ const { isSelected, optionsStyles, label, selectedIcon, component = null, itemProps = {}, isFocused } = props
20
+
21
+ const styles = optionsStyles({ isSelected, isFocused, baseStyles: (itemProps?.styles ?? {}) })
22
+
23
+ let _Component = null
24
+
25
+ if (TypeGuards.isNil(component)) {
26
+ _Component = () => (
27
+ <Button
28
+ text={label}
29
+ // @ts-ignore
30
+ rightIcon={isSelected && selectedIcon}
31
+ {...itemProps}
32
+ styles={styles}
33
+ />
34
+ )
35
+ } else {
36
+ _Component = component
37
+ }
38
+
39
+ return (
40
+ <components.Option {...props}>
41
+ <_Component {...props} styles={styles} />
42
+ </components.Option>
43
+ )
44
+ }
45
+
46
+ const CustomMenu = (props: MenuProps & { Footer: () => JSX.Element }) => {
47
+ const { Footer, children } = props
48
+
49
+ return <>
50
+ <components.Menu {...props}>
51
+ {children}
52
+ {!!Footer && <Footer />}
53
+ </components.Menu>
54
+ </>
55
+ }
56
+
57
+ const CustomMenuList = (props: MenuListProps & { defaultStyles: { wrapper: React.CSSProperties } }) => {
58
+ const { children, defaultStyles } = props
59
+
60
+ return (
61
+ <components.MenuList {...props}>
62
+ <View style={defaultStyles.wrapper}>
63
+ {children}
64
+ </View>
65
+ </components.MenuList>
66
+ )
67
+ }
68
+
69
+ const DefaultPlaceholder = (props: PlaceholderProps) => {
70
+ const { text: TextPlaceholder, defaultStyles, icon: IconPlaceholder } = props
71
+
72
+ const _Text = () => {
73
+ if (TypeGuards.isNil(TextPlaceholder)) return null
74
+
75
+ if (TypeGuards.isString(TextPlaceholder)) {
76
+ return <Text text={TextPlaceholder} css={[defaultStyles.text]} />
77
+ } else if (React.isValidElement(TextPlaceholder)) {
78
+ return TextPlaceholder
79
+ } else {
80
+ return <TextPlaceholder {...props} />
81
+ }
82
+ }
83
+
84
+ const _Image = () => {
85
+ if (TypeGuards.isNil(IconPlaceholder)) return null
86
+
87
+ if (TypeGuards.isString(IconPlaceholder)) {
88
+ return <Icon name={TextPlaceholder as any} forceStyle={defaultStyles.icon} />
89
+ } else if (React.isValidElement(IconPlaceholder)) {
90
+ // @ts-ignore
91
+ return <View style={defaultStyles.icon}>
92
+ { IconPlaceholder}
93
+ </View>
94
+ } else {
95
+ return <IconPlaceholder {...props} />
96
+ }
97
+ }
98
+
99
+ return (
100
+ <View css={[defaultStyles.wrapper]}>
101
+ <_Image />
102
+ <_Text />
103
+ </View>
104
+ )
105
+ }
106
+
107
+ const LoadingIndicator = (props: LoadingIndicatorProps) => {
108
+ const { defaultStyles, size } = props
109
+
110
+ return (
111
+ <View css={[defaultStyles.wrapper]}>
112
+ <ActivityIndicator size={size} />
113
+ </View>
114
+ )
115
+ }
116
+
117
+ const getMultiValue = (values: { label: string }[], separator: string, state: { searchable: boolean }) => {
118
+ let value = ''
119
+ const hasMulti = values?.length > 1
120
+
121
+ values.forEach(({ label }, i) => {
122
+ const isLast = values?.length - 1 === i
123
+ const txt = (hasMulti && separator)
124
+ ? label + (isLast && !state?.searchable ? '' : separator)
125
+ : label
126
+
127
+ value = value + txt
128
+ })
129
+
130
+ return value
131
+ }
132
+
133
+ const CustomMultiValue = (props: MultiValueProps & { defaultStyles: { text: CSSInterpolation }; separator: string }) => {
134
+ const { selectProps, index, defaultStyles, separator } = props
135
+
136
+ const searchable = selectProps?.isSearchable
137
+
138
+ if (index !== 0 || selectProps.inputValue.length > 0) return null
139
+
140
+ // @ts-ignore
141
+ const text = getMultiValue(selectProps?.value, separator, { searchable })
142
+
143
+ return <Text text={text} css={[defaultStyles.text]} />
144
+ }
145
+
146
+ const defaultFormatPlaceholderNoItems = (props: PlaceholderProps & { text: string }) => {
147
+ return props.text + `"${props.selectProps.inputValue}"`
148
+ }
149
+
150
+ const defaultProps: Partial<SelectProps> = {
151
+ PlaceholderComponent: DefaultPlaceholder,
152
+ PlaceholderNoItemsComponent: DefaultPlaceholder,
153
+ LoadingIndicatorComponent: LoadingIndicator,
154
+ noItemsText: 'No results for ',
155
+ noItemsIcon: 'placeholderNoItems-select',
156
+ placeholderText: 'Search items',
157
+ placeholderIcon: 'placeholder-select',
158
+ showDropdownIcon: true,
159
+ placeholder: 'Select',
160
+ clearable: false,
161
+ formatPlaceholderNoItems: defaultFormatPlaceholderNoItems,
162
+ selectedIcon: 'checkmark',
163
+ searchable: false,
164
+ separatorMultiValue: ', ',
165
+ itemProps: {},
166
+ loadingIndicatorSize: 20,
167
+ options: [],
168
+ }
169
+
170
+ export const Select = forwardRef<HTMLInputElement, SelectProps>(
171
+ <T extends string | number = string, Multi extends boolean = false>
172
+ (props: SelectProps<T, Multi>, inputRef: React.ForwardedRef<HTMLInputElement>) => {
173
+
174
+ type Option = FormTypes.Option<T>
175
+
176
+ const {
177
+ inputBaseProps,
178
+ others: selectProps,
179
+ } = selectInputBaseProps({
180
+ ...Select.defaultProps,
181
+ ...props,
182
+ })
183
+
184
+ const {
185
+ variants,
186
+ validate,
187
+ styles,
188
+ debugName,
189
+ onValueChange,
190
+ options,
191
+ value,
192
+ loadOptions,
193
+ multiple,
194
+ limit = null,
195
+ focused,
196
+ _error,
197
+ renderItem: OptionComponent = null,
198
+ FooterComponent = null,
199
+ PlaceholderComponent,
200
+ PlaceholderNoItemsComponent,
201
+ LoadingIndicatorComponent,
202
+ noItemsText,
203
+ noItemsIcon,
204
+ placeholderText,
205
+ placeholderIcon,
206
+ showDropdownIcon,
207
+ placeholder,
208
+ clearable,
209
+ formatPlaceholderNoItems,
210
+ closeOnSelect = !multiple,
211
+ selectedIcon,
212
+ onLoadOptionsError,
213
+ loadOptionsOnMount = options?.length === 0,
214
+ searchable,
215
+ separatorMultiValue,
216
+ filterItems = null,
217
+ itemProps = {},
218
+ loadingIndicatorSize,
219
+ ...otherProps
220
+ } = selectProps
221
+
222
+ const innerInputRef = useRef<any>(null)
223
+ const innerWrapperRef = useRef(null)
224
+
225
+ const [selectedOption, setSelectedOption] = useState(value)
226
+
227
+ const [_isFocused, setIsFocused] = useState(false)
228
+
229
+ const [keyDownActive, setKeyDownActive] = useState(false)
230
+
231
+ const isFocused = _isFocused || focused
232
+
233
+ // @ts-ignore
234
+ const validation = useValidate(value, validate)
235
+
236
+ const isDisabled = !!inputBaseProps.disabled
237
+
238
+ const hasError = !validation.isValid || _error
239
+ const errorMessage = validation.message || _error
240
+
241
+ const {
242
+ reactSelectStyles,
243
+ variantStyles,
244
+ optionsStyles,
245
+ placeholderStyles,
246
+ loadingStyles,
247
+ inputMultiValueStyles,
248
+ menuWrapperStyles,
249
+ } = useSelectStyles(props, {
250
+ error: !!hasError,
251
+ focused: isFocused,
252
+ disabled: isDisabled,
253
+ })
254
+
255
+ useImperativeHandle(inputRef, () => {
256
+ return {
257
+ ...innerInputRef.current,
258
+ focus: () => {
259
+ innerInputRef.current?.focus?.()
260
+ },
261
+ }
262
+ }, [!!innerInputRef?.current?.focus])
263
+
264
+ const onLoadOptions = async (inputValue, cb) => {
265
+ if (!!loadOptions) {
266
+ try {
267
+ const _options = await loadOptions(inputValue).then((options) => {
268
+ cb(options)
269
+ return options
270
+ })
271
+
272
+ return _options
273
+ } catch (err) {
274
+ onLoadOptionsError?.(err)
275
+ }
276
+
277
+ return
278
+ }
279
+ }
280
+
281
+ const handleChange = (opt: Multi extends true ? Option[] : Option) => {
282
+ if (TypeGuards.isArray(opt)) {
283
+ // @ts-ignore
284
+ if (TypeGuards.isNumber(limit) && opt?.length > limit && opt?.length > selectedOption?.length) {
285
+ return
286
+ }
287
+ // @ts-ignore
288
+ setSelectedOption(opt)
289
+ // @ts-ignore
290
+ onValueChange?.(opt?.map((o) => o?.value))
291
+ } else {
292
+ // @ts-ignore
293
+ setSelectedOption(opt)
294
+ // @ts-ignore
295
+ onValueChange?.(opt?.value)
296
+ }
297
+ }
298
+
299
+ const handleBlur: SelectProps['onBlur'] = React.useCallback((e) => {
300
+ validation?.onInputBlurred()
301
+ setIsFocused(false)
302
+ props?.onBlur?.(e)
303
+ }, [validation?.onInputBlurred, props?.onBlur])
304
+
305
+ const handleFocus: SelectProps['onFocus'] = React.useCallback((e) => {
306
+ validation?.onInputFocused()
307
+ setIsFocused(true)
308
+ props?.onFocus?.(e)
309
+ }, [validation?.onInputFocused, props?.onFocus])
310
+
311
+ const SelectComponent = !!loadOptions ? Async : _Select
312
+
313
+ const componentProps = {
314
+ focused: isFocused,
315
+ error: !!hasError,
316
+ disabled: isDisabled,
317
+ variantStyles,
318
+ }
319
+
320
+ const _Placeholder = (props: NoticeProps) => {
321
+ const hasInputValue = !!props.selectProps.inputValue
322
+ const styles = placeholderStyles[hasInputValue ? 'noItems' : 'empty']
323
+ const icon = hasInputValue ? noItemsIcon : placeholderIcon
324
+
325
+ const placeholderProps = {
326
+ ...props,
327
+ ...componentProps,
328
+ icon,
329
+ defaultStyles: styles,
330
+ }
331
+
332
+ if (!hasInputValue) {
333
+ return <PlaceholderComponent {...placeholderProps} text={placeholderText} />
334
+ } else {
335
+ const _Text = TypeGuards.isString(noItemsText) ? formatPlaceholderNoItems({ ...placeholderProps, text: noItemsText }) : noItemsText
336
+ return <PlaceholderNoItemsComponent {...placeholderProps} text={_Text} />
337
+ }
338
+ }
339
+
340
+ const _props = {
341
+ ...(!filterItems ? {} : { filterOption: filterItems }),
342
+ }
343
+
344
+ onUpdate(() => {
345
+ if (!_isFocused) {
346
+ setKeyDownActive(false)
347
+ }
348
+ }, [_isFocused])
349
+
350
+ const handleKeyDown = () => {
351
+ setKeyDownActive(true)
352
+ }
353
+
354
+ return (
355
+ <InputBase
356
+ {...inputBaseProps}
357
+ debugName={debugName}
358
+ error={hasError ? errorMessage : null}
359
+ focused={isFocused}
360
+ styles={{
361
+ ...variantStyles,
362
+ innerWrapper: [
363
+ variantStyles.innerWrapper,
364
+ searchable && variantStyles['innerWrapper:searchable'],
365
+ ],
366
+ }}
367
+ innerWrapperProps={{
368
+ ...(inputBaseProps.innerWrapperProps || {}),
369
+ onClick: () => {
370
+ innerInputRef.current?.focus?.()
371
+ },
372
+ }}
373
+ innerWrapperRef={innerWrapperRef}
374
+ >
375
+ <SelectComponent
376
+ openMenuOnFocus={true}
377
+ hideSelectedOptions={false}
378
+ tabSelectsValue={false}
379
+ tabIndex={0}
380
+ {...otherProps}
381
+ {..._props}
382
+ onKeyDown={isFocused ? handleKeyDown : null}
383
+ onBlur={handleBlur}
384
+ onFocus={handleFocus}
385
+ onChange={handleChange}
386
+ styles={reactSelectStyles}
387
+ value={selectedOption as any}
388
+ isMulti={multiple}
389
+ options={options}
390
+ loadOptions={onLoadOptions as any}
391
+ defaultOptions={loadOptionsOnMount}
392
+ ref={innerInputRef}
393
+ closeMenuOnSelect={closeOnSelect}
394
+ menuPortalTarget={innerWrapperRef.current}
395
+ placeholder={placeholder}
396
+ isDisabled={isDisabled}
397
+ isClearable={clearable}
398
+ isSearchable={searchable}
399
+ components={{
400
+ LoadingIndicator: () => null,
401
+ ...otherProps.components,
402
+ MultiValueRemove: () => null,
403
+ LoadingMessage: props => (
404
+ <LoadingIndicatorComponent
405
+ {...props}
406
+ defaultStyles={loadingStyles}
407
+ size={loadingIndicatorSize}
408
+ />
409
+ ),
410
+ DropdownIndicator: props => showDropdownIcon ? <components.DropdownIndicator {...props} /> : null,
411
+ NoOptionsMessage: props => <_Placeholder {...props} />,
412
+ Menu: props => <CustomMenu {...props} Footer={FooterComponent} />,
413
+ MenuList: props => <CustomMenuList {...props} defaultStyles={menuWrapperStyles} />,
414
+ Option: props => (
415
+ <DefaultOption
416
+ {...props}
417
+ {...componentProps}
418
+ itemProps={itemProps}
419
+ selectedIcon={selectedIcon}
420
+ optionsStyles={optionsStyles}
421
+ component={OptionComponent}
422
+ isFocused={props?.isFocused && keyDownActive}
423
+ />
424
+ ),
425
+ MultiValue: props => (
426
+ <CustomMultiValue
427
+ {...props}
428
+ separator={separatorMultiValue}
429
+ defaultStyles={inputMultiValueStyles}
430
+ />
431
+ ),
432
+ }}
433
+ />
434
+ </InputBase>
435
+ )
436
+ })
437
+
438
+ Select.defaultProps = defaultProps