react-native-ui-lib 7.38.0-snapshot.6267 → 7.38.0-snapshot.6272

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.
package/.eslintrc.js CHANGED
@@ -8,6 +8,13 @@ module.exports = {
8
8
  'no-undef': 'off',
9
9
  /* Other Rules */
10
10
  'no-unused-expressions': 'off',
11
+ 'no-restricted-syntax': [
12
+ 'error',
13
+ {
14
+ selector: `CallExpression[callee.object.name='console'][callee.property.name='error']`,
15
+ message: 'Using console.error is not allowed as it is sent to Sentry, please use LogService.error instead'
16
+ }
17
+ ],
11
18
  'arrow-parens': 'off',
12
19
  // TODO: remove after migration of legacy lifecycle methods
13
20
  camelcase: 'off',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-ui-lib",
3
- "version": "7.38.0-snapshot.6267",
3
+ "version": "7.38.0-snapshot.6272",
4
4
  "main": "src/index.js",
5
5
  "types": "src/index.d.ts",
6
6
  "author": "Ethan Sharabi <ethan.shar@gmail.com>",
@@ -17,4 +17,10 @@ export declare const MIN_WIDTH: {
17
17
  MEDIUM: number;
18
18
  LARGE: number;
19
19
  };
20
+ export declare const SIZE_TO_VERTICAL_HITSLOP: {
21
+ readonly xSmall: 30;
22
+ readonly small: 25;
23
+ readonly medium: 20;
24
+ readonly large: 15;
25
+ };
20
26
  export declare const DEFAULT_SIZE = ButtonSize.large;
@@ -17,4 +17,10 @@ export const MIN_WIDTH = {
17
17
  MEDIUM: 77,
18
18
  LARGE: 90
19
19
  };
20
+ export const SIZE_TO_VERTICAL_HITSLOP = {
21
+ [ButtonSize.xSmall]: 30,
22
+ [ButtonSize.small]: 25,
23
+ [ButtonSize.medium]: 20,
24
+ [ButtonSize.large]: 15
25
+ };
20
26
  export const DEFAULT_SIZE = ButtonSize.large;
@@ -11,9 +11,7 @@ declare class Button extends PureComponent<Props, ButtonState> {
11
11
  static sizes: typeof ButtonSize;
12
12
  static animationDirection: typeof ButtonAnimationDirection;
13
13
  constructor(props: Props);
14
- state: {
15
- size: undefined;
16
- };
14
+ state: Record<'size', undefined | number>;
17
15
  styles: {
18
16
  container: {
19
17
  backgroundColor: string;
@@ -370,7 +368,14 @@ declare class Button extends PureComponent<Props, ButtonState> {
370
368
  getLabelColor(): string | undefined;
371
369
  getIconColor(): string | undefined;
372
370
  getLabelSizeStyle(): TextStyle | undefined;
373
- getContainerSizeStyle(): any;
371
+ getContainerSizeStyle(): Partial<{
372
+ height: number;
373
+ width: number;
374
+ padding: number;
375
+ paddingVertical: number;
376
+ paddingHorizontal: number;
377
+ minWidth: number;
378
+ }>;
374
379
  getOutlineStyle(): {
375
380
  borderWidth: number;
376
381
  borderColor: string;
@@ -391,10 +396,18 @@ declare class Button extends PureComponent<Props, ButtonState> {
391
396
  })[] | undefined;
392
397
  getIconStyle(): [ImageStyle, StyleProp<ImageStyle>];
393
398
  getAnimationDirectionStyle(): {
394
- alignSelf: string;
399
+ readonly alignSelf: "flex-start";
400
+ } | {
401
+ readonly alignSelf: "flex-end";
395
402
  } | undefined;
396
403
  renderIcon(): React.JSX.Element | null;
397
404
  renderLabel(): React.JSX.Element | null;
405
+ getAccessibleHitSlop(): {
406
+ top: number;
407
+ bottom: number;
408
+ left: number;
409
+ right: number;
410
+ };
398
411
  render(): React.JSX.Element;
399
412
  }
400
413
  export { Button };
@@ -7,7 +7,7 @@ import TouchableOpacity from "../touchableOpacity";
7
7
  import Text from "../text";
8
8
  import Icon from "../icon";
9
9
  import { ButtonSize, ButtonAnimationDirection, ButtonProps, DEFAULT_PROPS } from "./types";
10
- import { PADDINGS, HORIZONTAL_PADDINGS, MIN_WIDTH, DEFAULT_SIZE } from "./ButtonConstants";
10
+ import { PADDINGS, HORIZONTAL_PADDINGS, MIN_WIDTH, DEFAULT_SIZE, SIZE_TO_VERTICAL_HITSLOP } from "./ButtonConstants";
11
11
  export { ButtonSize, ButtonAnimationDirection, ButtonProps };
12
12
  class Button extends PureComponent {
13
13
  static displayName = 'Button';
@@ -351,6 +351,20 @@ class Button extends PureComponent {
351
351
  }
352
352
  return null;
353
353
  }
354
+ getAccessibleHitSlop() {
355
+ const containerStyle = this.getContainerSizeStyle();
356
+ const isWidthSet = containerStyle.width !== undefined || containerStyle.minWidth !== undefined;
357
+ const width = containerStyle.width || containerStyle.minWidth || 0;
358
+ const widthWithPadding = width + (containerStyle.paddingHorizontal || containerStyle.padding || 0) * 2;
359
+ const horizontalHitslop = isWidthSet ? Math.max(0, (48 - widthWithPadding) / 2) : 10;
360
+ const verticalHitslop = (containerStyle.height ? Math.max(0, 48 - containerStyle.height) : SIZE_TO_VERTICAL_HITSLOP[this.props.size || DEFAULT_SIZE]) / 2;
361
+ return {
362
+ top: verticalHitslop,
363
+ bottom: verticalHitslop,
364
+ left: horizontalHitslop,
365
+ right: horizontalHitslop
366
+ };
367
+ }
354
368
  render() {
355
369
  const {
356
370
  onPress,
@@ -373,7 +387,7 @@ class Button extends PureComponent {
373
387
  const borderRadiusStyle = this.getBorderRadiusStyle();
374
388
  return <TouchableOpacity row centerV style={[this.styles.container, animateLayout && this.getAnimationDirectionStyle(), containerSizeStyle, this.isLink && this.styles.innerContainerLink, shadowStyle, margins, paddings, {
375
389
  backgroundColor
376
- }, borderRadiusStyle, outlineStyle, style]} activeOpacity={0.6} activeBackgroundColor={this.getActiveBackgroundColor()} onLayout={this.onLayout} onPress={onPress} disabled={disabled} testID={testID} {...others} ref={forwardedRef}>
390
+ }, borderRadiusStyle, outlineStyle, style]} activeOpacity={0.6} activeBackgroundColor={this.getActiveBackgroundColor()} onLayout={this.onLayout} onPress={onPress} disabled={disabled} testID={testID} {...others} ref={forwardedRef} hitSlop={this.getAccessibleHitSlop()}>
377
391
  {this.props.children}
378
392
  {this.props.iconOnRight ? this.renderLabel() : this.renderIcon()}
379
393
  {this.props.iconOnRight ? this.renderIcon() : this.renderLabel()}
@@ -15,6 +15,7 @@ import { BlurViewPackage } from "../../optionalDependencies";
15
15
  import Assets from "../../assets";
16
16
  import CardContext from "./CardContext";
17
17
  import * as CardPresenter from "./CardPresenter";
18
+ import { LogService } from "../../services";
18
19
  const BlurView = BlurViewPackage?.BlurView;
19
20
  const DEFAULT_BORDER_RADIUS = BorderRadiuses.br40;
20
21
  const DEFAULT_SELECTION_PROPS = {
@@ -47,7 +48,8 @@ class Card extends PureComponent {
47
48
  };
48
49
  this.styles = createStyles(this.props);
49
50
  if (props.enableBlur && !BlurView) {
50
- console.error(`RNUILib Card's "enableBlur" prop requires installing "@react-native-community/blur" dependency`);
51
+ // eslint-disable-next-line max-len
52
+ LogService.error(`RNUILib Card's "enableBlur" prop requires installing "@react-native-community/blur" dependency`);
51
53
  }
52
54
  }
53
55
  componentDidUpdate(prevProps) {
@@ -7,6 +7,7 @@ import { Colors, Typography } from "../../style";
7
7
  import TouchableOpacity from "../touchableOpacity";
8
8
  import View from "../view";
9
9
  import { Constants, asBaseComponent } from "../../commons/new";
10
+ import { LogService } from "../../services";
10
11
  import { ConnectionStatusBarProps, DEFAULT_PROPS } from "./types";
11
12
  export { ConnectionStatusBarProps };
12
13
 
@@ -36,7 +37,8 @@ class ConnectionStatusBar extends PureComponent {
36
37
  if (NetInfo) {
37
38
  this.getInitialConnectionState();
38
39
  } else {
39
- console.error(`RNUILib ConnectionStatusBar component requires installing "@react-native-community/netinfo" dependency`);
40
+ // eslint-disable-next-line max-len
41
+ LogService.error(`RNUILib ConnectionStatusBar component requires installing "@react-native-community/netinfo" dependency`);
40
42
  }
41
43
  }
42
44
  generateStyles() {
@@ -11,6 +11,7 @@ import Button from "../button";
11
11
  import ExpandableOverlay from "../../incubator/expandableOverlay";
12
12
  import useOldApi from "./useOldApi";
13
13
  import { isSameDate, isSameHourAndMinute } from "../../utils/dateUtils";
14
+ import { LogService } from "../../services";
14
15
  /*eslint-disable*/
15
16
  /**
16
17
  * @description: Date and Time Picker Component that wraps RNDateTimePicker for date and time modes.
@@ -64,7 +65,7 @@ const DateTimePicker = forwardRef((props, ref) => {
64
65
  useEffect(() => {
65
66
  if (!RNDateTimePicker) {
66
67
  // eslint-disable-next-line max-len
67
- console.error(`RNUILib DateTimePicker component requires installing "@react-native-community/datetimepicker" dependency`);
68
+ LogService.error(`RNUILib DateTimePicker component requires installing "@react-native-community/datetimepicker" dependency`);
68
69
  }
69
70
  }, []);
70
71
  useDidUpdate(() => {
@@ -1,6 +1,7 @@
1
1
  // TODO: delete whole file in v8
2
2
  import { useEffect } from 'react';
3
3
  import { MomentPackage as moment } from "../../optionalDependencies";
4
+ import { LogService } from "../../services";
4
5
 
5
6
  // This file will be deleted in the next major version,
6
7
  // duplicating these here will make this less complicated
@@ -15,7 +16,8 @@ const useOldApi = props => {
15
16
  } = props;
16
17
  useEffect(() => {
17
18
  if (!moment && (dateFormat || timeFormat)) {
18
- console.error(`RNUILib DateTimePicker component with date/time format requires installing "moment" dependency`);
19
+ // eslint-disable-next-line max-len
20
+ LogService.error(`RNUILib DateTimePicker component with date/time format requires installing "moment" dependency`);
19
21
  }
20
22
  }, [dateFormat, timeFormat]);
21
23
  const getStringValue = (value, mode) => {
@@ -1,13 +1,29 @@
1
1
  import _isEqual from "lodash/isEqual";
2
- import { useState, useCallback, useRef } from 'react';
2
+ import { useState, useCallback, useRef, useEffect } from 'react';
3
+ import { SafeAreaInsetsManager } from 'uilib-native';
4
+ import { Constants } from "../../../commons/new";
3
5
  export default function useHintLayout({
4
6
  onBackgroundPress,
5
7
  targetFrame
6
8
  }) {
7
9
  const [targetLayoutState, setTargetLayout] = useState(targetFrame);
8
- const [targetLayoutInWindowState, setTargetLayoutInWindow] = useState(targetFrame);
10
+ const [targetLayoutInWindowState, setTargetLayoutInWindow] = useState();
9
11
  const [hintMessageWidth, setHintMessageWidth] = useState();
10
12
  const targetRef = useRef(null);
13
+ useEffect(() => {
14
+ if (targetFrame) {
15
+ if (!onBackgroundPress) {
16
+ setTargetLayoutInWindow(targetFrame);
17
+ } else {
18
+ SafeAreaInsetsManager.getSafeAreaInsets().then(insets => {
19
+ setTargetLayoutInWindow({
20
+ ...targetFrame,
21
+ y: targetFrame.y + (insets?.top ?? 0) + Constants.getSafeAreaInsets().top
22
+ });
23
+ });
24
+ }
25
+ }
26
+ }, []);
11
27
  const onTargetLayout = useCallback(({
12
28
  nativeEvent: {
13
29
  layout
@@ -6,6 +6,7 @@ import { BlurViewPackage } from "../../optionalDependencies";
6
6
  import { Constants, asBaseComponent } from "../../commons/new";
7
7
  import TopBar, { ModalTopBarProps } from "./TopBar";
8
8
  import View from "../../components/view";
9
+ import { LogService } from "../../services";
9
10
  const BlurView = BlurViewPackage?.BlurView;
10
11
  export { ModalTopBarProps };
11
12
  /**
@@ -20,7 +21,8 @@ class Modal extends Component {
20
21
  constructor(props) {
21
22
  super(props);
22
23
  if (props.enableModalBlur && !BlurView) {
23
- console.error(`RNUILib Modal's "enableModalBlur" prop requires installing "@react-native-community/blur" dependency`);
24
+ // eslint-disable-next-line max-len
25
+ LogService.error(`RNUILib Modal's "enableModalBlur" prop requires installing "@react-native-community/blur" dependency`);
24
26
  }
25
27
  }
26
28
  renderTouchableOverlay() {
@@ -6,6 +6,7 @@ const {
6
6
  Svg,
7
7
  Path
8
8
  } = SvgPackage;
9
+ import { LogService } from "../../services";
9
10
  const DEFAULT_DIAMETER = 144;
10
11
  const PieChart = props => {
11
12
  const {
@@ -14,7 +15,7 @@ const PieChart = props => {
14
15
  ...others
15
16
  } = props;
16
17
  if (!Svg || !Path) {
17
- console.error(`RNUILib PieChart requires installing "@react-native-svg" dependency`);
18
+ LogService.error(`RNUILib PieChart requires installing "@react-native-svg" dependency`);
18
19
  return null;
19
20
  }
20
21
  const renderPieSegments = () => {
@@ -9,6 +9,7 @@ import { BorderRadiuses, Colors, Dividers, Spacings } from "../../style";
9
9
  import { createShimmerPlaceholder, LinearGradientPackage } from "../../optionalDependencies";
10
10
  import View from "../view";
11
11
  import { Constants } from "../../commons/new";
12
+ import { LogService } from "../../services";
12
13
  const LinearGradient = LinearGradientPackage?.default;
13
14
  let ShimmerPlaceholder;
14
15
  const ANIMATION_DURATION = 400;
@@ -62,9 +63,9 @@ class SkeletonView extends Component {
62
63
  opacity: new Animated.Value(0)
63
64
  };
64
65
  if (_isUndefined(LinearGradientPackage?.default)) {
65
- console.error(`RNUILib SkeletonView's requires installing "react-native-linear-gradient" dependency`);
66
+ LogService.error(`RNUILib SkeletonView's requires installing "react-native-linear-gradient" dependency`);
66
67
  } else if (_isUndefined(createShimmerPlaceholder)) {
67
- console.error(`RNUILib SkeletonView's requires installing "react-native-shimmer-placeholder" dependency`);
68
+ LogService.error(`RNUILib SkeletonView's requires installing "react-native-shimmer-placeholder" dependency`);
68
69
  } else if (ShimmerPlaceholder === undefined) {
69
70
  ShimmerPlaceholder = createShimmerPlaceholder(LinearGradient);
70
71
  }
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { isSvg, isSvgUri } from "../../utils/imageUtils";
3
3
  import { SvgPackage, SvgCssUri } from "../../optionalDependencies";
4
+ import { LogService } from "../../services";
4
5
  const SvgXml = SvgPackage?.SvgXml;
5
6
  // const SvgProps = SvgPackage?.SvgProps; TODO: not sure how (or if) we can use their props
6
7
 
@@ -14,7 +15,7 @@ function SvgImage(props) {
14
15
  } = props;
15
16
  if (!SvgXml) {
16
17
  // eslint-disable-next-line max-len
17
- console.error(`RNUILib Image "svg" prop requires installing "react-native-svg" and "react-native-svg-transformer" dependencies`);
18
+ LogService.error(`RNUILib Image "svg" prop requires installing "react-native-svg" and "react-native-svg-transformer" dependencies`);
18
19
  return null;
19
20
  }
20
21
  if (isSvgUri(data)) {
@@ -1,4 +1,5 @@
1
1
  import { interpolate } from 'react-native-reanimated';
2
+ import { LogService } from "../../services";
2
3
  export function getOffsetForValue(value, span, minimumValue = 0, maximumValue = 1) {
3
4
  const range = maximumValue - minimumValue;
4
5
  const relativeValue = minimumValue - value;
@@ -43,15 +44,21 @@ export function validateValues(props) {
43
44
  initialMaximumValue
44
45
  } = props;
45
46
  if (minimumValue > maximumValue || useRange && initialMinimumValue && initialMaximumValue && initialMinimumValue > initialMaximumValue) {
46
- console.error('Your passed values are invalid. Please check if minimum values are not higher than maximum values');
47
+ LogService.forwardError({
48
+ message: 'Your passed values are invalid. Please check if minimum values are not higher than maximum values'
49
+ });
47
50
  }
48
51
  if (value !== undefined && minimumValue && maximumValue && !inRange(value, minimumValue, maximumValue)) {
49
- console.error(`Your passed value (${value}) is invalid.
50
- Please check that it is in range of the minimum (${minimumValue}) and maximum (${maximumValue}) values`);
52
+ LogService.forwardError({
53
+ message: `Your passed value (${value}) is invalid.
54
+ Please check that it is in range of the minimum (${minimumValue}) and maximum (${maximumValue}) values`
55
+ });
51
56
  }
52
57
  if (useRange && initialMinimumValue && initialMaximumValue) {
53
58
  if (!inRange(initialMinimumValue, minimumValue, maximumValue) || !inRange(initialMaximumValue, minimumValue, maximumValue)) {
54
- console.error('Your passed values are invalid. Please check that they are in range of the minimum and maximum values');
59
+ LogService.forwardError({
60
+ message: 'Your passed values are invalid. Please check that they are in range of the minimum and maximum values'
61
+ });
55
62
  }
56
63
  }
57
64
  }
@@ -1,4 +1,5 @@
1
1
  import { HapticFeedbackPackage } from "../optionalDependencies";
2
+ import { LogService } from "./";
2
3
  const options = {
3
4
  enableVibrateFallback: false,
4
5
  ignoreAndroidSystemSettings: false
@@ -17,7 +18,7 @@ function triggerHaptic(hapticType, componentName) {
17
18
  if (HapticFeedbackPackage) {
18
19
  HapticFeedbackPackage.trigger(hapticType, options);
19
20
  } else {
20
- console.error(`RNUILib ${componentName}'s requires installing "react-native-haptic-feedback" dependency`);
21
+ LogService.error(`RNUILib ${componentName}'s requires installing "react-native-haptic-feedback" dependency`);
21
22
  }
22
23
  }
23
24
  export default {
@@ -1,12 +1,15 @@
1
1
  interface BILogger {
2
2
  log: (event: any) => void;
3
3
  }
4
- declare class LogService {
4
+ declare class LogService<ErrorInfo extends {
5
+ message: string;
6
+ }> {
5
7
  private biLogger;
6
8
  injectBILogger: (biLogger: BILogger) => void;
7
9
  logBI: (event: any) => void;
8
10
  warn: (message?: any, ...optionalParams: any[]) => void;
9
11
  error: (message?: any, ...optionalParams: any[]) => void;
12
+ forwardError: (errorInfo: ErrorInfo) => void;
10
13
  deprecationWarn: ({ component, oldProp, newProp }: {
11
14
  component: string;
12
15
  oldProp: string;
@@ -26,5 +29,7 @@ declare class LogService {
26
29
  newComponent: string;
27
30
  }) => void;
28
31
  }
29
- declare const _default: LogService;
32
+ declare const _default: LogService<{
33
+ message: string;
34
+ }>;
30
35
  export default _default;
@@ -12,9 +12,14 @@ class LogService {
12
12
  };
13
13
  error = (message, ...optionalParams) => {
14
14
  if (__DEV__) {
15
+ // eslint-disable-next-line no-restricted-syntax
15
16
  console.error(message, ...optionalParams);
16
17
  }
17
18
  };
19
+ forwardError = errorInfo => {
20
+ // eslint-disable-next-line no-restricted-syntax
21
+ console.error(errorInfo.message);
22
+ };
18
23
  deprecationWarn = ({
19
24
  component,
20
25
  oldProp,