@ledgerhq/native-ui 0.10.0 → 0.11.0-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.
- package/lib/components/Layout/List/VerticalTimeline/TimelineIndicator.d.ts +8 -0
- package/lib/components/Layout/List/VerticalTimeline/TimelineIndicator.js +67 -0
- package/lib/components/Layout/List/VerticalTimeline/TimelineItem.d.ts +9 -0
- package/lib/components/Layout/List/VerticalTimeline/TimelineItem.js +73 -0
- package/lib/components/Layout/List/VerticalTimeline/index.d.ts +14 -0
- package/lib/components/Layout/List/VerticalTimeline/index.js +18 -0
- package/lib/components/Layout/List/index.d.ts +1 -0
- package/lib/components/Layout/List/index.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { Props as FlexProps } from "../../Flex";
|
|
3
|
+
export declare type Props = FlexProps & {
|
|
4
|
+
status: "inactive" | "active" | "completed";
|
|
5
|
+
isFirstItem?: boolean;
|
|
6
|
+
isLastItem?: boolean;
|
|
7
|
+
};
|
|
8
|
+
export default function TimelineIndicator({ status, isFirstItem, isLastItem, ...props }: Props): JSX.Element;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import React from "react";
|
|
13
|
+
import { CircledCheckSolidMedium } from "@ledgerhq/icons-ui/native";
|
|
14
|
+
import styled, { useTheme } from "styled-components/native";
|
|
15
|
+
import Flex from "../../Flex";
|
|
16
|
+
const TopSegment = styled(Flex) `
|
|
17
|
+
height: 20px;
|
|
18
|
+
border-width: ${(p) => (p.hidden ? 0 : 1)}px;
|
|
19
|
+
border-style: solid;
|
|
20
|
+
border-color: ${(p) => p.status === "inactive" ? p.theme.colors.neutral.c50 : p.theme.colors.primary.c80};
|
|
21
|
+
background: ${(p) => p.status === "inactive" ? p.theme.colors.neutral.c50 : p.theme.colors.primary.c80};
|
|
22
|
+
`;
|
|
23
|
+
const BottomSegment = styled(Flex) `
|
|
24
|
+
flex: 1;
|
|
25
|
+
border-width: ${(p) => (p.hidden ? 0 : 1)}px;
|
|
26
|
+
border-style: solid;
|
|
27
|
+
border-color: ${(p) => p.status === "completed" ? p.theme.colors.primary.c80 : p.theme.colors.neutral.c50};
|
|
28
|
+
background: ${(p) => p.status === "completed" ? p.theme.colors.primary.c80 : p.theme.colors.neutral.c50};
|
|
29
|
+
`;
|
|
30
|
+
const getIconBackground = (theme, status, isLastItem) => {
|
|
31
|
+
if (status === "completed") {
|
|
32
|
+
return "transparent";
|
|
33
|
+
}
|
|
34
|
+
else if (isLastItem) {
|
|
35
|
+
return theme.colors.success.c10;
|
|
36
|
+
}
|
|
37
|
+
else if (status === "active") {
|
|
38
|
+
return theme.colors.neutral.c40;
|
|
39
|
+
}
|
|
40
|
+
return theme.colors.background.main;
|
|
41
|
+
};
|
|
42
|
+
const getIconBorder = (theme, status, isLastItem) => {
|
|
43
|
+
if (isLastItem) {
|
|
44
|
+
return theme.colors.success.c100;
|
|
45
|
+
}
|
|
46
|
+
else if (status === "inactive") {
|
|
47
|
+
return theme.colors.neutral.c50;
|
|
48
|
+
}
|
|
49
|
+
return theme.colors.primary.c80;
|
|
50
|
+
};
|
|
51
|
+
const CenterSegment = styled(Flex) `
|
|
52
|
+
border-radius: 9999px;
|
|
53
|
+
width: 20px;
|
|
54
|
+
height: 20px;
|
|
55
|
+
background: ${(p) => getIconBackground(p.theme, p.status, p.isLastItem)};
|
|
56
|
+
border: 2px solid ${(p) => getIconBorder(p.theme, p.status, p.isLastItem)};
|
|
57
|
+
align-items: center;
|
|
58
|
+
justify-content: center;
|
|
59
|
+
`;
|
|
60
|
+
export default function TimelineIndicator(_a) {
|
|
61
|
+
var { status, isFirstItem, isLastItem } = _a, props = __rest(_a, ["status", "isFirstItem", "isLastItem"]);
|
|
62
|
+
const { colors } = useTheme();
|
|
63
|
+
return (React.createElement(Flex, Object.assign({ flexDirection: "column", alignItems: "center" }, props),
|
|
64
|
+
React.createElement(TopSegment, { status: status, hidden: isFirstItem }),
|
|
65
|
+
React.createElement(CenterSegment, { status: status, isLastItem: isLastItem }, status === "completed" && (React.createElement(CircledCheckSolidMedium, { color: isLastItem ? colors.success.c100 : colors.primary.c80, size: 24 }))),
|
|
66
|
+
React.createElement(BottomSegment, { status: status, hidden: isLastItem })));
|
|
67
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { Item } from ".";
|
|
3
|
+
export declare type Props = {
|
|
4
|
+
item: Item;
|
|
5
|
+
formatEstimatedTime?: (_: number) => string;
|
|
6
|
+
isFirstItem?: boolean;
|
|
7
|
+
isLastItem?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export default function TimelineItem({ item, formatEstimatedTime, isFirstItem, isLastItem, }: Props): JSX.Element;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React, { useCallback, useState } from "react";
|
|
2
|
+
import Animated, { Easing, useAnimatedStyle, useDerivedValue, withTiming, } from "react-native-reanimated";
|
|
3
|
+
import styled from "styled-components/native";
|
|
4
|
+
import { Flex } from "../..";
|
|
5
|
+
import { Text, Tag } from "../../..";
|
|
6
|
+
import TimelineIndicator from "./TimelineIndicator";
|
|
7
|
+
const getContainerBackground = (theme, status, isLastItem) => {
|
|
8
|
+
if (isLastItem && status === "completed") {
|
|
9
|
+
return theme.colors.success.c30;
|
|
10
|
+
}
|
|
11
|
+
else if (status === "completed") {
|
|
12
|
+
return theme.colors.primary.c20;
|
|
13
|
+
}
|
|
14
|
+
else if (status === "active") {
|
|
15
|
+
return theme.colors.neutral.c20;
|
|
16
|
+
}
|
|
17
|
+
return theme.colors.neutral.c30;
|
|
18
|
+
};
|
|
19
|
+
const getContainerBorder = (theme, status, isLastItem) => {
|
|
20
|
+
if (isLastItem && status === "completed") {
|
|
21
|
+
return theme.colors.success.c30;
|
|
22
|
+
}
|
|
23
|
+
else if (isLastItem && status === "active") {
|
|
24
|
+
return theme.colors.success.c100;
|
|
25
|
+
}
|
|
26
|
+
else if (status === "completed") {
|
|
27
|
+
return theme.colors.primary.c20;
|
|
28
|
+
}
|
|
29
|
+
else if (status === "active") {
|
|
30
|
+
return theme.colors.primary.c80;
|
|
31
|
+
}
|
|
32
|
+
return theme.colors.neutral.c30;
|
|
33
|
+
};
|
|
34
|
+
const Container = styled(Flex) `
|
|
35
|
+
flex: 1;
|
|
36
|
+
border-radius: ${(p) => p.theme.radii[2]}px;
|
|
37
|
+
background: ${(p) => getContainerBackground(p.theme, p.status, p.isLastItem)};
|
|
38
|
+
border: 1px solid ${(p) => getContainerBorder(p.theme, p.status, p.isLastItem)};
|
|
39
|
+
padding: 20px 16px;
|
|
40
|
+
`;
|
|
41
|
+
export default function TimelineItem({ item, formatEstimatedTime, isFirstItem, isLastItem, }) {
|
|
42
|
+
const [height, setHeight] = useState(0);
|
|
43
|
+
const transition = useDerivedValue(() => {
|
|
44
|
+
return item.status === "active"
|
|
45
|
+
? withTiming(1, { duration: 300, easing: Easing.out(Easing.linear) })
|
|
46
|
+
: withTiming(0, { duration: 300, easing: Easing.in(Easing.linear) });
|
|
47
|
+
}, [item.status]);
|
|
48
|
+
const handleLayoutChange = useCallback((event) => {
|
|
49
|
+
var _a, _b;
|
|
50
|
+
if (height === 0 && ((_b = (_a = event === null || event === void 0 ? void 0 : event.nativeEvent) === null || _a === void 0 ? void 0 : _a.layout) === null || _b === void 0 ? void 0 : _b.height) > 0) {
|
|
51
|
+
setHeight(event.nativeEvent.layout.height);
|
|
52
|
+
}
|
|
53
|
+
}, [setHeight, height]);
|
|
54
|
+
const style = useAnimatedStyle(() => ({
|
|
55
|
+
height: transition.value * height + 1,
|
|
56
|
+
overflow: "hidden",
|
|
57
|
+
}), [height, transition.value]);
|
|
58
|
+
return (React.createElement(Flex, { flexDirection: "row" },
|
|
59
|
+
React.createElement(TimelineIndicator, { status: item.status, isFirstItem: isFirstItem, isLastItem: isLastItem, mr: 4 }),
|
|
60
|
+
React.createElement(Container, { status: item.status, isLastItem: isLastItem, mb: 4 },
|
|
61
|
+
React.createElement(Flex, { flexDirection: "row", justifyContent: "space-between" },
|
|
62
|
+
React.createElement(Text, { variant: "body", color: item.status === "inactive"
|
|
63
|
+
? "neutral.c80"
|
|
64
|
+
: isLastItem
|
|
65
|
+
? "success.c100"
|
|
66
|
+
: "primary.c90" }, item.title),
|
|
67
|
+
(item === null || item === void 0 ? void 0 : item.estimatedTime) && item.status === "active" && (React.createElement(Tag, null, formatEstimatedTime
|
|
68
|
+
? formatEstimatedTime(item.estimatedTime)
|
|
69
|
+
: `${item.estimatedTime / 60} min`))),
|
|
70
|
+
React.createElement(Animated.View, { style: style }, item.renderBody && (React.createElement(Flex, { position: "relative" },
|
|
71
|
+
React.createElement(Flex, { onLayout: handleLayoutChange, pt: 6, position: "absolute", opacity: 0 }, item.renderBody(false)),
|
|
72
|
+
React.createElement(Flex, { pt: 6 }, item.renderBody(item.status === "active"))))))));
|
|
73
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { BaseStyledProps } from "src/components/styled";
|
|
3
|
+
export declare type ItemStatus = "inactive" | "active" | "completed";
|
|
4
|
+
export declare type Item = {
|
|
5
|
+
status: ItemStatus;
|
|
6
|
+
title: string;
|
|
7
|
+
estimatedTime?: number;
|
|
8
|
+
renderBody?: (isDisplayed?: boolean) => ReactNode;
|
|
9
|
+
};
|
|
10
|
+
export declare type Props = BaseStyledProps & {
|
|
11
|
+
steps?: Item[];
|
|
12
|
+
formatEstimatedTime?: (_: number) => string;
|
|
13
|
+
};
|
|
14
|
+
export default function VerticalTimeline({ steps, formatEstimatedTime, ...props }: Props): JSX.Element;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import React from "react";
|
|
13
|
+
import TimelineItem from "./TimelineItem";
|
|
14
|
+
import { Flex } from "../..";
|
|
15
|
+
export default function VerticalTimeline(_a) {
|
|
16
|
+
var { steps, formatEstimatedTime } = _a, props = __rest(_a, ["steps", "formatEstimatedTime"]);
|
|
17
|
+
return (React.createElement(Flex, Object.assign({}, props, { flexDirection: "column" }), steps === null || steps === void 0 ? void 0 : steps.map((step, index) => (React.createElement(TimelineItem, { key: step.title, item: step, formatEstimatedTime: formatEstimatedTime, isFirstItem: index === 0, isLastItem: index === steps.length - 1 })))));
|
|
18
|
+
}
|
|
@@ -2,3 +2,4 @@ export { default as List } from "./List";
|
|
|
2
2
|
export { default as IconBoxList } from "./IconBoxList";
|
|
3
3
|
export { default as TipList } from "./TipList";
|
|
4
4
|
export { default as NumberedList } from "./NumberedList";
|
|
5
|
+
export { default as VerticalTimeline } from "./VerticalTimeline";
|
|
@@ -2,3 +2,4 @@ export { default as List } from "./List";
|
|
|
2
2
|
export { default as IconBoxList } from "./IconBoxList";
|
|
3
3
|
export { default as TipList } from "./TipList";
|
|
4
4
|
export { default as NumberedList } from "./NumberedList";
|
|
5
|
+
export { default as VerticalTimeline } from "./VerticalTimeline";
|