react95-native-rabbl 0.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 (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +24 -0
  3. package/package.json +154 -0
  4. package/src/assets/fonts/src/ms-sans-serif/MS Sans Serif.ttf +0 -0
  5. package/src/assets/fonts/src/ms-sans-serif/license.txt +4 -0
  6. package/src/assets/fonts/src/ms-sans-serif/readme.txt +26 -0
  7. package/src/assets/fonts/src/ms-sans-serif-bold/MS Sans Serif Bold.ttf +0 -0
  8. package/src/assets/fonts/src/ms-sans-serif-bold/license.txt +4 -0
  9. package/src/assets/fonts/src/ms-sans-serif-bold/readme.txt +26 -0
  10. package/src/components/AppBar/AppBar.spec.tsx +140 -0
  11. package/src/components/AppBar/AppBar.tsx +43 -0
  12. package/src/components/AppBar/AppBarBackAction.tsx +20 -0
  13. package/src/components/AppBar/AppBarContent.tsx +84 -0
  14. package/src/components/AppBar/index.ts +1 -0
  15. package/src/components/Button/Button.spec.tsx +59 -0
  16. package/src/components/Button/Button.tsx +236 -0
  17. package/src/components/Button/index.ts +1 -0
  18. package/src/components/Card/Card.spec.tsx +54 -0
  19. package/src/components/Card/Card.tsx +88 -0
  20. package/src/components/Card/CardContent.tsx +23 -0
  21. package/src/components/Card/index.ts +1 -0
  22. package/src/components/Checkbox/Checkbox.tsx +10 -0
  23. package/src/components/Checkbox/index.ts +1 -0
  24. package/src/components/ColorButton/ColorButton.tsx +69 -0
  25. package/src/components/ColorButton/index.ts +1 -0
  26. package/src/components/ColorPicker/ColorPicker.tsx +109 -0
  27. package/src/components/ColorPicker/index.ts +1 -0
  28. package/src/components/Desktop/Desktop.spec.tsx +32 -0
  29. package/src/components/Desktop/Desktop.tsx +132 -0
  30. package/src/components/Desktop/index.tsx +1 -0
  31. package/src/components/Divider/Divider.spec.tsx +47 -0
  32. package/src/components/Divider/Divider.tsx +52 -0
  33. package/src/components/Divider/index.tsx +1 -0
  34. package/src/components/FAB/FAB.tsx +288 -0
  35. package/src/components/FAB/FABGroup.tsx +385 -0
  36. package/src/components/FAB/index.ts +1 -0
  37. package/src/components/Fieldset/Fieldset.spec.tsx +48 -0
  38. package/src/components/Fieldset/Fieldset.tsx +107 -0
  39. package/src/components/Fieldset/index.ts +1 -0
  40. package/src/components/Hourglass/Hourglass.spec.tsx +24 -0
  41. package/src/components/Hourglass/Hourglass.tsx +43 -0
  42. package/src/components/Hourglass/base64hourglass.ts +3 -0
  43. package/src/components/Hourglass/index.ts +1 -0
  44. package/src/components/Icons/ArrowIcon.tsx +85 -0
  45. package/src/components/Icons/CheckmarkIcon.tsx +55 -0
  46. package/src/components/Icons/ChevronIcon.tsx +93 -0
  47. package/src/components/Icons/CloseIcon.tsx +48 -0
  48. package/src/components/Icons/index.ts +4 -0
  49. package/src/components/Label/Label.tsx +77 -0
  50. package/src/components/Label/index.ts +1 -0
  51. package/src/components/List/List.tsx +3 -0
  52. package/src/components/List/ListAccordion.tsx +154 -0
  53. package/src/components/List/ListItem.tsx +74 -0
  54. package/src/components/List/ListSection.tsx +51 -0
  55. package/src/components/List/index.ts +3 -0
  56. package/src/components/Menu/Menu.tsx +100 -0
  57. package/src/components/Menu/MenuItem.tsx +100 -0
  58. package/src/components/Menu/index.ts +1 -0
  59. package/src/components/NumberInput/NumberInput.spec.tsx +119 -0
  60. package/src/components/NumberInput/NumberInput.tsx +144 -0
  61. package/src/components/NumberInput/index.ts +1 -0
  62. package/src/components/Panel/Panel.spec.tsx +29 -0
  63. package/src/components/Panel/Panel.tsx +75 -0
  64. package/src/components/Panel/index.ts +1 -0
  65. package/src/components/Portal/Portal.tsx +52 -0
  66. package/src/components/Portal/PortalConsumer.tsx +48 -0
  67. package/src/components/Portal/PortalHost.tsx +150 -0
  68. package/src/components/Portal/PortalManager.tsx +57 -0
  69. package/src/components/Portal/index.ts +1 -0
  70. package/src/components/Progress/Progress.tsx +125 -0
  71. package/src/components/Progress/index.ts +1 -0
  72. package/src/components/Radio/Radio.tsx +14 -0
  73. package/src/components/Radio/index.ts +1 -0
  74. package/src/components/ScrollPanel/ScrollPanel.tsx +72 -0
  75. package/src/components/ScrollPanel/index.ts +1 -0
  76. package/src/components/ScrollView/ScrollView.tsx +284 -0
  77. package/src/components/ScrollView/index.ts +1 -0
  78. package/src/components/Select/Select.tsx +229 -0
  79. package/src/components/Select/SelectBase.tsx +119 -0
  80. package/src/components/Select/SelectBox.tsx +66 -0
  81. package/src/components/Select/index.ts +2 -0
  82. package/src/components/Slider/Slider.tsx +301 -0
  83. package/src/components/Slider/index.ts +1 -0
  84. package/src/components/Snackbar/Snackbar.tsx +260 -0
  85. package/src/components/Snackbar/SnackbarContent.tsx +23 -0
  86. package/src/components/Snackbar/index.ts +1 -0
  87. package/src/components/SwitchBase/SwitchBase.tsx +193 -0
  88. package/src/components/SwitchBase/index.ts +1 -0
  89. package/src/components/Tabs/Tabs.tsx +208 -0
  90. package/src/components/Tabs/index.ts +1 -0
  91. package/src/components/TextInput/TextInput.tsx +82 -0
  92. package/src/components/TextInput/index.ts +1 -0
  93. package/src/components/Toolbar/Toolbar.tsx +113 -0
  94. package/src/components/Toolbar/index.ts +1 -0
  95. package/src/components/Typography/Anchor.tsx +38 -0
  96. package/src/components/Typography/Text.spec.tsx +30 -0
  97. package/src/components/Typography/Text.tsx +55 -0
  98. package/src/components/Typography/Title.tsx +58 -0
  99. package/src/components/Typography/index.ts +3 -0
  100. package/src/components/Window/Window.tsx +132 -0
  101. package/src/components/Window/index.ts +1 -0
  102. package/src/core/Provider.tsx +52 -0
  103. package/src/core/theming.tsx +8 -0
  104. package/src/hooks/useAsyncReference.ts +22 -0
  105. package/src/hooks/useControlledOrUncontrolled.ts +23 -0
  106. package/src/index.ts +38 -0
  107. package/src/styles/shadow.tsx +36 -0
  108. package/src/styles/styleElements.tsx +105 -0
  109. package/src/styles/styles.ts +129 -0
  110. package/src/styles/themes/aiee.ts +36 -0
  111. package/src/styles/themes/ash.ts +35 -0
  112. package/src/styles/themes/azureOrange.ts +33 -0
  113. package/src/styles/themes/bee.ts +33 -0
  114. package/src/styles/themes/blackAndWhite.ts +33 -0
  115. package/src/styles/themes/blue.ts +36 -0
  116. package/src/styles/themes/brick.ts +33 -0
  117. package/src/styles/themes/candy.ts +33 -0
  118. package/src/styles/themes/cherry.ts +36 -0
  119. package/src/styles/themes/coldGray.ts +34 -0
  120. package/src/styles/themes/counterStrike.ts +33 -0
  121. package/src/styles/themes/darkTeal.ts +36 -0
  122. package/src/styles/themes/eggplant.ts +33 -0
  123. package/src/styles/themes/fxDev.ts +36 -0
  124. package/src/styles/themes/highContrast.ts +33 -0
  125. package/src/styles/themes/hotChocolate.ts +36 -0
  126. package/src/styles/themes/index.ts +103 -0
  127. package/src/styles/themes/lilac.ts +33 -0
  128. package/src/styles/themes/lilacRoseDark.ts +34 -0
  129. package/src/styles/themes/maple.ts +33 -0
  130. package/src/styles/themes/marine.ts +33 -0
  131. package/src/styles/themes/matrix.ts +33 -0
  132. package/src/styles/themes/millenium.ts +33 -0
  133. package/src/styles/themes/modernDark.ts +33 -0
  134. package/src/styles/themes/molecule.ts +33 -0
  135. package/src/styles/themes/monochrome.ts +0 -0
  136. package/src/styles/themes/ninjaTurtles.ts +33 -0
  137. package/src/styles/themes/olive.ts +33 -0
  138. package/src/styles/themes/original.ts +33 -0
  139. package/src/styles/themes/pamelaAnderson.ts +33 -0
  140. package/src/styles/themes/plum.ts +33 -0
  141. package/src/styles/themes/polarized.ts +36 -0
  142. package/src/styles/themes/powerShell.ts +36 -0
  143. package/src/styles/themes/rainyDay.ts +33 -0
  144. package/src/styles/themes/raspberry.ts +36 -0
  145. package/src/styles/themes/redWine.ts +36 -0
  146. package/src/styles/themes/rose.ts +33 -0
  147. package/src/styles/themes/seawater.ts +36 -0
  148. package/src/styles/themes/slate.ts +33 -0
  149. package/src/styles/themes/solarizedDark.ts +36 -0
  150. package/src/styles/themes/solarizedLight.ts +36 -0
  151. package/src/styles/themes/spruce.ts +33 -0
  152. package/src/styles/themes/stormClouds.ts +36 -0
  153. package/src/styles/themes/theSixtiesUSA.ts +33 -0
  154. package/src/styles/themes/tokyoDark.ts +33 -0
  155. package/src/styles/themes/tooSexy.ts +33 -0
  156. package/src/styles/themes/travel.ts +33 -0
  157. package/src/styles/themes/vaporTeal.ts +33 -0
  158. package/src/styles/themes/vermillion.ts +33 -0
  159. package/src/styles/themes/violetDark.ts +33 -0
  160. package/src/styles/themes/water.ts +33 -0
  161. package/src/styles/themes/wmii.ts +36 -0
  162. package/src/types.tsx +55 -0
  163. package/src/utils/index.ts +57 -0
@@ -0,0 +1,301 @@
1
+ import React, { useRef, useState, useEffect } from 'react';
2
+ import {
3
+ StyleProp,
4
+ StyleSheet,
5
+ View,
6
+ ViewStyle,
7
+ LayoutChangeEvent,
8
+ GestureResponderEvent,
9
+ PanResponder,
10
+ ImageBackground,
11
+ } from 'react-native';
12
+ import useAsyncReference from '../../hooks/useAsyncReference';
13
+
14
+ import type { Theme, $RemoveChildren } from '../../types';
15
+ import { withTheme } from '../../core/theming';
16
+
17
+ import { buildBorderStyles } from '../../styles/styles';
18
+ import { Border } from '../../styles/styleElements';
19
+ import { clamp, roundValueToStep, findClosest } from '../../utils';
20
+
21
+ import { Panel, Text, Label } from '../..';
22
+
23
+ function percentToValue(percent: number, min: number, max: number) {
24
+ return (max - min) * percent + min;
25
+ }
26
+
27
+ type Mark = { value: number; label?: string };
28
+
29
+ type Props = $RemoveChildren<typeof View> & {
30
+ disabled?: boolean;
31
+ marks?: Mark[] | boolean;
32
+ max?: number;
33
+ min?: number;
34
+ onChange?: (a: number) => void;
35
+ onChangeCommitted?: (a: number) => void;
36
+ step?: number | null;
37
+ style?: StyleProp<ViewStyle>;
38
+ theme: Theme;
39
+ value?: number;
40
+ };
41
+
42
+ const Slider = ({
43
+ disabled = false,
44
+ marks: marksProp,
45
+ max = 100,
46
+ min = 0,
47
+ onChange,
48
+ onChangeCommitted,
49
+ step = 1,
50
+ style,
51
+ theme,
52
+ value = 0,
53
+ ...rest
54
+ }: Props) => {
55
+ const [isUsed, setIsUsed] = useState(false);
56
+
57
+ let marks: Mark[];
58
+ // if marks is set to true, we only show ticks at specified steps
59
+ if (marksProp === true && step !== null) {
60
+ marks = [...Array(Math.round((max - min) / step) + 1)].map((_, index) => ({
61
+ value: min + step * index,
62
+ }));
63
+ // otherwise we display ticks and optional labels specified by the developer
64
+ } else if (Array.isArray(marksProp)) {
65
+ marks = marksProp;
66
+ // otherwise don't display any marks or labels
67
+ } else {
68
+ marks = [];
69
+ }
70
+
71
+ const [sliderSize, setSliderSize] = useAsyncReference(0);
72
+ const handleLayout = (e: LayoutChangeEvent) => {
73
+ setSliderSize(e.nativeEvent.layout.width);
74
+ };
75
+
76
+ const getNewValue = (e: GestureResponderEvent) => {
77
+ const percent = clamp(e.nativeEvent.locationX / sliderSize.current, 0, 1);
78
+ let newValue = percentToValue(percent, min, max);
79
+
80
+ if (step) {
81
+ newValue = roundValueToStep(newValue, step, min);
82
+ } else {
83
+ const marksValues = marks.map(mark => mark.value);
84
+ const closestIndex = findClosest(marksValues, newValue);
85
+ newValue = marksValues[closestIndex];
86
+ }
87
+ newValue = clamp(newValue, min, max);
88
+ return newValue;
89
+ };
90
+
91
+ // TODO: is this a good approach?
92
+ const valueRef = useRef(value);
93
+ useEffect(() => {
94
+ valueRef.current = value;
95
+ }, [value]);
96
+
97
+ const handleChange = (newValue: number) => {
98
+ if (valueRef.current !== newValue) {
99
+ onChange?.(newValue);
100
+ }
101
+ };
102
+
103
+ const panResponder = useRef(
104
+ PanResponder.create({
105
+ onStartShouldSetPanResponder: () => true,
106
+ onStartShouldSetPanResponderCapture: () => true,
107
+ onMoveShouldSetPanResponder: () => true,
108
+ onMoveShouldSetPanResponderCapture: () => true,
109
+ onPanResponderStart: e => {
110
+ setIsUsed(true);
111
+ const newValue = getNewValue(e);
112
+ handleChange(newValue);
113
+ },
114
+ onPanResponderMove: e => {
115
+ const newValue = getNewValue(e);
116
+ handleChange(newValue);
117
+ },
118
+ onPanResponderEnd: e => {
119
+ setIsUsed(false);
120
+ const newValue = getNewValue(e);
121
+ onChangeCommitted?.(newValue);
122
+ },
123
+ onPanResponderTerminationRequest: () => true,
124
+ }),
125
+ ).current;
126
+
127
+ const borderStyles = buildBorderStyles(theme);
128
+ return (
129
+ <View
130
+ style={[styles.wrapper, style]}
131
+ {...rest}
132
+ accessibilityRole='adjustable'
133
+ accessibilityState={{ disabled }}
134
+ accessibilityValue={{
135
+ min,
136
+ max,
137
+ now: value,
138
+ }}
139
+ >
140
+ <View
141
+ style={[
142
+ styles.inner,
143
+ isUsed
144
+ ? borderStyles.focusOutline
145
+ : { borderWidth: 2, borderColor: 'transparent' },
146
+ ]}
147
+ >
148
+ <View
149
+ pointerEvents={disabled ? 'none' : 'auto'}
150
+ style={[styles.track]}
151
+ onLayout={handleLayout}
152
+ {...panResponder.panHandlers}
153
+ >
154
+ <View style={[styles.trackInner]}>
155
+ <Border theme={theme} variant='cutout' />
156
+ {/* THUMB */}
157
+ <Panel
158
+ theme={theme}
159
+ pointerEvents='none'
160
+ style={[
161
+ styles.thumb,
162
+ {
163
+ left: `${(100 * (value - min)) / (max - min)}%`,
164
+ },
165
+ ]}
166
+ >
167
+ {disabled && (
168
+ <ImageBackground
169
+ style={{
170
+ flex: 1,
171
+ }}
172
+ imageStyle={{
173
+ resizeMode: 'repeat',
174
+ }}
175
+ source={{
176
+ // TODO: create util function for generating checkered background
177
+ uri:
178
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAIUlEQVQoU2P8////fwYkwMjIyIjCp4MCZPtAbAwraa8AAEGrH/nfAIhgAAAAAElFTkSuQmCC',
179
+ }}
180
+ />
181
+ )}
182
+ {isUsed && (
183
+ <View style={styles.tooltipWrapper}>
184
+ <Label elevation={4} style={styles.tooltip}>
185
+ {value}
186
+ </Label>
187
+ </View>
188
+ )}
189
+ </Panel>
190
+ </View>
191
+ </View>
192
+ {marks && (
193
+ <View style={styles.marksWrapper}>
194
+ {marks.map((m: Mark, index: number) => (
195
+ <View
196
+ style={[
197
+ styles.mark,
198
+
199
+ {
200
+ position: index === 0 ? 'relative' : 'absolute',
201
+ left: `${((m.value - min) / (max - min)) * 100}%`,
202
+ },
203
+ ]}
204
+ key={(m.value / (max - min)) * 100}
205
+ >
206
+ <View
207
+ style={[
208
+ styles.tick,
209
+ {
210
+ backgroundColor: disabled
211
+ ? theme.materialTextDisabled
212
+ : theme.materialText,
213
+ // TODO: util function to create disabled shadows
214
+ shadowColor: disabled
215
+ ? theme.materialTextDisabledShadow
216
+ : 'transparent',
217
+ shadowOffset: {
218
+ width: 1,
219
+ height: 1,
220
+ },
221
+ shadowOpacity: 1,
222
+ shadowRadius: 0,
223
+ },
224
+ ]}
225
+ />
226
+ {m.label ? (
227
+ <Text style={styles.markText} disabled={disabled}>
228
+ {m.label}
229
+ </Text>
230
+ ) : null}
231
+ </View>
232
+ ))}
233
+ </View>
234
+ )}
235
+ </View>
236
+ </View>
237
+ );
238
+ };
239
+
240
+ const thumbWidth = 18;
241
+ const thumbHeight = 32;
242
+ const tickSize = 6;
243
+
244
+ const styles = StyleSheet.create({
245
+ wrapper: {
246
+ paddingVertical: 4,
247
+ },
248
+ inner: {
249
+ position: 'relative',
250
+ paddingHorizontal: 16,
251
+ },
252
+ track: {
253
+ paddingVertical: thumbHeight / 2,
254
+ },
255
+ trackInner: {
256
+ height: 8,
257
+ width: '100%',
258
+ alignItems: 'center',
259
+ justifyContent: 'center',
260
+ },
261
+ thumb: {
262
+ position: 'absolute',
263
+ width: thumbWidth,
264
+ height: thumbHeight,
265
+ transform: [
266
+ {
267
+ translateX: -thumbWidth / 2,
268
+ },
269
+ ],
270
+ },
271
+ tooltipWrapper: {
272
+ position: 'absolute',
273
+ top: -44,
274
+ left: thumbWidth / 2,
275
+ alignItems: 'center',
276
+ },
277
+ tooltip: {
278
+ position: 'absolute',
279
+ alignItems: 'center',
280
+ justifyContent: 'center',
281
+ },
282
+ marksWrapper: {
283
+ position: 'relative',
284
+ },
285
+ mark: {
286
+ transform: [{ translateX: -1 }],
287
+ },
288
+ tick: {
289
+ height: tickSize,
290
+ marginBottom: 2,
291
+ width: 2,
292
+ },
293
+ markText: {
294
+ fontSize: 14,
295
+ // TODO: is there a way to translate by 0.5 of a character width?
296
+ // tick should centered above
297
+ transform: [{ translateX: -2 }],
298
+ },
299
+ });
300
+
301
+ export default withTheme(Slider);
@@ -0,0 +1 @@
1
+ export { default } from './Slider';
@@ -0,0 +1,260 @@
1
+ import * as React from 'react';
2
+ import {
3
+ Animated,
4
+ SafeAreaView,
5
+ StyleProp,
6
+ StyleSheet,
7
+ ViewStyle,
8
+ View,
9
+ ImageBackground,
10
+ TouchableOpacity,
11
+ } from 'react-native';
12
+
13
+ import type { Theme } from '../../types';
14
+ import { withTheme } from '../../core/theming';
15
+ import { Text } from '../..';
16
+
17
+ type Props = React.ComponentProps<typeof Animated.View> & {
18
+ /**
19
+ * Whether the Snackbar is currently visible.
20
+ */
21
+ visible: boolean;
22
+ /**
23
+ * Label and press callback for the action button. It should contain the following properties:
24
+ * - `label` - Label of the action button
25
+ * - `onPress` - Callback that is called when action button is pressed.
26
+ */
27
+ action?: {
28
+ label: string;
29
+ accessibilityLabel?: string;
30
+ onPress: () => void;
31
+ };
32
+ /**
33
+ * The duration for which the Snackbar is shown.
34
+ */
35
+ duration?: number;
36
+ /**
37
+ * Callback called when Snackbar is dismissed. The `visible` prop needs to be updated when this is called.
38
+ */
39
+ onDismiss: () => void;
40
+ /**
41
+ * Text content of the Snackbar.
42
+ */
43
+ children: React.ReactNode;
44
+ /**
45
+ * Style for the wrapper of the snackbar
46
+ */
47
+ wrapperStyle?: StyleProp<ViewStyle>;
48
+ style?: StyleProp<ViewStyle>;
49
+ ref?: React.RefObject<View>;
50
+ /**
51
+ * @optional
52
+ */
53
+ theme: Theme;
54
+ };
55
+
56
+ const DURATION_SHORT = 4000;
57
+ const DURATION_MEDIUM = 7000;
58
+ const DURATION_LONG = 10000;
59
+
60
+ const shadowOffset = 8;
61
+ const radius = 4;
62
+
63
+ const Snackbar = ({
64
+ visible,
65
+ action,
66
+ duration = DURATION_MEDIUM,
67
+ onDismiss,
68
+ children,
69
+ wrapperStyle,
70
+ style,
71
+ theme,
72
+ ...rest
73
+ }: Props) => {
74
+ const { current: opacity } = React.useRef<Animated.Value>(
75
+ new Animated.Value(0.0),
76
+ );
77
+ const [hidden, setHidden] = React.useState<boolean>(!visible);
78
+
79
+ const hideTimeout = React.useRef<NodeJS.Timeout | undefined>(undefined);
80
+
81
+ const scale = 0.5;
82
+
83
+ React.useEffect(() => {
84
+ return () => {
85
+ if (hideTimeout.current) clearTimeout(hideTimeout.current);
86
+ };
87
+ }, []);
88
+
89
+ React.useLayoutEffect(() => {
90
+ if (visible) {
91
+ // show
92
+ if (hideTimeout.current) clearTimeout(hideTimeout.current);
93
+ setHidden(false);
94
+ Animated.timing(opacity, {
95
+ toValue: 1,
96
+ duration: 200 * scale,
97
+ useNativeDriver: true,
98
+ }).start(({ finished }) => {
99
+ if (finished) {
100
+ const isInfinity =
101
+ duration === Number.POSITIVE_INFINITY ||
102
+ duration === Number.NEGATIVE_INFINITY;
103
+
104
+ if (finished && !isInfinity) {
105
+ hideTimeout.current = setTimeout(onDismiss, duration);
106
+ }
107
+ }
108
+ });
109
+ } else {
110
+ // hide
111
+ if (hideTimeout.current) clearTimeout(hideTimeout.current);
112
+
113
+ Animated.timing(opacity, {
114
+ toValue: 0,
115
+ duration: 100 * scale,
116
+ useNativeDriver: true,
117
+ }).start(({ finished }) => {
118
+ if (finished) setHidden(true);
119
+ });
120
+ }
121
+ }, [visible, duration, opacity, scale, onDismiss]);
122
+
123
+ if (hidden) return null;
124
+
125
+ return (
126
+ <SafeAreaView
127
+ pointerEvents='box-none'
128
+ style={[styles.wrapper, wrapperStyle]}
129
+ >
130
+ <Animated.View
131
+ pointerEvents='box-none'
132
+ accessibilityLiveRegion='polite'
133
+ // TODO: fix this TS error
134
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
135
+ // @ts-ignore
136
+ style={
137
+ [
138
+ styles.container,
139
+ {
140
+ opacity,
141
+ transform: [
142
+ {
143
+ scale: visible
144
+ ? opacity.interpolate({
145
+ inputRange: [0, 1],
146
+ outputRange: [0.9, 1],
147
+ })
148
+ : 1,
149
+ },
150
+ ],
151
+ },
152
+ style,
153
+ ] as StyleProp<ViewStyle>
154
+ }
155
+ {...rest}
156
+ >
157
+ <View style={styles.inner}>
158
+ <View style={styles.shadow}>
159
+ <ImageBackground
160
+ style={[{ width: '100%', height: '100%' }]}
161
+ imageStyle={{
162
+ resizeMode: 'repeat',
163
+ }}
164
+ source={{
165
+ uri:
166
+ 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAJElEQVQoU2NkYGD4z4AKGJG5IA4dFKA5AdVKFAdBVaK4iXIFAEiuCAWq9MdHAAAAAElFTkSuQmCC',
167
+ }}
168
+ />
169
+ </View>
170
+ <View
171
+ style={[
172
+ styles.card,
173
+ {
174
+ backgroundColor: theme.tooltip,
175
+ borderColor: theme.borderDarkest,
176
+ },
177
+ ]}
178
+ >
179
+ <Text style={[styles.content, { marginRight: action ? 0 : 16 }]}>
180
+ {children}
181
+ </Text>
182
+ {action ? (
183
+ <TouchableOpacity
184
+ activeOpacity={0.4}
185
+ accessibilityLabel={action.accessibilityLabel}
186
+ onPress={() => {
187
+ action.onPress();
188
+ onDismiss();
189
+ }}
190
+ style={styles.button}
191
+ >
192
+ <Text bold style={styles.buttonText}>
193
+ {action.label}
194
+ </Text>
195
+ </TouchableOpacity>
196
+ ) : null}
197
+ </View>
198
+ </View>
199
+ </Animated.View>
200
+ </SafeAreaView>
201
+ );
202
+ };
203
+
204
+ Snackbar.DURATION_SHORT = DURATION_SHORT;
205
+
206
+ Snackbar.DURATION_MEDIUM = DURATION_MEDIUM;
207
+
208
+ Snackbar.DURATION_LONG = DURATION_LONG;
209
+
210
+ const styles = StyleSheet.create({
211
+ wrapper: {
212
+ position: 'absolute',
213
+ bottom: 0,
214
+ width: '100%',
215
+ },
216
+ container: {
217
+ margin: 16,
218
+ },
219
+ content: {
220
+ marginLeft: 16,
221
+ marginVertical: 16,
222
+ },
223
+ button: {
224
+ marginHorizontal: 8,
225
+ marginVertical: 8,
226
+ textTransform: 'uppercase',
227
+ alignSelf: 'flex-end',
228
+ height: 36,
229
+ paddingHorizontal: 8,
230
+ alignContent: 'center',
231
+ justifyContent: 'center',
232
+ },
233
+ buttonText: {
234
+ textTransform: 'uppercase',
235
+ },
236
+ inner: {
237
+ flex: 1,
238
+ marginRight: shadowOffset,
239
+ marginBottom: shadowOffset,
240
+ },
241
+ card: {
242
+ borderWidth: 2,
243
+ borderRadius: radius,
244
+ flexWrap: 'wrap',
245
+ flexDirection: 'row',
246
+ justifyContent: 'space-between',
247
+ alignItems: 'center',
248
+ },
249
+ shadow: {
250
+ position: 'absolute',
251
+ top: shadowOffset,
252
+ left: shadowOffset,
253
+ overflow: 'hidden',
254
+ borderRadius: radius,
255
+ width: '100%',
256
+ height: '100%',
257
+ },
258
+ });
259
+
260
+ export default withTheme(Snackbar);
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import { StyleProp, StyleSheet, ViewStyle, View } from 'react-native';
3
+
4
+ type Props = React.ComponentPropsWithRef<typeof View> & {
5
+ children?: React.ReactNode;
6
+ style?: StyleProp<ViewStyle>;
7
+ };
8
+
9
+ const SnackbarContent = ({ children, style = {}, ...rest }: Props) => {
10
+ return (
11
+ <View style={[styles.wrapper, style]} {...rest}>
12
+ {children}
13
+ </View>
14
+ );
15
+ };
16
+
17
+ const styles = StyleSheet.create({
18
+ wrapper: {
19
+ padding: 8,
20
+ },
21
+ });
22
+
23
+ export default SnackbarContent;
@@ -0,0 +1 @@
1
+ export { default } from './Snackbar';