@chem-po/react-native 0.0.19 → 0.0.21

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 (59) hide show
  1. package/lib/commonjs/components/button/ActionButton.js +97 -0
  2. package/lib/commonjs/components/button/ActionButton.js.map +1 -0
  3. package/lib/commonjs/components/button/index.js +11 -0
  4. package/lib/commonjs/components/button/index.js.map +1 -1
  5. package/lib/commonjs/components/feed/MediaFeed.js +3 -4
  6. package/lib/commonjs/components/feed/MediaFeed.js.map +1 -1
  7. package/lib/commonjs/components/form/input/Editable.js +3 -3
  8. package/lib/commonjs/components/form/input/Editable.js.map +1 -1
  9. package/lib/commonjs/components/form/input/file/index.js +6 -1
  10. package/lib/commonjs/components/form/input/file/index.js.map +1 -1
  11. package/lib/commonjs/components/loading/Loading.js +1 -55
  12. package/lib/commonjs/components/loading/Loading.js.map +1 -1
  13. package/lib/commonjs/components/loading/LoadingOverlay.js +66 -0
  14. package/lib/commonjs/components/loading/LoadingOverlay.js.map +1 -0
  15. package/lib/commonjs/components/loading/index.js +11 -0
  16. package/lib/commonjs/components/loading/index.js.map +1 -1
  17. package/lib/commonjs/hooks/useFadeIn.js +45 -0
  18. package/lib/commonjs/hooks/useFadeIn.js.map +1 -0
  19. package/lib/module/components/button/ActionButton.js +88 -0
  20. package/lib/module/components/button/ActionButton.js.map +1 -0
  21. package/lib/module/components/button/index.js +1 -0
  22. package/lib/module/components/button/index.js.map +1 -1
  23. package/lib/module/components/feed/MediaFeed.js +2 -3
  24. package/lib/module/components/feed/MediaFeed.js.map +1 -1
  25. package/lib/module/components/form/input/Editable.js +2 -2
  26. package/lib/module/components/form/input/Editable.js.map +1 -1
  27. package/lib/module/components/form/input/file/index.js +7 -2
  28. package/lib/module/components/form/input/file/index.js.map +1 -1
  29. package/lib/module/components/loading/Loading.js +2 -55
  30. package/lib/module/components/loading/Loading.js.map +1 -1
  31. package/lib/module/components/loading/LoadingOverlay.js +57 -0
  32. package/lib/module/components/loading/LoadingOverlay.js.map +1 -0
  33. package/lib/module/components/loading/index.js +1 -0
  34. package/lib/module/components/loading/index.js.map +1 -1
  35. package/lib/module/hooks/useFadeIn.js +38 -0
  36. package/lib/module/hooks/useFadeIn.js.map +1 -0
  37. package/lib/typescript/components/button/ActionButton.d.ts +15 -0
  38. package/lib/typescript/components/button/ActionButton.d.ts.map +1 -0
  39. package/lib/typescript/components/button/index.d.ts +1 -0
  40. package/lib/typescript/components/button/index.d.ts.map +1 -1
  41. package/lib/typescript/components/form/input/file/index.d.ts.map +1 -1
  42. package/lib/typescript/components/loading/Loading.d.ts +0 -6
  43. package/lib/typescript/components/loading/Loading.d.ts.map +1 -1
  44. package/lib/typescript/components/loading/LoadingOverlay.d.ts +17 -0
  45. package/lib/typescript/components/loading/LoadingOverlay.d.ts.map +1 -0
  46. package/lib/typescript/components/loading/index.d.ts +1 -0
  47. package/lib/typescript/components/loading/index.d.ts.map +1 -1
  48. package/lib/typescript/hooks/useFadeIn.d.ts +10 -0
  49. package/lib/typescript/hooks/useFadeIn.d.ts.map +1 -0
  50. package/package.json +3 -3
  51. package/src/components/button/ActionButton.tsx +108 -0
  52. package/src/components/button/index.ts +1 -0
  53. package/src/components/feed/MediaFeed.tsx +2 -2
  54. package/src/components/form/input/Editable.tsx +2 -2
  55. package/src/components/form/input/file/index.tsx +5 -1
  56. package/src/components/loading/Loading.tsx +2 -67
  57. package/src/components/loading/LoadingOverlay.tsx +64 -0
  58. package/src/components/loading/index.ts +1 -0
  59. package/src/hooks/useFadeIn.ts +48 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/loading/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/loading/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAA;AAClC,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,iBAAiB,CAAA"}
