@codeleap/web 2.4.7 → 3.0.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 (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,103 @@
1
+ import { VariableSizeList as VirtualList , VariableSizeListProps} from 'react-window'
2
+ import { ComponentProps, CSSProperties, ReactElement } from 'react'
3
+ import AutoSizer from 'react-virtualized-auto-sizer'
4
+ import {
5
+ ComponentVariants,
6
+ useDefaultComponentStyle
7
+ } from '@codeleap/common'
8
+ import { StylesOf } from '../../types/utility'
9
+ import { CSSObject } from '@emotion/react'
10
+ import { ListComposition, ListPresets } from './styles'
11
+
12
+ export type ListRender<T> = (itemProps: {
13
+ item: T
14
+ index: number
15
+ style: CSSProperties
16
+ }) => ReactElement
17
+
18
+ export * from './styles'
19
+
20
+ export type ListProps<T> = {
21
+ styles?: StylesOf<ListComposition>
22
+ css?: CSSObject
23
+ data: T[]
24
+ getSize: (i: T, idx: number) => number
25
+ renderItem: ListRender<T>
26
+ } & Omit<
27
+ VariableSizeListProps,
28
+ | 'itemCount'
29
+ | 'itemSize'
30
+ | 'itemData'
31
+ | 'itemHeight'
32
+ | 'width'
33
+ | 'height'
34
+ | 'children'
35
+ > &
36
+ ComponentVariants<typeof ListPresets>
37
+
38
+ export const List = <T extends unknown>(
39
+ listProps: ListProps<T>,
40
+ ) => {
41
+ const {
42
+ variants,
43
+ responsiveVariants,
44
+ styles,
45
+ data,
46
+ getSize,
47
+ renderItem: Item,
48
+ ...viewProps
49
+ } = listProps
50
+
51
+ const variantStyles = useDefaultComponentStyle('View', {
52
+ variants,
53
+ responsiveVariants,
54
+ styles,
55
+ })
56
+
57
+ return (
58
+ // @ts-ignore
59
+ <AutoSizer>
60
+ {({ height, width }) => (
61
+ // @ts-ignore
62
+ <VirtualList
63
+ height={height}
64
+ width={width}
65
+ itemCount={data.length}
66
+ itemData={data}
67
+ itemSize={(idx) => getSize(data[idx], idx)}
68
+ css={variantStyles.wrapper}
69
+ {...viewProps}
70
+ >
71
+ {({ style, index }) => (
72
+ <Item item={data[index]} style={style} index={index} />
73
+ )}
74
+ </VirtualList>
75
+ )}
76
+ </AutoSizer>
77
+ )
78
+
79
+ // return <View {...viewProps}>
80
+ // {data.map((item, idx) => <Component item={item} idx={idx} key={idx}/>)}
81
+ // </View>
82
+ }
83
+
84
+ // const rowHeights = new Array(1000)
85
+ // .fill(true)
86
+ // .map(() => 25 + Math.round(Math.random() * 50));
87
+
88
+ // const getItemSize = index => rowHeights[index];
89
+
90
+ // const Row = ({ index, style }) => (
91
+ // <div style={style}>Row {index}</div>
92
+ // );
93
+
94
+ // const Example = () => (
95
+ // <List
96
+ // height={150}
97
+ // itemCount={1000}
98
+ // itemSize={getItemSize}
99
+ // width={300}
100
+ // >
101
+ // {Row}
102
+ // </List>
103
+ // );
@@ -0,0 +1,8 @@
1
+ import { createDefaultVariantFactory, includePresets } from "@codeleap/common";
2
+ import { ViewComposition } from "../View";
3
+
4
+ export type ListComposition = ViewComposition
5
+
6
+ const createListStyles = createDefaultVariantFactory<ListComposition>()
7
+
8
+ export const ListPresets = includePresets((styles) => createListStyles(() => ({ wrapper: styles })))
@@ -0,0 +1,34 @@
1
+ import { ComponentVariants, useDefaultComponentStyle } from "@codeleap/common"
2
+ import React from "react"
3
+ import { StylesOf } from "../.."
4
+ import { LoadingOverlayComposition, LoadingOverlayPresets } from "./styles"
5
+ import {View} from '../View'
6
+ import { ActivityIndicator } from "../ActivityIndicator"
7
+
8
+ export type LoadingOverlayProps = React.PropsWithChildren<{
9
+ visible?: boolean
10
+ styles?: StylesOf<LoadingOverlayComposition>
11
+ }> & ComponentVariants<typeof LoadingOverlayPresets>
12
+
13
+
14
+ export const LoadingOverlay = (props: LoadingOverlayProps) => {
15
+ const { visible, children, styles, variants,responsiveVariants } = props
16
+
17
+ const variantStyles = useDefaultComponentStyle<'u:LoadingOverlay', typeof LoadingOverlayPresets>('u:LoadingOverlay', {
18
+ variants, styles, responsiveVariants, rootElement: 'wrapper'
19
+ })
20
+
21
+ return <View css={[variantStyles.wrapper, visible && variantStyles["wrapper:visible"]]}>
22
+ <ActivityIndicator
23
+ styles={{
24
+ wrapper: [variantStyles.indicatorWrapper, visible && variantStyles["indicatorWrapper:visible"]],
25
+ backCircle: [variantStyles.indicatorBackCircle, visible && variantStyles["indicatorBackCircle:visible"]],
26
+ frontCircle: [variantStyles.indicatorFrontCircle, visible && variantStyles["indicatorFrontCircle:visible"]],
27
+ circle: [variantStyles.indicatorCircle, visible && variantStyles["indicatorCircle:visible"]],
28
+ }}
29
+ />
30
+ {children}
31
+ </View>
32
+ }
33
+
34
+ export * from './styles'
@@ -0,0 +1,12 @@
1
+ import { createDefaultVariantFactory, includePresets } from "@codeleap/common";
2
+ import { ActivityIndicatorComposition } from "../ActivityIndicator";
3
+
4
+ type LoadingOverlayStates = 'visible'
5
+
6
+ export type LoadingOverlayParts = 'wrapper' | `indicator${Capitalize<ActivityIndicatorComposition>}`
7
+
8
+ export type LoadingOverlayComposition = `${LoadingOverlayParts}:${LoadingOverlayStates}` | LoadingOverlayParts
9
+
10
+ export const createLoadingOverlayStyle = createDefaultVariantFactory<LoadingOverlayComposition>()
11
+
12
+ export const LoadingOverlayPresets = includePresets(s => createLoadingOverlayStyle(() => ({wrapper: s})))
@@ -0,0 +1,189 @@
1
+ /** @jsx jsx */
2
+ import { jsx } from '@emotion/react'
3
+
4
+ import {
5
+ AnyFunction,
6
+ ComponentVariants,
7
+ IconPlaceholder,
8
+ onUpdate,
9
+ useDefaultComponentStyle,
10
+ useNestedStylesByKey,
11
+ } from '@codeleap/common'
12
+
13
+ import { ReactNode, useEffect, useId, useLayoutEffect, useRef } from 'react'
14
+ import ReactDOM from 'react-dom'
15
+
16
+ import { v4 } from 'uuid'
17
+
18
+ import { StylesOf } from '../../types/utility'
19
+ import { Button } from '../Button'
20
+ import { View } from '../View'
21
+ import { Text } from '../Text'
22
+ import { Overlay } from '../Overlay'
23
+
24
+ import {ModalComposition,ModalPresets} from './styles'
25
+ import { ActionIcon } from '../ActionIcon'
26
+
27
+ export * from './styles'
28
+
29
+ export type ModalProps = React.PropsWithChildren<{
30
+ visible: boolean
31
+ title?: React.ReactNode
32
+ toggle: AnyFunction
33
+ styles?: StylesOf<ModalComposition>
34
+ accessible?: boolean
35
+ showClose?: boolean
36
+ closable?: boolean
37
+ scroll?: boolean
38
+ footer?: ReactNode
39
+ debugName?: string
40
+ } & ComponentVariants<typeof ModalPresets>
41
+ >
42
+ function focusModal(event: FocusEvent, id: string) {
43
+ event.preventDefault()
44
+ const modal = document.getElementById(id)
45
+ if (modal) {
46
+ modal.focus()
47
+ }
48
+ }
49
+ export const ModalContent: React.FC<ModalProps & { id: string }> = (
50
+ modalProps,
51
+ ) => {
52
+ const {
53
+ children,
54
+ closable = true,
55
+ visible,
56
+ title = '',
57
+ toggle,
58
+ responsiveVariants,
59
+ variants,
60
+ styles,
61
+ showClose = true,
62
+ footer,
63
+ ...props
64
+ } = modalProps
65
+
66
+ const id = useId()
67
+
68
+ const variantStyles = useDefaultComponentStyle<'u:Modal', typeof ModalPresets>('u:Modal', {
69
+ responsiveVariants,
70
+ variants,
71
+ styles,
72
+ })
73
+
74
+ onUpdate(() => {
75
+ if (visible) {
76
+ document.body.style.overflow = 'hidden'
77
+ } else {
78
+ document.body.style.overflow = 'auto'
79
+
80
+ }
81
+ }, [visible])
82
+
83
+ function closeOnEscPress(e: React.KeyboardEvent<HTMLDivElement>) {
84
+ if (e.key === 'Escape') {
85
+ toggle()
86
+ }
87
+ }
88
+
89
+ useLayoutEffect(() => {
90
+ const modal = document.getElementById(id)
91
+ if (modal) {
92
+ modal.focus()
93
+ }
94
+ }, [id])
95
+
96
+ const closeButtonStyles = useNestedStylesByKey('closeButton', variantStyles)
97
+ const close = closable ? toggle : () => {}
98
+ return (
99
+ <View
100
+ aria-hidden={!visible}
101
+ css={[variantStyles.wrapper, visible ? variantStyles['wrapper:visible'] : variantStyles['wrapper:hidden']]}
102
+ >
103
+ <Overlay
104
+ visible={visible}
105
+
106
+ css={[variantStyles.backdrop, visible ? variantStyles['backdrop:visible'] : variantStyles['backdrop:hidden'] ]}
107
+ />
108
+ <View css={variantStyles.innerWrapper} >
109
+ <View css={variantStyles.backdropPressable} onClick={close}/>
110
+ <View
111
+ component='section'
112
+ css={[variantStyles.box, visible ? variantStyles['box:visible'] : variantStyles['box:hidden']]}
113
+ className='content'
114
+ onKeyDown={closeOnEscPress}
115
+ tabIndex={0}
116
+ id={id}
117
+ aria-modal={true}
118
+ role='dialog'
119
+ aria-describedby={`${id}-title`}
120
+ aria-label='Close the modal by presing Escape key'
121
+ {...props}
122
+ >
123
+ {(title || showClose) && (
124
+ <View
125
+ component='header'
126
+ className='modal-header header'
127
+ id={`${id}-title`}
128
+ css={variantStyles.header}
129
+ >
130
+ {typeof title === 'string' ? <Text text={title} css={variantStyles.title} /> : title}
131
+
132
+ {showClose && closable && (
133
+ <ActionIcon
134
+ icon={'close' as IconPlaceholder}
135
+
136
+ onPress={toggle}
137
+ styles={closeButtonStyles}
138
+ />
139
+ )}
140
+ </View>
141
+ )}
142
+
143
+ <View css={variantStyles.body}>{children}</View>
144
+ {footer && (
145
+ <View component='footer' css={variantStyles.footer}>
146
+ {footer}
147
+ </View>
148
+ )}
149
+ </View>
150
+ </View>
151
+ </View>
152
+ )
153
+ }
154
+
155
+ export const Modal: React.FC<ModalProps> = ({ accessible, ...props }) => {
156
+ const modalId = useRef(v4())
157
+
158
+ useEffect(() => {
159
+ if (accessible) {
160
+ const currentId = modalId.current
161
+ const appRoot = document.body
162
+ appRoot.addEventListener('focusin', (e) => focusModal(e, currentId))
163
+ return () => appRoot.removeEventListener('focusin', (e) => focusModal(e, currentId))
164
+ }
165
+ }, [])
166
+
167
+ useEffect(() => {
168
+ if (accessible) {
169
+ const appRoot = document.body
170
+ appRoot.setAttribute('aria-hidden', `${props.visible}`)
171
+ appRoot.setAttribute('tabindex', `${-1}`)
172
+ }
173
+ }, [props.visible])
174
+
175
+ if (accessible) {
176
+ if (props.visible) {
177
+ document.body.style.overflow = 'hidden'
178
+ return ReactDOM.createPortal(
179
+ <ModalContent {...props} id={modalId.current} />,
180
+ document.body,
181
+ )
182
+ } else {
183
+ document.body.style.overflow = 'visible'
184
+ return null
185
+ }
186
+ }
187
+
188
+ return <ModalContent {...props} id={modalId.current} />
189
+ }
@@ -0,0 +1,26 @@
1
+ import {
2
+ createDefaultVariantFactory,
3
+ includePresets,
4
+ } from '@codeleap/common'
5
+ import { ActionIconComposition } from '../ActionIcon'
6
+
7
+ export type AnimatableParts = 'box' | 'backdrop' | 'wrapper'
8
+
9
+ export type ModalParts =
10
+ | AnimatableParts
11
+ | 'body'
12
+ | 'footer'
13
+ | 'header'
14
+ | 'title'
15
+ | 'innerWrapper'
16
+ | 'backdropPressable'
17
+ | `closeButton${Capitalize<ActionIconComposition>}`
18
+
19
+ export type ModalComposition =
20
+ | ModalParts
21
+ | `${AnimatableParts}:visible`
22
+ | `${AnimatableParts}:hidden`
23
+
24
+ const createModalStyle = createDefaultVariantFactory<ModalComposition>()
25
+
26
+ export const ModalPresets = includePresets((style) => createModalStyle(() => ({ body: style })))
@@ -0,0 +1,292 @@
1
+ import * as React from 'react'
2
+ import {
3
+ ComponentVariants,
4
+ yup,
5
+ useDefaultComponentStyle,
6
+ StylesOf,
7
+ PropsOf,
8
+ TypeGuards,
9
+ onUpdate,
10
+ useState,
11
+ useRef,
12
+ useValidate,
13
+ FormTypes,
14
+ IconPlaceholder,
15
+ } from '@codeleap/common'
16
+ import { View } from '../View'
17
+ import { NumberIncrementPresets, NumberIncrementComposition } from './styles'
18
+ import { InputBase, InputBaseProps, selectInputBaseProps } from '../InputBase'
19
+ import { Text } from '../Text'
20
+ import {
21
+ PatternFormat,
22
+ PatternFormatProps as PFProps,
23
+ NumericFormat,
24
+ NumericFormatProps as NFProps,
25
+ NumberFormatBase,
26
+ } from 'react-number-format'
27
+ import { FormatInputValueFunction } from 'react-number-format/types/types'
28
+
29
+ export * from './styles'
30
+
31
+ export type NumberIncrementProps = Pick<
32
+ InputBaseProps,
33
+ 'debugName' | 'disabled' | 'label'
34
+ > & {
35
+ variants?: ComponentVariants<typeof NumberIncrementPresets>['variants']
36
+ styles?: StylesOf<NumberIncrementComposition>
37
+ value: number
38
+ onValueChange: (value: number) => void
39
+ onChangeText?: (value: number) => void
40
+ validate?: FormTypes.ValidatorWithoutForm<string> | yup.SchemaOf<string>
41
+ style?: PropsOf<typeof View>['style']
42
+ max?: number
43
+ min?: number
44
+ step?: number
45
+ editable?: boolean
46
+ prefix?: NFProps['prefix']
47
+ suffix?: NFProps['suffix']
48
+ separator?: NFProps['thousandSeparator']
49
+ format?: PFProps['format']
50
+ mask?: PFProps['mask']
51
+ hasSeparator?: boolean
52
+ _error?: string
53
+ formatter?: FormatInputValueFunction
54
+ placeholder?: string
55
+ }
56
+
57
+ export const NumberIncrement = (props: NumberIncrementProps) => {
58
+ const {
59
+ inputBaseProps,
60
+ others,
61
+ } = selectInputBaseProps(props)
62
+
63
+ const {
64
+ variants = [],
65
+ style = {},
66
+ styles = {},
67
+ value,
68
+ disabled,
69
+ onValueChange,
70
+ onChangeText,
71
+ max = 1000000000,
72
+ min = 0,
73
+ step = 1,
74
+ editable = true,
75
+ hasSeparator = false,
76
+ format = null,
77
+ mask = undefined,
78
+ suffix,
79
+ separator = null,
80
+ prefix,
81
+ validate,
82
+ _error,
83
+ formatter = null,
84
+ placeholder,
85
+ } = others
86
+
87
+ const [isFocused, setIsFocused] = useState(false)
88
+
89
+ const innerWrapperRef = useRef(null)
90
+ const innerInputRef = useRef<HTMLInputElement>(null)
91
+
92
+ const validation = useValidate(value, validate)
93
+
94
+ const hasError = !validation.isValid || _error
95
+ const errorMessage = validation.message || _error
96
+
97
+ const incrementDisabled = React.useMemo(() => {
98
+ if (TypeGuards.isNumber(max) && (Number(value) >= max)) {
99
+ return true
100
+ }
101
+ return false
102
+ }, [value])
103
+
104
+ const decrementDisabled = React.useMemo(() => {
105
+ if (TypeGuards.isNumber(min) && (Number(value) <= min)) {
106
+ return true
107
+ }
108
+ return false
109
+ }, [value])
110
+
111
+ const variantStyles = useDefaultComponentStyle<'u:NumberIncrement', typeof NumberIncrementPresets>(
112
+ 'u:NumberIncrement',
113
+ {
114
+ variants,
115
+ styles,
116
+ rootElement: 'wrapper',
117
+ },
118
+ )
119
+
120
+ const onChange = (newValue: number) => {
121
+ if (onValueChange) onValueChange?.(newValue)
122
+ if (onChangeText) onChangeText?.(newValue)
123
+ }
124
+
125
+ const handleChange = React.useCallback((action: 'increment' | 'decrement') => {
126
+ validation?.onInputFocused()
127
+
128
+ if (action === 'increment' && !incrementDisabled) {
129
+ const newValue = Number(value) + step
130
+ onChange(newValue)
131
+ return
132
+ } else if (action === 'decrement' && !decrementDisabled) {
133
+ const newValue = Number(value) - step
134
+ onChange(newValue)
135
+ return
136
+ }
137
+
138
+ validation?.onInputBlurred()
139
+ }, [validation?.onInputBlurred, validation?.onInputFocused, value])
140
+
141
+ const inputTextStyle = React.useMemo(() => {
142
+ return [
143
+ variantStyles.input,
144
+ isFocused && variantStyles['input:focus'],
145
+ hasError && variantStyles['input:error'],
146
+ disabled && variantStyles['input:disabled'],
147
+ ]
148
+ }, [disabled, isFocused, hasError])
149
+
150
+ const placeholderStyles = [
151
+ variantStyles.placeholder,
152
+ isFocused && variantStyles['placeholder:focus'],
153
+ hasError && variantStyles['placeholder:error'],
154
+ disabled && variantStyles['placeholder:disabled'],
155
+ ]
156
+
157
+ const handleBlur = React.useCallback(() => {
158
+ if (TypeGuards.isNumber(max) && (value >= max)) {
159
+ onChange(max)
160
+ return
161
+ } else if (TypeGuards.isNumber(min) && (value <= min) || !value) {
162
+ onChange(min)
163
+ return
164
+ }
165
+
166
+ validation?.onInputBlurred()
167
+ }, [validation?.onInputBlurred, value])
168
+
169
+ const handleFocus = React.useCallback(() => {
170
+ validation?.onInputFocused()
171
+ setIsFocused(true)
172
+ }, [validation?.onInputFocused])
173
+
174
+ onUpdate(() => {
175
+ function handleKeyboardEvent(event: KeyboardEvent) {
176
+ if (!isFocused) return
177
+
178
+ if (event.keyCode === 39 || event.key === 'ArrowRight') {
179
+ handleChange('increment')
180
+ } else if (event.keyCode === 37 || event.key === 'ArrowLeft') {
181
+ handleChange('decrement')
182
+ }
183
+ }
184
+
185
+ document.addEventListener('keydown', handleKeyboardEvent)
186
+
187
+ return () => {
188
+ document.removeEventListener('keydown', handleKeyboardEvent)
189
+ }
190
+ }, [handleChange, isFocused])
191
+
192
+ onUpdate(() => {
193
+ function handleClickOutside(event: MouseEvent) {
194
+ if (innerWrapperRef.current && !innerWrapperRef.current.contains(event.target)) {
195
+ setIsFocused(false)
196
+ }
197
+ }
198
+
199
+ document.addEventListener('mousedown', handleClickOutside)
200
+
201
+ return () => {
202
+ document.removeEventListener('mousedown', handleClickOutside)
203
+ }
204
+ }, [innerWrapperRef])
205
+
206
+ const handleChangeInput: NFProps['onValueChange'] = (values) => {
207
+ const { floatValue } = values
208
+
209
+ onChange(Number(floatValue))
210
+ }
211
+
212
+ const InputFormat = TypeGuards.isString(format) || TypeGuards.isString(mask)
213
+ ? PatternFormat
214
+ : NumericFormat
215
+
216
+ const Input = TypeGuards.isFunction(formatter)
217
+ ? NumberFormatBase
218
+ : InputFormat
219
+
220
+ return (
221
+ <InputBase
222
+ {...inputBaseProps}
223
+ error={hasError ? errorMessage : null}
224
+ styles={{
225
+ ...variantStyles,
226
+ innerWrapper: [
227
+ variantStyles.innerWrapper,
228
+ editable && variantStyles['innerWrapper:cursor'],
229
+ ],
230
+ }}
231
+ rightIcon={{
232
+ name: 'plus' as IconPlaceholder,
233
+ disabled: disabled || incrementDisabled,
234
+ onPress: () => handleChange('increment'),
235
+ component: 'button',
236
+ ...inputBaseProps.rightIcon,
237
+ }}
238
+ leftIcon={{
239
+ name: 'minus' as IconPlaceholder,
240
+ disabled: disabled || decrementDisabled,
241
+ onPress: () => handleChange('decrement'),
242
+ component: 'button',
243
+ ...inputBaseProps.leftIcon,
244
+ }}
245
+ style={style}
246
+ disabled={disabled}
247
+ focused={isFocused}
248
+ innerWrapperProps={{
249
+ ...(inputBaseProps.innerWrapperProps || {}),
250
+ onClick: () => {
251
+ setIsFocused(true)
252
+ innerInputRef.current?.focus?.()
253
+ },
254
+ }}
255
+ innerWrapperRef={innerWrapperRef}
256
+ >
257
+ {editable && !disabled ? (
258
+ <Input
259
+ displayType='input'
260
+ css={[
261
+ ...inputTextStyle,
262
+ {
263
+ '&::placeholder': placeholderStyles,
264
+ },
265
+ {
266
+ '&:focus': [
267
+ {
268
+ outline: 'none',
269
+ borderWidth: 0,
270
+ borderColor: 'transparent',
271
+ },
272
+ ],
273
+ },
274
+ ]}
275
+ inputMode='numeric'
276
+ onValueChange={handleChangeInput}
277
+ onBlur={handleBlur}
278
+ onFocus={handleFocus}
279
+ value={value}
280
+ thousandSeparator={separator}
281
+ thousandsGroupStyle={hasSeparator || TypeGuards.isString(separator) ? 'thousand' : 'none'}
282
+ suffix={suffix}
283
+ prefix={prefix}
284
+ format={TypeGuards.isFunction(formatter) ? formatter as any : format}
285
+ mask={mask}
286
+ placeholder={placeholder}
287
+ getInputRef={innerInputRef}
288
+ />
289
+ ) : <Text text={String(value)} css={inputTextStyle} />}
290
+ </InputBase>
291
+ )
292
+ }
@@ -0,0 +1,15 @@
1
+ import { createDefaultVariantFactory, includePresets } from '@codeleap/common'
2
+ import { InputBaseParts } from '../InputBase'
3
+
4
+ export type NumberIncrementParts = InputBaseParts | 'input' | 'placeholder'
5
+
6
+ export type NumberIncrementStates = 'disabled' | 'focus' | 'error'
7
+
8
+ export type NumberIncrementComposition =
9
+ | NumberIncrementParts
10
+ | `${NumberIncrementParts}:${NumberIncrementStates}`
11
+ | `innerWrapper:cursor`
12
+
13
+ const createNumberIncrementStyle = createDefaultVariantFactory<NumberIncrementComposition>()
14
+
15
+ export const NumberIncrementPresets = includePresets((styles) => createNumberIncrementStyle(() => ({ wrapper: styles })))