@ledgerhq/native-ui 0.23.3 → 0.23.4-nightly.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.
@@ -0,0 +1,11 @@
1
+ /// <reference types="react" />
2
+ interface TabSelectorProps<T extends string | number> {
3
+ options: T[];
4
+ selectedOption: T;
5
+ handleSelectOption: (option: T) => void;
6
+ labels: {
7
+ [key in T]: string;
8
+ };
9
+ }
10
+ export default function TabSelector<T extends string | number>({ options, selectedOption, handleSelectOption, labels, }: TabSelectorProps<T>): JSX.Element;
11
+ export {};
@@ -0,0 +1,61 @@
1
+ import React, { useEffect } from "react";
2
+ import Text from "../../Text";
3
+ import Flex from "../../Layout/Flex";
4
+ import styled, { useTheme } from "styled-components/native";
5
+ import { TouchableOpacity } from "react-native";
6
+ import Animated, { useSharedValue, useAnimatedStyle, withSpring } from "react-native-reanimated";
7
+ const StyledTouchableOpacity = styled(TouchableOpacity) `
8
+ width: ${(p) => p.width}px;
9
+ flex: 1;
10
+ height: 100%;
11
+ `;
12
+ const StyledFlex = styled(Flex) `
13
+ height: 100%;
14
+ justify-content: center;
15
+ align-items: center;
16
+ `;
17
+ const StyledText = styled(Text) `
18
+ line-height: 14.52px;
19
+ overflow: visible;
20
+ text-align: center;
21
+ font-size: 12px;
22
+ color: ${(p) => p.isSelected ? p.theme.colors.constant.black : p.theme.colors.opacityDefault.c50};
23
+ `;
24
+ const OptionButton = ({ option, selectedOption, handleSelectOption, label, width, }) => {
25
+ const isSelected = selectedOption === option;
26
+ return (React.createElement(StyledTouchableOpacity, { width: width, onPress: () => handleSelectOption(option) },
27
+ React.createElement(StyledFlex, { isSelected: isSelected },
28
+ React.createElement(StyledText, { fontWeight: "semiBold", isSelected: isSelected, numberOfLines: 1 }, label))));
29
+ };
30
+ export default function TabSelector({ options, selectedOption, handleSelectOption, labels, }) {
31
+ const { colors } = useTheme();
32
+ const longuestLabel = labels[options[0]].length > labels[options[1]].length ? options[0] : options[1];
33
+ const widthFactor = 8;
34
+ const margin = 20;
35
+ const width = labels[longuestLabel].length * widthFactor + margin;
36
+ const semiWidth = width / 2;
37
+ const translateX = useSharedValue(-semiWidth);
38
+ useEffect(() => {
39
+ translateX.value = withSpring(selectedOption === options[0] ? -semiWidth : semiWidth, {
40
+ damping: 30,
41
+ stiffness: 80,
42
+ });
43
+ }, [selectedOption, translateX, options]);
44
+ const animatedStyle = useAnimatedStyle(() => {
45
+ return {
46
+ transform: [{ translateX: translateX.value }],
47
+ };
48
+ });
49
+ return (React.createElement(Flex, { flexDirection: "row", justifyContent: "center", alignItems: "center", width: width * 2 + 4, height: "35px", borderRadius: "40px", bg: colors.opacityDefault.c05, position: "relative" },
50
+ React.createElement(Animated.View, { style: [
51
+ {
52
+ position: "absolute",
53
+ width: width - 2,
54
+ height: "90%",
55
+ backgroundColor: colors.primary.c80,
56
+ borderRadius: 40,
57
+ },
58
+ animatedStyle,
59
+ ] }),
60
+ options.map((option) => (React.createElement(OptionButton, { width: width, key: option, option: option, selectedOption: selectedOption, handleSelectOption: handleSelectOption, label: labels[option] })))));
61
+ }
@@ -4,3 +4,4 @@ export { default as Slider } from "./Slider";
4
4
  export { default as Switch } from "./Switch";
5
5
  export { default as Toggle } from "./Toggle";
6
6
  export { default as SelectableList } from "./SelectableList";
7
+ export { default as TabSelector } from "./TabSelector";
@@ -4,3 +4,4 @@ export { default as Slider } from "./Slider";
4
4
  export { default as Switch } from "./Switch";
5
5
  export { default as Toggle } from "./Toggle";
6
6
  export { default as SelectableList } from "./SelectableList";