@@ -0,0 +1,10 @@
1
+ import { Animated } from 'react-native';
2
+ export interface FadeInOptions {
3
+ activeOpacity?: number;
4
+ inactiveOpacity?: number;
5
+ duration?: number;
6
+ enterDelay?: number;
7
+ exitDelay?: number;
8
+ }
9
+ export declare const useFadeIn: (active: boolean, opts?: FadeInOptions) => Animated.Value;
10
+ //# sourceMappingURL=useFadeIn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFadeIn.d.ts","sourceRoot":"","sources":["../../../src/hooks/useFadeIn.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEvC,MAAM,WAAW,aAAa;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AASD,eAAO,MAAM,SAAS,GAAI,QAAQ,OAAO,EAAE,OAAO,aAAa,mBA6B9D,CAAA"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@chem-po/react-native",
3
3
  "author": "Elan Canfield",
4
4
  "license": "MIT",
5
- "version": "0.0.19",
5
+ "version": "0.0.21",
6
6
  "main": "lib/commonjs/index.js",
7
7
  "types": "lib/typescript/index.d.ts",
8
8
  "source": "src/index.ts",
@@ -49,8 +49,8 @@
49
49
  "react-native-paper-dates": "^0.22.42",
50
50
  "react-native-svg": "15.11.2",
51
51
  "zustand": "^4.3.3",
52
- "@chem-po/react": "0.0.19",
53
- "@chem-po/core": "0.0.19"
52
+ "@chem-po/core": "0.0.21",
53
+ "@chem-po/react": "0.0.21"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@babel/core": "^7.26.0",
@@ -0,0 +1,108 @@
1
+ import { palette } from '@chem-po/core'
2
+ import { useBackgroundColor } from '@chem-po/react'
3
+ import React, { PropsWithChildren } from 'react'
4
+ import { Pressable, StyleProp, StyleSheet, TextStyle, ViewStyle } from 'react-native'
5
+ import { WithLoadingOverlay } from '../loading/LoadingOverlay'
6
+ import { Txt } from '../text'
7
+
8
+ export interface ActionButtonProps
9
+ extends PropsWithChildren<{
10
+ onPress: () => void
11
+ style?: StyleProp<ViewStyle>
12
+ disabled?: boolean
13
+ size?: 'lg' | 'md' | 'sm' | 'xs'
14
+ }> {
15
+ textStyle?: StyleProp<TextStyle>
16
+ disabledColor?: string
17
+ loading?: boolean
18
+ }
19
+ export const ActionButton = ({
20
+ children,
21
+ onPress,
22
+ style,
23
+ textStyle,
24
+ disabled = false,
25
+ loading,
26
+ size = 'md',
27
+ disabledColor = palette.gray.medium,
28
+ }: ActionButtonProps) => {
29
+ const defaultBackgroundColor = useBackgroundColor(300)
30
+ const backgroundColor = disabled ? disabledColor : defaultBackgroundColor
31
+ const body =
32
+ typeof children === 'string' ? (
33
+ <Txt
34
+ style={[
35
+ textStyles[size],
36
+ { color: disabled ? disabledColor : defaultBackgroundColor },
37
+ textStyle,
38
+ ]}>
39
+ {children}
40
+ </Txt>
41
+ ) : (
42
+ children
43
+ )
44
+ return (
45
+ <Pressable
46
+ style={[containerStyles.base, containerStyles[size], { backgroundColor }, style]}
47
+ onPress={onPress}
48
+ disabled={disabled}>
49
+ {loading !== undefined ? (
50
+ <WithLoadingOverlay loading={loading}>{body}</WithLoadingOverlay>
51
+ ) : (
52
+ body
53
+ )}
54
+ </Pressable>
55
+ )
56
+ }
57
+
58
+ export const RoundedButton = ({ style, ...props }: ActionButtonProps) => {
59
+ return <ActionButton style={[styles.rounded, style]} {...props} />
60
+ }
61
+
62
+ const styles = StyleSheet.create({
63
+ rounded: {
64
+ borderRadius: 100,
65
+ },
66
+ })
67
+
68
+ const containerStyles = StyleSheet.create({
69
+ base: {
70
+ justifyContent: 'center',
71
+ alignItems: 'center',
72
+ },
73
+ lg: {
74
+ paddingVertical: 10,
75
+ paddingHorizontal: 16,
76
+ borderRadius: 5,
77
+ },
78
+ md: {
79
+ paddingVertical: 8,
80
+ paddingHorizontal: 16,
81
+ borderRadius: 4,
82
+ },
83
+ sm: {
84
+ paddingVertical: 6,
85
+ paddingHorizontal: 12,
86
+ borderRadius: 3,
87
+ },
88
+ xs: {
89
+ paddingVertical: 4,
90
+ paddingHorizontal: 8,
91
+ borderRadius: 2,
92
+ },
93
+ })
94
+
95
+ const textStyles = StyleSheet.create({
96
+ lg: {
97
+ fontSize: 18,
98
+ },
99
+ md: {
100
+ fontSize: 16,
101
+ },
102
+ sm: {
103
+ fontSize: 14,
104
+ },
105
+ xs: {
106
+ fontSize: 12,
107
+ },
108
+ })
@@ -1,3 +1,4 @@
1
+ export * from './ActionButton'
1
2
  export * from './DeleteButton'
