@janiscommerce/ui-native 1.16.0 → 1.17.0

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.
@@ -7,7 +7,6 @@ interface BaseInputPropsExtended extends BaseInputProps {
7
7
  variant?: InputVariant;
8
8
  onChangeText?: (text: string) => void;
9
9
  totalValue?: number;
10
- placeholder?: string;
11
10
  }
12
11
  type AmountTotalProps = BaseInputPropsExtended & {
13
12
  variant: 'amountTotal';
@@ -1,11 +1,11 @@
1
1
  import React, { forwardRef, useState, useRef } from 'react';
2
- import { StyleSheet, View, TouchableWithoutFeedback, Keyboard, Platform, } from 'react-native';
2
+ import { StyleSheet, View, TouchableWithoutFeedback, Keyboard } from 'react-native';
3
3
  import BaseInput from '../../atoms/BaseInput';
4
4
  import { palette } from '../../../theme/palette';
5
5
  import { moderateScale, scaledForDevice } from '../../../scale';
6
6
  import handleChangeText from './utils/handleChangeText';
7
7
  import Typography from '../../atoms/Typography';
8
- const isWeb = Platform.OS === 'web';
8
+ import typography from '../../../theme/typography';
9
9
  var InputType;
10
10
  (function (InputType) {
11
11
  InputType["currency"] = "numeric";
@@ -18,9 +18,8 @@ var InputType;
18
18
  InputType["amountTotal"] = "numeric";
19
19
  InputType["numeric"] = "numeric";
20
20
  })(InputType || (InputType = {}));
21
- const Input = forwardRef(({ style, type, variant = 'default', totalValue, placeholder, onChangeText, ...props }, ref) => {
21
+ const Input = forwardRef(({ style, type, variant = 'default', totalValue, onChangeText, ...props }, ref) => {
22
22
  const [value, setValue] = useState('');
23
- const isPlaceholderBeingShown = !value;
24
23
  const isAmountTotalVariant = variant === 'amountTotal';
25
24
  const internalRef = useRef(null);
26
25
  const inputRef = ref ?? internalRef;
@@ -42,24 +41,24 @@ const Input = forwardRef(({ style, type, variant = 'default', totalValue, placeh
42
41
  width: '100%',
43
42
  },
44
43
  input: {
44
+ ...typography.display.medium,
45
45
  color: palette.black.main,
46
- fontSize: scaledForDevice(42, moderateScale),
47
46
  height: '100%',
48
47
  textAlign: 'center',
49
48
  textAlignVertical: 'center',
50
49
  includeFontPadding: false,
51
50
  paddingVertical: 0,
52
- ...(isPlaceholderBeingShown && { marginLeft: scaledForDevice(-12, moderateScale) }),
53
- ...(isWeb && { flex: 1, maxWidth: isPlaceholderBeingShown ? '1%' : undefined }),
54
51
  },
55
52
  totalValue: {
56
53
  color: palette.primary.main,
57
54
  },
58
- placeholder: {
59
- color: '#A8AAAC',
60
- marginLeft: scaledForDevice(-12, moderateScale),
61
- },
62
55
  });
56
+ const getTextAlignment = () => {
57
+ if (value) {
58
+ return isAmountTotalVariant ? 'right' : 'center';
59
+ }
60
+ return 'left';
61
+ };
63
62
  const changeTextCb = (text) => {
64
63
  const transformedText = handleChangeText(text, variant);
65
64
  setValue(transformedText);
@@ -83,18 +82,9 @@ const Input = forwardRef(({ style, type, variant = 'default', totalValue, placeh
83
82
  }
84
83
  return InputType.default;
85
84
  })();
86
- const renderPlaceholder = () => {
87
- if (value.length > 0) {
88
- return null;
89
- }
90
- return (<Typography type="display" style={styles.placeholder}>
91
- {placeholder}
92
- </Typography>);
93
- };
94
85
  return (<TouchableWithoutFeedback onPress={handlePress}>
95
86
  <View style={[styles.container, style]}>
96
- <BaseInput testID="input" style={styles.input} ref={inputRef} value={value} keyboardType={resolvedKeyboardType} onChangeText={changeTextCb} {...props}/>
97
- {renderPlaceholder()}
87
+ <BaseInput testID="input" style={styles.input} textAlign={getTextAlignment()} ref={inputRef} value={value} keyboardType={resolvedKeyboardType} onChangeText={changeTextCb} {...props}/>
98
88
  {isAmountTotalVariant && (<Typography style={styles.totalValue} type="display">
99
89
  {`/${totalValue?.toString()}`}
100
90
  </Typography>)}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ interface ErrorFallbackProps {
3
+ error?: string;
4
+ errorDetails?: string;
5
+ isDebug?: boolean;
6
+ errorMessage?: string;
7
+ }
8
+ declare const ErrorFallback: React.FC<ErrorFallbackProps>;
9
+ export default ErrorFallback;
@@ -0,0 +1,81 @@
1
+ import React from 'react';
2
+ import Collapsible from '../../../../atoms/Collapsible';
3
+ import Typography from '../../../../atoms/Typography';
4
+ import { StyleSheet, TouchableOpacity, View } from 'react-native';
5
+ import { palette } from '../../../../../theme/palette';
6
+ const styles = StyleSheet.create({
7
+ container: {
8
+ flex: 1,
9
+ justifyContent: 'center',
10
+ alignItems: 'center',
11
+ backgroundColor: palette.white.light,
12
+ padding: 30,
13
+ borderRadius: 12,
14
+ margin: 16,
15
+ shadowColor: palette.base.black,
16
+ shadowOffset: { width: 0, height: 2 },
17
+ shadowOpacity: 0.2,
18
+ shadowRadius: 4,
19
+ elevation: 5,
20
+ },
21
+ errorMessageText: {
22
+ textAlign: 'center',
23
+ color: palette.error.main,
24
+ },
25
+ showErrorButton: {
26
+ paddingVertical: 10,
27
+ paddingHorizontal: 20,
28
+ justifyContent: 'center',
29
+ alignItems: 'center',
30
+ backgroundColor: palette.error.main,
31
+ borderRadius: 6,
32
+ marginVertical: 12,
33
+ },
34
+ collapsibleWrapper: {
35
+ marginBottom: 35,
36
+ },
37
+ errorDetails: {
38
+ padding: 10,
39
+ backgroundColor: palette.black.main,
40
+ borderRadius: 8,
41
+ marginVertical: 10,
42
+ },
43
+ heading: {
44
+ marginBottom: 12,
45
+ },
46
+ goBackButtonWrapper: {
47
+ marginTop: 20,
48
+ },
49
+ });
50
+ const ShowErrorDetailsButton = () => {
51
+ return (<View style={styles.showErrorButton}>
52
+ <Typography color={palette.base.white}>Show error details</Typography>
53
+ </View>);
54
+ };
55
+ const ErrorDetails = ({ errorDetails }) => {
56
+ return (<View style={styles.errorDetails}>
57
+ <Typography color={palette.error.main}>{errorDetails}</Typography>
58
+ </View>);
59
+ };
60
+ const ErrorFallback = ({ error, errorDetails, isDebug, errorMessage, }) => {
61
+ const data = [
62
+ {
63
+ errorDetails,
64
+ },
65
+ ];
66
+ if (errorMessage) {
67
+ return (<View style={styles.container}>
68
+ <Typography type="heading" size="large" style={styles.errorMessageText}>
69
+ {errorMessage}
70
+ </Typography>
71
+ </View>);
72
+ }
73
+ return (<View style={styles.container}>
74
+ <Typography type="heading" size="large" style={styles.heading}>
75
+ Oops! Something went wrong.
76
+ </Typography>
77
+ {error && <Typography color={palette.error.main}>{error}</Typography>}
78
+ {isDebug && (<Collapsible wrapperStyle={styles.collapsibleWrapper} header={ShowErrorDetailsButton} content={ErrorDetails} data={data} pressableComponent={TouchableOpacity}/>)}
79
+ </View>);
80
+ };
81
+ export default ErrorFallback;
@@ -0,0 +1,22 @@
1
+ import React, { ReactNode } from 'react';
2
+ interface ErrorBoundaryProps {
3
+ children: ReactNode;
4
+ isDebug?: boolean;
5
+ errorMessage?: string;
6
+ renderErrorComponent?: (errorMessage: string) => ReactNode;
7
+ onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
8
+ onMount?: () => void;
9
+ }
10
+ interface ErrorBoundaryState {
11
+ hasError: boolean;
12
+ error: Error | null;
13
+ errorInfo: React.ErrorInfo | null;
14
+ }
15
+ declare class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
16
+ constructor(props: ErrorBoundaryProps);
17
+ static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState>;
18
+ componentDidMount(): void;
19
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void;
20
+ render(): React.ReactNode;
21
+ }
22
+ export default ErrorBoundary;
@@ -0,0 +1,37 @@
1
+ import React from 'react';
2
+ import ErrorFallback from '../ErrorBoundary/components/ErrorFallback';
3
+ class ErrorBoundary extends React.Component {
4
+ constructor(props) {
5
+ super(props);
6
+ this.state = {
7
+ hasError: false,
8
+ error: null,
9
+ errorInfo: null,
10
+ };
11
+ }
12
+ static getDerivedStateFromError(error) {
13
+ return { hasError: true, error };
14
+ }
15
+ componentDidMount() {
16
+ if (this.props.onMount) {
17
+ this.props.onMount();
18
+ }
19
+ }
20
+ componentDidCatch(error, errorInfo) {
21
+ this.setState({ errorInfo });
22
+ if (this.props.onError) {
23
+ this.props.onError(error, errorInfo);
24
+ }
25
+ }
26
+ render() {
27
+ if (this.state.hasError) {
28
+ const { renderErrorComponent } = this.props;
29
+ if (typeof renderErrorComponent === 'function') {
30
+ return renderErrorComponent(this.state.error?.message || '');
31
+ }
32
+ return (<ErrorFallback isDebug={this.props.isDebug} errorMessage={this.props.errorMessage} error={this.state.error?.message} errorDetails={this.state.errorInfo?.componentStack}/>);
33
+ }
34
+ return this.props.children;
35
+ }
36
+ }
37
+ export default ErrorBoundary;
package/dist/index.d.ts CHANGED
@@ -28,6 +28,7 @@ import Input from './components/molecules/Input';
28
28
  import LoadingFullScreen from './components/organisms/LoadingFullScreen';
29
29
  import FullScreenMessage from './components/organisms/FullScreenMessage';
30
30
  import SwipeItemSelectionList from './components/organisms/SwipeItemSelectionList';
31
+ import ErrorBoundary from './components/organisms/ErrorBoundary';
31
32
  import { palette } from './theme/palette';
32
33
  import * as getScale from './scale';
33
- export { Text, Avatar, CheckBox, Icon, Image, Input, Loading, Svg, StatusChip, palette, LoadingFullScreen, RadioButton, Select, SwipeUp, SwipeUpFlatList, SwipeUpScrollView, SwipeUpView, Carousel, ProgressBar, List, BaseButton, Button, getScale, LayoutWithBottomButtons, FullScreenMessage, Toast, configToast, SwipeList, ItemSelectionButton, SwipeItemSelectionList, MainCardList, BaseInput, Typography, Collapsible, };
34
+ export { Text, Avatar, CheckBox, Icon, Image, Input, Loading, Svg, StatusChip, palette, LoadingFullScreen, RadioButton, Select, SwipeUp, SwipeUpFlatList, SwipeUpScrollView, SwipeUpView, Carousel, ProgressBar, List, BaseButton, Button, getScale, LayoutWithBottomButtons, FullScreenMessage, Toast, configToast, SwipeList, ItemSelectionButton, SwipeItemSelectionList, MainCardList, BaseInput, Typography, Collapsible, ErrorBoundary, };
package/dist/index.js CHANGED
@@ -31,7 +31,8 @@ import Input from './components/molecules/Input';
31
31
  import LoadingFullScreen from './components/organisms/LoadingFullScreen';
32
32
  import FullScreenMessage from './components/organisms/FullScreenMessage';
33
33
  import SwipeItemSelectionList from './components/organisms/SwipeItemSelectionList';
34
+ import ErrorBoundary from './components/organisms/ErrorBoundary';
34
35
  // Misc
35
36
  import { palette } from './theme/palette';
36
37
  import * as getScale from './scale';
37
- export { Text, Avatar, CheckBox, Icon, Image, Input, Loading, Svg, StatusChip, palette, LoadingFullScreen, RadioButton, Select, SwipeUp, SwipeUpFlatList, SwipeUpScrollView, SwipeUpView, Carousel, ProgressBar, List, BaseButton, Button, getScale, LayoutWithBottomButtons, FullScreenMessage, Toast, configToast, SwipeList, ItemSelectionButton, SwipeItemSelectionList, MainCardList, BaseInput, Typography, Collapsible, };
38
+ export { Text, Avatar, CheckBox, Icon, Image, Input, Loading, Svg, StatusChip, palette, LoadingFullScreen, RadioButton, Select, SwipeUp, SwipeUpFlatList, SwipeUpScrollView, SwipeUpView, Carousel, ProgressBar, List, BaseButton, Button, getScale, LayoutWithBottomButtons, FullScreenMessage, Toast, configToast, SwipeList, ItemSelectionButton, SwipeItemSelectionList, MainCardList, BaseInput, Typography, Collapsible, ErrorBoundary, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@janiscommerce/ui-native",
3
- "version": "1.16.0",
3
+ "version": "1.17.0",
4
4
  "description": "components library for Janis app",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -25,7 +25,8 @@
25
25
  "update-stories": "sb-rn-get-stories --config-path .ondevice",
26
26
  "storybook-web": "node scripts/set-app-mode.js web && npm run storybook-web-build && start-storybook -p 6006 --config-dir ./.storybook",
27
27
  "storybook-web-build": "node scripts/set-app-mode.js web && build-storybook --config-dir ./.storybook --output-dir ./.storybook_static",
28
- "storybook-web-docs": "build-storybook --config-dir ./.storybook --output-dir ./docs"
28
+ "storybook-web-docs": "build-storybook --config-dir ./.storybook --output-dir ./docs",
29
+ "preversion": "npm run test:coverage"
29
30
  },
30
31
  "repository": {
31
32
  "type": "git",