7
+ export { default as TabSelector } from "./TabSelector";
@@ -5,6 +5,7 @@ import { IconOrElementType } from "../../../Icon/type";
5
5
  export type BaseModalProps = {
6
6
  isOpen?: boolean;
7
7
  onClose?: () => void;
8
+ onBack?: () => void;
8
9
  modalStyle?: StyleProp<ViewStyle>;
9
10
  safeContainerStyle?: StyleProp<ViewStyle>;
10
11
  containerStyle?: StyleProp<ViewStyle>;
@@ -16,10 +17,12 @@ export type BaseModalProps = {
16
17
  subtitle?: string;
17
18
  children?: React.ReactNode;
18
19
  noCloseButton?: boolean;
20
+ hasBackButton?: boolean;
19
21
  CustomHeader?: React.ComponentType<{
20
22
  children?: ReactNode;
21
23
  }>;
22
24
  } & Partial<ModalProps>;
23
25
  export declare function ModalHeader({ Icon, iconColor, title, description, subtitle, }: Pick<BaseModalProps, "Icon" | "iconColor" | "title" | "description" | "subtitle">): React.ReactElement | null;
24
26
  export declare function ModalHeaderCloseButton({ onClose, }: Pick<BaseModalProps, "onClose">): React.ReactElement;
25
- export default function BaseModal({ isOpen, onClose, noCloseButton, safeContainerStyle, containerStyle, modalStyle, preventBackdropClick, Icon, iconColor, title, description, subtitle, children, onModalHide, CustomHeader, ...rest }: BaseModalProps): React.ReactElement;
27
+ export declare function ModalHeaderBackButton({ onBack, }: Pick<BaseModalProps, "onBack">): React.ReactElement;
28
+ export default function BaseModal({ isOpen, onClose, onBack, noCloseButton, hasBackButton, safeContainerStyle, containerStyle, modalStyle, preventBackdropClick, Icon, iconColor, title, description, subtitle, children, onModalHide, CustomHeader, ...rest }: BaseModalProps): React.ReactElement;
@@ -12,12 +12,13 @@ var __rest = (this && this.__rest) || function (s, e) {
12
12
  import React, { useCallback } from "react";
13
13
  import ReactNativeModal from "react-native-modal";
14
14
  import styled from "styled-components/native";
15
+ import { TouchableOpacity } from "react-native";
15
16
  import sizes from "../../../../helpers/getDeviceSize";
16
17
  import Text from "../../../Text";
17
18
  import { BoxedIcon } from "../../../Icon";
18
19
  import { Flex } from "../../index";
19
20
  import { space } from "styled-system";
20
- import { Close } from "@ledgerhq/icons-ui/native";
21
+ import { Close, ArrowLeft } from "@ledgerhq/icons-ui/native";
21
22
  import { useTheme } from "styled-components/native";
22
23
  const { width, height } = sizes;
23
24
  const SafeContainer = styled.SafeAreaView `
@@ -39,6 +40,12 @@ const CloseContainer = styled.View `
39
40
  margin-bottom: ${(p) => p.theme.space[6]}px;
40
41
  z-index: 10;
41
42
  `;
43
+ const BackContainer = styled.View `
44
+ display: flex;
45
+ align-items: flex-start;
46
+ margin-bottom: ${(p) => p.theme.space[6]}px;
47
+ z-index: 10;
48
+ `;
42
49
  const ClosePressableExtendedBounds = styled.TouchableOpacity.attrs({
43
50
  p: 3,
44
51
  }) `
@@ -76,8 +83,14 @@ export function ModalHeaderCloseButton({ onClose, }) {
76
83
  React.createElement(ClosePressableExtendedBounds, { onPress: onClose, testID: "modal-close-button" },
77
84
  React.createElement(Close, { color: colors.neutral.c100, size: "XS" }))));
78
85
  }
86
+ export function ModalHeaderBackButton({ onBack, }) {
87
+ const { colors } = useTheme();
88
+ return (React.createElement(BackContainer, null,
89
+ React.createElement(TouchableOpacity, { onPress: onBack, testID: "modal-back-button" },
90
+ React.createElement(ArrowLeft, { color: colors.neutral.c100, size: "XS" }))));
91
+ }
79
92
  export default function BaseModal(_a) {
80
- var { isOpen, onClose = () => { }, noCloseButton, safeContainerStyle = {}, containerStyle = {}, modalStyle = {}, preventBackdropClick, Icon, iconColor, title, description, subtitle, children, onModalHide, CustomHeader } = _a, rest = __rest(_a, ["isOpen", "onClose", "noCloseButton", "safeContainerStyle", "containerStyle", "modalStyle", "preventBackdropClick", "Icon", "iconColor", "title", "description", "subtitle", "children", "onModalHide", "CustomHeader"]);
93
+ var { isOpen, onClose = () => { }, onBack = () => { }, noCloseButton, hasBackButton, safeContainerStyle = {}, containerStyle = {}, modalStyle = {}, preventBackdropClick, Icon, iconColor, title, description, subtitle, children, onModalHide, CustomHeader } = _a, rest = __rest(_a, ["isOpen", "onClose", "onBack", "noCloseButton", "hasBackButton", "safeContainerStyle", "containerStyle", "modalStyle", "preventBackdropClick", "Icon", "iconColor", "title", "description", "subtitle", "children", "onModalHide", "CustomHeader"]);
81
94
  const backDropProps = preventBackdropClick
82
95
  ? {}
83
96
  : {
@@ -96,7 +109,11 @@ export default function BaseModal(_a) {
96
109
  React.createElement(SafeContainer, { style: safeContainerStyle },
97
110
  CustomHeader && (React.createElement(CustomHeader, null, !noCloseButton && React.createElement(ModalHeaderCloseButton, { onClose: onClose }))),
98
111
  React.createElement(Container, { style: containerStyle },
99
- !CustomHeader && !noCloseButton && React.createElement(ModalHeaderCloseButton, { onClose: onClose }),
112
+ React.createElement(Flex, { flexDirection: "row", justifyContent: "space-between", width: "100%", alignItems: "center" },
113
+ !CustomHeader && onBack && hasBackButton && (React.createElement(Flex, { flex: 1, justifyContent: "flex-start" },
114
+ React.createElement(ModalHeaderBackButton, { onBack: onBack }))),
115
+ !CustomHeader && !noCloseButton && (React.createElement(Flex, { flex: 1, justifyContent: "flex-end" },
116
+ React.createElement(ModalHeaderCloseButton, { onClose: onClose })))),
100
117
  React.createElement(ModalHeader, { Icon: Icon, iconColor: iconColor, title: title, description: description, subtitle: subtitle }),
101
118
  React.createElement(ContentContainer, null, children)))));
102
119
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/native-ui",
3
- "version": "0.23.3",
3
+ "version": "0.23.4-nightly.0",
4
4
  "description": "Ledger Live - Mobile UI",
5
5
  "repository": {
6
6
  "type": "git",