2
3
  export * from './LoadingButton'
3
4
  export * from './Toggle'
@@ -18,7 +18,7 @@ import {
18
18
  } from 'react-native-gesture-handler'
19
19
  import { fill } from '../../styles/fill'
20
20
  import { Center } from '../box/Center'
21
- import { LoadingOverlay } from '../loading/Loading'
21
+ import { LoadingOverlay } from '../loading/LoadingOverlay'
22
22
  import { REFRESH_THRESHOLD, SWIPE_THRESHOLD } from './constants'
23
23
  import { MediaFeedProvider } from './context'
24
24
  import { FeedContentPane } from './FeedContentPane'
@@ -183,7 +183,7 @@ export const MediaFeed = <T extends AnyObject = AnyObject>({
183
183
  </View>
184
184
  <MediaFeedRefresh canRefresh={!canGoPrev} refreshing={refreshing} offsetY={offsetY} />
185
185
  {/* {onSwipeUp ? <MediaFeedSwipeUp offsetY={offsetY} /> : null} */}
186
- <LoadingOverlay inFeed isLoading={loading} />
186
+ <LoadingOverlay loading={loading} />
187
187
  {children ? <Center style={[fill.absolute, { zIndex: 3 }]}>{children}</Center> : null}
188
188
  </Center>
189
189
  </GestureDetector>
@@ -9,7 +9,7 @@ import {
9
9
  import { Ionicons } from '@expo/vector-icons'
10
10
  import React, { useCallback, useEffect, useMemo } from 'react'
11
11
  import { StyleSheet, TouchableOpacity, View, ViewStyle } from 'react-native'
12
- import { LoadingOverlay } from '../../loading/Loading'
12
+ import { LoadingOverlay } from '../../loading/LoadingOverlay'
13
13
  import { UploadProgress } from '../UploadProgress'
14
14
  import { FieldView } from '../view'
15
15
  import { StandaloneInput } from './StandaloneInput'
@@ -203,7 +203,7 @@ export const Editable = <T extends Field>({
203
203
  </View>
204
204
  </View>
205
205
  )}
206
- <LoadingOverlay isLoading={isLoading} />
206
+ <LoadingOverlay loading={isLoading} />
207
207
  </View>
208
208
  <UploadProgress uploads={uploads} />
209
209
  </View>
@@ -3,6 +3,7 @@ import {
3
3
  FileField,
4
4
  useBorderColor,
5
5
  useIconColor,
6
+ useObjectUrl,
6
7
  usePlaceholderColor,
7
8
  useTextColor,
8
9
  } from '@chem-po/react'
@@ -55,6 +56,8 @@ export const FileView = ({
55
56
  const { storagePath, dataUrl } = value ?? {}
56
57
  const missingFile = !dataUrl && !storagePath
57
58
 
59
+ const { url, loading } = useObjectUrl(value)
60
+
58
61
  const iconColor = useIconColor()
59
62
  const fileNameColor = useTextColor()
60
63
  const borderColor = useBorderColor()
@@ -65,7 +68,8 @@ export const FileView = ({
65
68
  if (value.type?.startsWith('image/')) {
66
69
  return (
67
70
  <LoadingImage
68
- src={dataUrl}
71
+ src={url}
72
+ loadingOverride={loading}
69
73
  width={imageOptions?.width ?? 120}
70
74
  height={imageOptions?.height ?? 120}
71
75
  style={styles.image}
@@ -1,7 +1,7 @@
1
1
  import { ThemedAsset, useAppAssets, useTheme } from '@chem-po/react'
2
2
  import LottieView from 'lottie-react-native'
3
- import React, { useEffect, useMemo, useState } from 'react'
4
- import { Animated, Image, StyleSheet, Text, View, ViewStyle } from 'react-native'
3
+ import React, { useMemo } from 'react'
4
+ import { Image, StyleSheet, Text, View, ViewStyle } from 'react-native'
5
5
 
6
6
  export const LottieLoadingLogo = ({
7
7
  size = 30,
@@ -124,62 +124,6 @@ export const Loading = ({
124
124
  return inBox ? <View style={styles.boxContainer}>{body}</View> : body
125
125
  }
126
126
 
127
- export const LoadingOverlay = ({
128
- isLoading,
129
- text,
130
- inFeed,
131
- style,
132
- }: {
133
- isLoading: boolean
134
- text?: string
135
- inFeed?: boolean
136
- style?: ViewStyle
137
- }) => {
138
- const { colorMode } = useTheme()
139
- const bgColor = colorMode === 'dark' ? 'rgba(0, 0, 0, 0.53)' : 'rgba(255, 255, 255, 0.67)'
140
- const opacity = useMemo(() => new Animated.Value(0), [])
141
- const [isAnimating, setIsAnimating] = useState(false)
142
-
143
- useEffect(() => {
144
- if (isLoading) {
145
- setIsAnimating(true)
146
- Animated.timing(opacity, {
147
- toValue: 1,
148
- duration: 200,
149
- useNativeDriver: true,
150
- }).start()
151
- } else {
152
- Animated.timing(opacity, {
153
- toValue: 0,
154
- duration: 200,
155
- useNativeDriver: true,
156
- }).start(() => {
157
- setIsAnimating(false)
158
- })
159
- }
160
- }, [isLoading, opacity])
161
-
162
- if (!isLoading && !isAnimating) return null
163
-
164
- return (
165
- <Animated.View
166
- style={[
167
- styles.overlay,
168
- {
169
- backgroundColor: bgColor,
170
- opacity,
171
- },
172
- style,
173
- ]}>
174
- {!text ? (
175
- <LoadingLogo inFeed={inFeed} size={100} isLoading={isLoading} />
176
- ) : (
177
- <Loading text={text} />
178
- )}
179
- </Animated.View>
180
- )
181
- }
182
-
183
127
  const styles = StyleSheet.create({
184
128
  loadingContainer: {
185
129
  flexDirection: 'row',
@@ -196,15 +140,6 @@ const styles = StyleSheet.create({
196
140
  borderRadius: 8,
197
141
  backgroundColor: 'rgba(0, 0, 0, 0.05)',
198
142
  },
199
- overlay: {
200
- position: 'absolute',
201
- top: 0,
202
- left: 0,
203
- right: 0,
204
- bottom: 0,
205
- justifyContent: 'center',
206
- alignItems: 'center',
207
- },
208
143
  errorText: {
209
144
  color: 'red',
210
145
  },
@@ -0,0 +1,64 @@
1
+ import React, { useMemo } from 'react'
2
+ import { Animated, StyleProp, StyleSheet, ViewStyle } from 'react-native'
3
+ import { FadeInOptions, useFadeIn } from '../../hooks/useFadeIn'
4
+ import { CircularProgress } from './CircularProgress'
5
+
6
+ const loadingFadeInProps: FadeInOptions = {
7
+ activeOpacity: 0.5,
8
+ duration: 100,
9
+ }
10
+ interface LoadingOverlayProps {
11
+ loading: boolean
12
+ fadeOptions?: FadeInOptions
13
+ style?: StyleProp<ViewStyle>
14
+ }
15
+ export const LoadingOverlay = ({ loading, fadeOptions, style }: LoadingOverlayProps) => {
16
+ const opts = useMemo(() => ({ ...loadingFadeInProps, ...fadeOptions }), [fadeOptions])
17
+ const opacity = useFadeIn(loading, opts)
18
+
19
+ return (
20
+ <Animated.View
21
+ style={[styles.overlay, style, { opacity, pointerEvents: loading ? 'auto' : 'none' }]}>
22
+ <CircularProgress />
23
+ </Animated.View>
24
+ )
25
+ }
26
+
27
+ const withOverlayLoadingFadeIn: FadeInOptions = {
28
+ enterDelay: 250,
29
+ }
30
+ export const WithLoadingOverlay = ({
31
+ loading,
32
+ children,
33
+ style,
34
+ overlayStyle,
35
+ }: {
36
+ loading: boolean
37
+ children: React.ReactNode
38
+ style?: StyleProp<ViewStyle>
39
+ overlayStyle?: StyleProp<ViewStyle>
40
+ }) => {
41
+ const bodyOpacity = useFadeIn(!loading, withOverlayLoadingFadeIn)
42
+ return (
43
+ <>
44
+ <Animated.View style={[style, { opacity: bodyOpacity }]}>{children}</Animated.View>
45
+ <LoadingOverlay
46
+ fadeOptions={withOverlayLoadingFadeIn}
47
+ loading={loading}
48
+ style={overlayStyle}
49
+ />
50
+ </>
51
+ )
52
+ }
53
+
54
+ const styles = StyleSheet.create({
55
+ overlay: {
56
+ position: 'absolute',
57
+ justifyContent: 'center',
58
+ alignItems: 'center',
59
+ left: 0,
60
+ right: 0,
61
+ top: 0,
62
+ bottom: 0,
63
+ },
64
+ })
@@ -1,4 +1,5 @@
1
1
  export * from './CircularProgress'
2
2
  export * from './Loading'
3
3
  export * from './LoadingImage'
4
+ export * from './LoadingOverlay'
4
5
  export * from './LoadingSwitch'
@@ -0,0 +1,48 @@
1
+ import { useEffect, useRef } from 'react'
2
+ import { Animated } from 'react-native'
3
+
4
+ export interface FadeInOptions {
5
+ activeOpacity?: number
6
+ inactiveOpacity?: number
7
+ duration?: number
8
+ enterDelay?: number
9
+ exitDelay?: number
10
+ }
11
+
12
+ const defaultFadeInOptions: FadeInOptions = {
13
+ activeOpacity: 1,
14
+ inactiveOpacity: 0,
15
+ duration: 250,
16
+ enterDelay: 0,
17
+ exitDelay: 0,
18
+ }
19
+ export const useFadeIn = (active: boolean, opts?: FadeInOptions) => {
20
+ const {
21
+ activeOpacity = 1,
22
+ inactiveOpacity = 0,
23
+ duration = 300,
24
+ enterDelay = 0,
25
+ exitDelay = 0,
26
+ } = opts ?? defaultFadeInOptions
27
+ const opacity = useRef(new Animated.Value(0))
28
+
29
+ useEffect(() => {
30
+ if (active) {
31
+ Animated.timing(opacity.current, {
32
+ toValue: activeOpacity,
33
+ duration,
34
+ useNativeDriver: true,
35
+ delay: enterDelay,
36
+ }).start()
37
+ } else {
38
+ Animated.timing(opacity.current, {
39
+ toValue: inactiveOpacity,
40
+ duration,
41
+ useNativeDriver: true,
42
+ delay: exitDelay,
43
+ }).start()
44
+ }
45
+ }, [active, activeOpacity, inactiveOpacity, duration, enterDelay, exitDelay])
46
+
47
+ return opacity.current
48
+ }