@ledgerhq/native-ui 0.7.18-updater.0 → 0.8.0-next.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.
- package/lib/components/Carousel/index.d.ts +23 -1
- package/lib/components/Carousel/index.js +56 -16
- package/lib/components/Icon/BoxedIcon.d.ts +5 -1
- package/lib/components/Icon/BoxedIcon.js +2 -2
- package/lib/components/Layout/List/IconBoxList/index.d.ts +3 -1
- package/lib/components/Layout/List/IconBoxList/index.js +3 -3
- package/lib/components/Layout/Modals/BaseModal/index.d.ts +1 -0
- package/lib/components/Layout/Modals/BaseModal/index.js +9 -6
- package/lib/components/Layout/ScrollListContainer/index.d.ts +12 -7
- package/lib/components/Layout/ScrollListContainer/index.js +5 -5
- package/lib/components/Navigation/SlideIndicator/index.d.ts +1 -1
- package/lib/components/Navigation/SlideIndicator/index.js +1 -1
- package/lib/components/Navigation/StoriesIndicator/index.d.ts +34 -0
- package/lib/components/Navigation/StoriesIndicator/index.js +32 -0
- package/lib/components/Navigation/index.d.ts +1 -0
- package/lib/components/Navigation/index.js +1 -0
- package/package.json +2 -2
|
@@ -14,6 +14,10 @@ export declare type Props = React.PropsWithChildren<{
|
|
|
14
14
|
* Called when the active carousel index is updated.
|
|
15
15
|
*/
|
|
16
16
|
onChange?: (index: number) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Called when Carousel try to scroll before the first or after the last item (if restartAfterEnd is false).
|
|
19
|
+
*/
|
|
20
|
+
onOverflow?: (side: "start" | "end", fromAutoDelay: boolean) => void;
|
|
17
21
|
/**
|
|
18
22
|
* This number in milliseconds will enable automatic scrolling when defined.
|
|
19
23
|
*
|
|
@@ -24,6 +28,14 @@ export declare type Props = React.PropsWithChildren<{
|
|
|
24
28
|
* manually change the carousel item displayed.
|
|
25
29
|
*/
|
|
26
30
|
autoDelay?: number;
|
|
31
|
+
/**
|
|
32
|
+
* When the delay is elasped, if the Carousel is at the last item, it will scroll back to the beginning.
|
|
33
|
+
*/
|
|
34
|
+
restartAfterEnd?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* When the user tap on one side of an item, it will scroll to the next or precedent item. Same behavior as Instagram or Snapchat. Default: false.
|
|
37
|
+
*/
|
|
38
|
+
scrollOnSidePress?: boolean;
|
|
27
39
|
/**
|
|
28
40
|
* Additional props to pass to the outer container.
|
|
29
41
|
* This container is a Flex element.
|
|
@@ -39,7 +51,17 @@ export declare type Props = React.PropsWithChildren<{
|
|
|
39
51
|
* This container is a Flex element.
|
|
40
52
|
*/
|
|
41
53
|
slideIndicatorContainerProps?: FlexboxProps & ViewProps;
|
|
54
|
+
IndicatorComponent?: React.ComponentType<{
|
|
55
|
+
activeIndex: number;
|
|
56
|
+
slidesLength: number;
|
|
57
|
+
onChange?: (index: number) => void;
|
|
58
|
+
duration?: number;
|
|
59
|
+
}> | React.ReactElement;
|
|
60
|
+
/**
|
|
61
|
+
* Number of milliseconds a tap should not exceed to scroll to the netxt or precedent item.
|
|
62
|
+
*/
|
|
63
|
+
maxDurationOfTap?: number;
|
|
42
64
|
}>;
|
|
43
|
-
declare function Carousel({ activeIndex, autoDelay, containerProps, slideIndicatorContainerProps, scrollViewProps, onChange, children, }: Props): JSX.Element;
|
|
65
|
+
declare function Carousel({ activeIndex, autoDelay, restartAfterEnd, scrollOnSidePress, containerProps, slideIndicatorContainerProps, scrollViewProps, onChange, onOverflow, IndicatorComponent, maxDurationOfTap, children, }: Props): JSX.Element;
|
|
44
66
|
declare const _default: React.MemoExoticComponent<typeof Carousel>;
|
|
45
67
|
export default _default;
|
|
@@ -5,7 +5,7 @@ import { Flex, SlideIndicator } from "../index";
|
|
|
5
5
|
const HorizontalScrollView = styled.ScrollView.attrs({ horizontal: true }) `
|
|
6
6
|
flex: 1;
|
|
7
7
|
`;
|
|
8
|
-
function Carousel({ activeIndex, autoDelay, containerProps, slideIndicatorContainerProps, scrollViewProps, onChange, children, }) {
|
|
8
|
+
function Carousel({ activeIndex = 0, autoDelay, restartAfterEnd = true, scrollOnSidePress = false, containerProps, slideIndicatorContainerProps, scrollViewProps, onChange, onOverflow, IndicatorComponent = SlideIndicator, maxDurationOfTap, children, }) {
|
|
9
9
|
const [init, setInit] = useState(false);
|
|
10
10
|
const [activeIndexState, setActiveIndexState] = useState(activeIndex);
|
|
11
11
|
const disableTimer = useRef(false);
|
|
@@ -25,8 +25,9 @@ function Carousel({ activeIndex, autoDelay, containerProps, slideIndicatorContai
|
|
|
25
25
|
}, [itemWidth]);
|
|
26
26
|
useEffect(() => {
|
|
27
27
|
// On init scroll to the active index prop location - if specified.
|
|
28
|
-
if (init && activeIndex)
|
|
28
|
+
if (init && activeIndex) {
|
|
29
29
|
scrollToIndex(activeIndex, false);
|
|
30
|
+
}
|
|
30
31
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
31
32
|
}, [init]);
|
|
32
33
|
useEffect(() => {
|
|
@@ -39,6 +40,23 @@ function Carousel({ activeIndex, autoDelay, containerProps, slideIndicatorContai
|
|
|
39
40
|
dimensions.current = { contentWidth, contentHeight };
|
|
40
41
|
setInit(true);
|
|
41
42
|
};
|
|
43
|
+
const onTap = useCallback((event) => {
|
|
44
|
+
const tapPositionXPercent = event.nativeEvent.locationX / itemWidth;
|
|
45
|
+
if (tapPositionXPercent > 0.25) {
|
|
46
|
+
if (slidesLength > activeIndexState + 1) {
|
|
47
|
+
scrollToIndex(activeIndexState + 1, false);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
onOverflow && onOverflow("end", false);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else if (activeIndexState > 0) {
|
|
54
|
+
scrollToIndex(activeIndexState - 1, false);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
onOverflow && onOverflow("start", false);
|
|
58
|
+
}
|
|
59
|
+
}, [slidesLength, activeIndexState, scrollToIndex, onOverflow, itemWidth]);
|
|
42
60
|
const onScroll = ({ nativeEvent: { contentOffset, contentSize }, }) => {
|
|
43
61
|
const newIndex = Math.abs(Math.round((contentOffset.x / contentSize.width) * slidesLength));
|
|
44
62
|
setActiveIndexState(newIndex);
|
|
@@ -47,28 +65,50 @@ function Carousel({ activeIndex, autoDelay, containerProps, slideIndicatorContai
|
|
|
47
65
|
useEffect(() => {
|
|
48
66
|
if (!autoDelay)
|
|
49
67
|
return;
|
|
50
|
-
const interval =
|
|
68
|
+
const interval = setTimeout(() => {
|
|
51
69
|
if (!disableTimer.current) {
|
|
52
|
-
|
|
53
|
-
|
|
70
|
+
const newIndex = typeof activeIndexState !== "undefined" ? (activeIndexState + 1) % slidesLength : 0;
|
|
71
|
+
if (restartAfterEnd || newIndex !== 0) {
|
|
54
72
|
scrollToIndex(newIndex);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
onOverflow && onOverflow("end", true);
|
|
76
|
+
}
|
|
58
77
|
}
|
|
59
78
|
}, autoDelay);
|
|
60
|
-
return () =>
|
|
61
|
-
|
|
79
|
+
return () => {
|
|
80
|
+
return clearTimeout(interval);
|
|
81
|
+
};
|
|
82
|
+
}, [
|
|
83
|
+
resetTimer,
|
|
84
|
+
slidesLength,
|
|
85
|
+
scrollToIndex,
|
|
86
|
+
onChange,
|
|
87
|
+
autoDelay,
|
|
88
|
+
activeIndexState,
|
|
89
|
+
onOverflow,
|
|
90
|
+
restartAfterEnd,
|
|
91
|
+
]);
|
|
92
|
+
// Timestamp of start of click on the Carrousel
|
|
93
|
+
const [tapTime, setTapTime] = useState(0);
|
|
94
|
+
const onStartTap = useCallback(() => {
|
|
95
|
+
setTapTime(new Date().getTime());
|
|
96
|
+
}, []);
|
|
97
|
+
const onEndTap = useCallback((event) => {
|
|
98
|
+
const currentTime = new Date().getTime();
|
|
99
|
+
if (!maxDurationOfTap || currentTime - tapTime <= maxDurationOfTap) {
|
|
100
|
+
onTap(event);
|
|
101
|
+
}
|
|
102
|
+
}, [maxDurationOfTap, onTap, tapTime]);
|
|
62
103
|
return (React.createElement(Flex, Object.assign({ flex: 1, width: "100%", alignItems: "center", justifyContent: "center" }, containerProps),
|
|
63
104
|
React.createElement(HorizontalScrollView, Object.assign({ ref: scrollRef, onScroll: onScroll, onContentSizeChange: onContentSizeChange, onScrollBeginDrag: () => {
|
|
64
105
|
disableTimer.current = true;
|
|
65
106
|
}, onScrollEndDrag: () => {
|
|
66
107
|
disableTimer.current = false;
|
|
67
|
-
}, pagingEnabled: Platform.OS !== "web", showsHorizontalScrollIndicator: false, scrollEventThrottle: 200, contentContainerStyle: { width: `${fullWidth}%` }, decelerationRate: "fast" }, scrollViewProps), React.Children.map(children, (child, index) => (React.createElement(Flex, { key: index, flex: 1 }, child)))),
|
|
68
|
-
React.createElement(Flex, Object.assign({ my: 8 }, slideIndicatorContainerProps),
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}, slidesLength: slidesLength }))));
|
|
108
|
+
}, pagingEnabled: Platform.OS !== "web", showsHorizontalScrollIndicator: false, scrollEventThrottle: 200, contentContainerStyle: { width: `${fullWidth}%` }, decelerationRate: "fast", onTouchStart: scrollOnSidePress ? onStartTap : undefined, onTouchEnd: scrollOnSidePress ? onEndTap : undefined }, scrollViewProps), React.Children.map(children, (child, index) => (React.createElement(Flex, { key: index, flex: 1 }, child)))),
|
|
109
|
+
React.createElement(Flex, Object.assign({ my: 8 }, slideIndicatorContainerProps), React.isValidElement(IndicatorComponent) ? (IndicatorComponent) : (React.createElement(IndicatorComponent, { activeIndex: activeIndexState || 0, onChange: (index) => {
|
|
110
|
+
scrollToIndex(index);
|
|
111
|
+
setResetTimer({});
|
|
112
|
+
}, slidesLength: slidesLength, duration: autoDelay })))));
|
|
73
113
|
}
|
|
74
114
|
export default React.memo(Carousel);
|
|
@@ -9,6 +9,10 @@ export declare type IconBoxProps = {
|
|
|
9
9
|
* Component that takes `{size?: number; color?: string}` as props. Will be rendered at the top right with the size provided in `badgeSize` or a default size.
|
|
10
10
|
*/
|
|
11
11
|
Badge?: IconType;
|
|
12
|
+
/**
|
|
13
|
+
* Color of the background, only applied if no Badge is provided
|
|
14
|
+
*/
|
|
15
|
+
backgroundColor?: string;
|
|
12
16
|
/**
|
|
13
17
|
* Color of the border
|
|
14
18
|
*/
|
|
@@ -45,6 +49,6 @@ export declare type BoxedIconProps = IconBoxProps & {
|
|
|
45
49
|
*/
|
|
46
50
|
iconColor?: string;
|
|
47
51
|
};
|
|
48
|
-
export declare const IconBox: ({ Badge, size, children, borderColor, badgeColor, badgeSize, variant, }: IconBoxProps) => JSX.Element;
|
|
52
|
+
export declare const IconBox: ({ Badge, size, children, borderColor, backgroundColor, badgeColor, badgeSize, variant, }: IconBoxProps) => JSX.Element;
|
|
49
53
|
declare const BoxedIcon: ({ Icon, iconSize, iconColor, ...iconBoxProps }: BoxedIconProps) => JSX.Element;
|
|
50
54
|
export default BoxedIcon;
|
|
@@ -70,10 +70,10 @@ const IconBoxBackgroundSVG = ({ size, borderColor, badgeSize, variant = "square"
|
|
|
70
70
|
React.createElement(Rect, { x: "0", y: squareSize, width: "100%", height: svgSize - squareSize }))),
|
|
71
71
|
React.createElement(Rect, { strokeWidth: PixelRatio.roundToNearestPixel(borderWidth), stroke: strokeColor, x: borderWidth, y: borderWidth, rx: rectRadius, ry: rectRadius, width: rectSize, height: rectSize, fill: "transparent", clipPath: "url(#clip)" }))));
|
|
72
72
|
};
|
|
73
|
-
export const IconBox = ({ Badge, size = DEFAULT_BOX_SIZE, children, borderColor = "neutral.c40", badgeColor, badgeSize = DEFAULT_BADGE_SIZE, variant = "square", }) => {
|
|
73
|
+
export const IconBox = ({ Badge, size = DEFAULT_BOX_SIZE, children, borderColor = "neutral.c40", backgroundColor = "transparent", badgeColor, badgeSize = DEFAULT_BADGE_SIZE, variant = "square", }) => {
|
|
74
74
|
const hasBadge = !!Badge;
|
|
75
75
|
return (React.createElement(Container, { size: size },
|
|
76
|
-
hasBadge ? (React.createElement(IconBoxBackgroundSVG, { size: size, badgeSize: badgeSize, borderColor: borderColor, variant: variant })) : (React.createElement(IconBoxBackground, { border: "1px solid", size: size, borderColor: borderColor, variant: variant })),
|
|
76
|
+
hasBadge ? (React.createElement(IconBoxBackgroundSVG, { size: size, badgeSize: badgeSize, borderColor: borderColor, variant: variant })) : (React.createElement(IconBoxBackground, { border: "1px solid", size: size, borderColor: borderColor, variant: variant, backgroundColor: backgroundColor })),
|
|
77
77
|
children,
|
|
78
78
|
hasBadge && (React.createElement(BadgeContainer, { badgeSize: badgeSize },
|
|
79
79
|
React.createElement(Badge, { size: badgeSize, color: badgeColor })))));
|
|
@@ -6,5 +6,7 @@ export declare type IconBoxListItemProps = Omit<BaseListItemProps, "bullet"> & {
|
|
|
6
6
|
};
|
|
7
7
|
export declare type IconBoxListProps = Omit<BaseListProps, "items"> & {
|
|
8
8
|
items: IconBoxListItemProps[];
|
|
9
|
+
iconVariants?: "outlined" | "plain";
|
|
10
|
+
iconShapes?: "square" | "circle";
|
|
9
11
|
};
|
|
10
|
-
export default function IconBoxList({ items, ...props }: IconBoxListProps): React.ReactElement;
|
|
12
|
+
export default function IconBoxList({ items, iconVariants, iconShapes, ...props }: IconBoxListProps): React.ReactElement;
|
|
@@ -11,9 +11,9 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
11
11
|
};
|
|
12
12
|
import React, { useMemo } from "react";
|
|
13
13
|
import List from "../List";
|
|
14
|
-
import
|
|
14
|
+
import BoxedIcon from "../../../Icon/BoxedIcon";
|
|
15
15
|
export default function IconBoxList(_a) {
|
|
16
|
-
var { items } = _a, props = __rest(_a, ["items"]);
|
|
17
|
-
const iconBoxItems = useMemo(() => items.map((item) => (Object.assign(Object.assign({}, item), { bullet: React.createElement(
|
|
16
|
+
var { items, iconVariants, iconShapes } = _a, props = __rest(_a, ["items", "iconVariants", "iconShapes"]);
|
|
17
|
+
const iconBoxItems = useMemo(() => items.map((item) => (Object.assign(Object.assign({}, item), { bullet: (React.createElement(BoxedIcon, { variant: iconShapes, iconColor: iconVariants === "plain" ? "primary.c70" : undefined, backgroundColor: iconVariants === "plain" ? "primary.c10" : undefined, borderColor: iconVariants === "plain" ? "transparent" : undefined, Icon: item.Icon, iconSize: 20 })) }))), [items]);
|
|
18
18
|
return React.createElement(List, Object.assign({ items: iconBoxItems }, props));
|
|
19
19
|
}
|
|
@@ -18,4 +18,5 @@ export declare type BaseModalProps = {
|
|
|
18
18
|
noCloseButton?: boolean;
|
|
19
19
|
} & Partial<ModalProps>;
|
|
20
20
|
export declare function ModalHeader({ Icon, iconColor, title, description, subtitle, }: Pick<BaseModalProps, "Icon" | "iconColor" | "title" | "description" | "subtitle">): React.ReactElement | null;
|
|
21
|
+
export declare function ModalHeaderCloseButton({ onClose, }: Pick<BaseModalProps, "onClose">): React.ReactElement;
|
|
21
22
|
export default function BaseModal({ isOpen, onClose, noCloseButton, safeContainerStyle, containerStyle, modalStyle, preventBackdropClick, Icon, iconColor, title, description, subtitle, children, ...rest }: BaseModalProps): React.ReactElement;
|
|
@@ -20,10 +20,10 @@ import { space } from "styled-system";
|
|
|
20
20
|
import { Icons } from "../../../../assets";
|
|
21
21
|
const { width, height } = sizes;
|
|
22
22
|
const SafeContainer = styled.SafeAreaView `
|
|
23
|
-
background-color: ${(p) => p.theme.colors.background.
|
|
23
|
+
background-color: ${(p) => p.theme.colors.background.drawer};
|
|
24
24
|
`;
|
|
25
25
|
const Container = styled.View `
|
|
26
|
-
background-color: ${(p) => p.theme.colors.background.
|
|
26
|
+
background-color: ${(p) => p.theme.colors.background.drawer};
|
|
27
27
|
width: 100%;
|
|
28
28
|
padding: 16px;
|
|
29
29
|
min-height: 350px;
|
|
@@ -35,7 +35,7 @@ const ContentContainer = styled.View `
|
|
|
35
35
|
const CloseContainer = styled.View `
|
|
36
36
|
display: flex;
|
|
37
37
|
align-items: flex-end;
|
|
38
|
-
margin-bottom: ${(p) => p.theme.space[
|
|
38
|
+
margin-bottom: ${(p) => p.theme.space[6]}px;
|
|
39
39
|
`;
|
|
40
40
|
const ClosePressableExtendedBounds = styled.TouchableOpacity.attrs({
|
|
41
41
|
p: 3,
|
|
@@ -68,6 +68,11 @@ export function ModalHeader({ Icon, iconColor, title, description, subtitle, })
|
|
|
68
68
|
title && React.createElement(StyledTitle, { textAlign: "center" }, title),
|
|
69
69
|
description && (React.createElement(Text, { variant: "body", color: "neutral.c70", textAlign: "center", mt: 6 }, description))));
|
|
70
70
|
}
|
|
71
|
+
export function ModalHeaderCloseButton({ onClose, }) {
|
|
72
|
+
return (React.createElement(CloseContainer, null,
|
|
73
|
+
React.createElement(ClosePressableExtendedBounds, { onPress: onClose },
|
|
74
|
+
React.createElement(Icons.CloseMedium, { color: "neutral.c100", size: "20px" }))));
|
|
75
|
+
}
|
|
71
76
|
export default function BaseModal(_a) {
|
|
72
77
|
var { isOpen, onClose = () => { }, noCloseButton, safeContainerStyle = {}, containerStyle = {}, modalStyle = {}, preventBackdropClick, Icon, iconColor, title, description, subtitle, children } = _a, rest = __rest(_a, ["isOpen", "onClose", "noCloseButton", "safeContainerStyle", "containerStyle", "modalStyle", "preventBackdropClick", "Icon", "iconColor", "title", "description", "subtitle", "children"]);
|
|
73
78
|
const backDropProps = preventBackdropClick
|
|
@@ -80,9 +85,7 @@ export default function BaseModal(_a) {
|
|
|
80
85
|
return (React.createElement(ReactNativeModal, Object.assign({}, rest, backDropProps, { isVisible: isOpen, deviceWidth: width, deviceHeight: height, useNativeDriver: true, useNativeDriverForBackdrop: true, hideModalContentWhileAnimating: true, onModalHide: onClose, style: [defaultModalStyle, modalStyle] }),
|
|
81
86
|
React.createElement(SafeContainer, { style: safeContainerStyle },
|
|
82
87
|
React.createElement(Container, { style: containerStyle },
|
|
83
|
-
!noCloseButton &&
|
|
84
|
-
React.createElement(ClosePressableExtendedBounds, { onPress: onClose },
|
|
85
|
-
React.createElement(Icons.CloseMedium, { color: "neutral.c100", size: "20px" })))),
|
|
88
|
+
!noCloseButton && React.createElement(ModalHeaderCloseButton, { onClose: onClose }),
|
|
86
89
|
React.createElement(ModalHeader, { Icon: Icon, iconColor: iconColor, title: title, description: description, subtitle: subtitle }),
|
|
87
90
|
React.createElement(ContentContainer, null, children)))));
|
|
88
91
|
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { FlatListProps, NativeSyntheticEvent, NativeScrollEvent } from "react-native";
|
|
3
|
-
import
|
|
4
|
-
|
|
2
|
+
import { FlatListProps, NativeSyntheticEvent, NativeScrollEvent, FlatList } from "react-native";
|
|
3
|
+
declare const ScrollListContainer: React.ForwardRefExoticComponent<import("styled-system").SpaceProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, string | number | symbol> & import("styled-system").FlexboxProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & import("styled-system").PositionProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & import("styled-system").ColorProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, string | number | symbol> & import("styled-system").LayoutProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & import("styled-system").OverflowProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>> & import("styled-system").BorderProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, import("csstype").Property.Border<import("styled-system").TLengthStyledSystem>> & import("styled-system").BackgroundProps<Required<import("styled-system").Theme<import("styled-system").TLengthStyledSystem>>, import("csstype").Property.Background<import("styled-system").TLengthStyledSystem>> & {
|
|
4
|
+
columnGap?: string | number | undefined;
|
|
5
|
+
rowGap?: string | number | undefined;
|
|
6
|
+
color?: string | undefined;
|
|
7
|
+
display?: string | undefined;
|
|
8
|
+
position?: string | undefined;
|
|
9
|
+
maxHeight?: number | undefined;
|
|
10
|
+
} & Omit<FlatListProps<any>, "data" | "onScroll" | "renderItem"> & {
|
|
5
11
|
children: React.ReactNode;
|
|
6
|
-
onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
7
|
-
horizontal?: boolean;
|
|
8
|
-
}
|
|
9
|
-
declare const ScrollListContainer: ({ children, onScroll, horizontal, ...props }: ScrollListContainerProps) => JSX.Element;
|
|
12
|
+
onScroll?: ((event: NativeSyntheticEvent<NativeScrollEvent>) => void) | undefined;
|
|
13
|
+
horizontal?: boolean | undefined;
|
|
14
|
+
} & React.RefAttributes<FlatList<any>>>;
|
|
10
15
|
export default ScrollListContainer;
|
|
@@ -9,8 +9,8 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
-
import React from "react";
|
|
13
|
-
import { View } from "react-native";
|
|
12
|
+
import React, { forwardRef } from "react";
|
|
13
|
+
import { View, } from "react-native";
|
|
14
14
|
import Animated from "react-native-reanimated";
|
|
15
15
|
import baseStyled from "../../styled";
|
|
16
16
|
const StyledFlatList = baseStyled.FlatList ``;
|
|
@@ -19,8 +19,8 @@ const AnimatedFlatList = Animated.createAnimatedComponent(StyledFlatList);
|
|
|
19
19
|
** This Layout is a wrapper for FlatList that accepts
|
|
20
20
|
** complex onScroll callback for react-native-reanimated.
|
|
21
21
|
*/
|
|
22
|
-
const ScrollListContainer = (_a) => {
|
|
22
|
+
const ScrollListContainer = forwardRef((_a, ref) => {
|
|
23
23
|
var { children, onScroll, horizontal = false } = _a, props = __rest(_a, ["children", "onScroll", "horizontal"]);
|
|
24
|
-
return (React.createElement(AnimatedFlatList, Object.assign({ data: [...React.Children.toArray(children)], renderItem: ({ item }) => React.createElement(View, null, item), onScroll: onScroll, horizontal: horizontal }, props)));
|
|
25
|
-
};
|
|
24
|
+
return (React.createElement(AnimatedFlatList, Object.assign({ ref: ref, data: [...React.Children.toArray(children)], renderItem: ({ item }) => React.createElement(View, null, item), onScroll: onScroll, horizontal: horizontal }, props)));
|
|
25
|
+
});
|
|
26
26
|
export default ScrollListContainer;
|
|
@@ -2,7 +2,7 @@ import React from "react";
|
|
|
2
2
|
declare type Props = {
|
|
3
3
|
slidesLength: number;
|
|
4
4
|
activeIndex: number;
|
|
5
|
-
onChange
|
|
5
|
+
onChange?: (index: number) => void;
|
|
6
6
|
};
|
|
7
7
|
declare function SlideIndicator({ slidesLength, activeIndex, onChange }: Props): React.ReactElement;
|
|
8
8
|
export default SlideIndicator;
|
|
@@ -40,7 +40,7 @@ function SlideIndicator({ slidesLength, activeIndex = 0, onChange }) {
|
|
|
40
40
|
width: withTiming(activeSize.value, config),
|
|
41
41
|
}));
|
|
42
42
|
return (React.createElement(Container, null,
|
|
43
|
-
slidesArray.map((_, index) => (React.createElement(Bullet, { key: index, onPress: () => onChange(index) }))),
|
|
43
|
+
slidesArray.map((_, index) => (React.createElement(Bullet, { key: index, onPress: () => onChange && onChange(index) }))),
|
|
44
44
|
React.createElement(AnimatedBullet, { style: [animatedStyles] })));
|
|
45
45
|
}
|
|
46
46
|
export default SlideIndicator;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { FlexBoxProps } from "../../Layout/Flex";
|
|
3
|
+
export interface StoryBarProps {
|
|
4
|
+
/**
|
|
5
|
+
* Is this step active.
|
|
6
|
+
*/
|
|
7
|
+
isActive?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Has this step been completed.
|
|
10
|
+
*/
|
|
11
|
+
full?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* The duration of this step.
|
|
14
|
+
*/
|
|
15
|
+
duration?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface StoriesIndicatorProps extends FlexBoxProps {
|
|
18
|
+
/**
|
|
19
|
+
* The index of the active step.
|
|
20
|
+
*/
|
|
21
|
+
activeIndex: number;
|
|
22
|
+
/**
|
|
23
|
+
* The total number of steps.
|
|
24
|
+
*/
|
|
25
|
+
slidesLength: number;
|
|
26
|
+
onChange?: (index: number) => void;
|
|
27
|
+
/**
|
|
28
|
+
* The duration of each step.
|
|
29
|
+
*/
|
|
30
|
+
duration?: number;
|
|
31
|
+
}
|
|
32
|
+
declare function StoriesIndicator({ activeIndex, slidesLength, duration }: StoriesIndicatorProps): JSX.Element;
|
|
33
|
+
declare const _default: React.MemoExoticComponent<typeof StoriesIndicator>;
|
|
34
|
+
export default _default;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React, { useEffect, useMemo } from "react";
|
|
2
|
+
import styled from "styled-components/native";
|
|
3
|
+
import Animated, { useAnimatedStyle, withTiming, useSharedValue, Easing, } from "react-native-reanimated";
|
|
4
|
+
import { Flex } from "../../Layout";
|
|
5
|
+
const ProgressBar = styled.View `
|
|
6
|
+
background-color: ${(p) => p.theme.colors.primary.c100};
|
|
7
|
+
height: 100%;
|
|
8
|
+
width: 100%;
|
|
9
|
+
border-radius: ${(p) => p.theme.radii[2]}px;
|
|
10
|
+
`;
|
|
11
|
+
const AnimatedProgressBar = Animated.createAnimatedComponent(ProgressBar);
|
|
12
|
+
function ActiveProgressBar({ duration }) {
|
|
13
|
+
const width = useSharedValue(0);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
width.value = 100;
|
|
16
|
+
}, [width]);
|
|
17
|
+
const animatedStyles = useAnimatedStyle(() => ({
|
|
18
|
+
width: withTiming(`${width.value}%`, {
|
|
19
|
+
duration: duration || 200,
|
|
20
|
+
easing: Easing.linear,
|
|
21
|
+
}),
|
|
22
|
+
}), [width, duration]);
|
|
23
|
+
return React.createElement(AnimatedProgressBar, { style: animatedStyles });
|
|
24
|
+
}
|
|
25
|
+
function StoryBar({ full = false, isActive, duration }) {
|
|
26
|
+
return (React.createElement(Flex, { height: 4, backgroundColor: "neutral.c50", margin: "auto", borderRadius: 2, flex: 1, mx: 1 }, isActive ? React.createElement(ActiveProgressBar, { duration: duration }) : full ? React.createElement(ProgressBar, null) : null));
|
|
27
|
+
}
|
|
28
|
+
function StoriesIndicator({ activeIndex, slidesLength, duration }) {
|
|
29
|
+
const storiesArray = useMemo(() => new Array(slidesLength).fill(0), [slidesLength]);
|
|
30
|
+
return (React.createElement(Flex, { flexDirection: "row", alignItems: "stretch", width: "100%" }, storiesArray.map((_, storyIndex) => (React.createElement(StoryBar, { key: storyIndex, full: activeIndex > storyIndex, isActive: activeIndex === storyIndex, duration: duration })))));
|
|
31
|
+
}
|
|
32
|
+
export default React.memo(StoriesIndicator);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/native-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0-next.1",
|
|
4
4
|
"description": "Ledger Live - Mobile UI",
|
|
5
5
|
"repository": "https://github.com/LedgerHQ/ui",
|
|
6
6
|
"license": "MIT",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@ledgerhq/icons-ui": "^0.2.4",
|
|
29
|
-
"@ledgerhq/ui-shared": "^0.1.8
|
|
29
|
+
"@ledgerhq/ui-shared": "^0.1.8",
|
|
30
30
|
"@types/color": "^3.0.3",
|
|
31
31
|
"@types/react": "^17.0.39",
|
|
32
32
|
"@types/react-native": "^0.65.9",
|