@ledgerhq/react-ui 0.7.1 → 0.7.4
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/components/asorted/Text/styles.js +16 -16
- package/components/cta/Button/index.js +2 -2
- package/components/form/BaseInput/index.d.ts +3 -0
- package/components/form/BaseInput/index.js +12 -1
- package/components/form/DropdownGeneric/index.d.ts +8 -2
- package/components/form/DropdownGeneric/index.js +28 -8
- package/components/form/LegendInput/index.d.ts +1 -0
- package/components/form/NumberInput/index.d.ts +1 -0
- package/components/form/QrCodeInput/index.d.ts +1 -0
- package/components/form/QuantityInput/index.d.ts +1 -0
- package/components/form/SearchInput/index.d.ts +1 -0
- package/components/navigation/FlowStepper/index.d.ts +71 -12
- package/components/navigation/FlowStepper/index.js +56 -7
- package/package.json +2 -2
|
@@ -57,65 +57,65 @@ export const fontStyles = css `
|
|
|
57
57
|
`;
|
|
58
58
|
export const textVariantStyle = {
|
|
59
59
|
h1: {
|
|
60
|
-
fontFamily: "Alpha",
|
|
60
|
+
fontFamily: "Alpha, Inter, Sans",
|
|
61
61
|
fontWeight: 500,
|
|
62
62
|
"text-transform": "uppercase",
|
|
63
63
|
},
|
|
64
64
|
h2: {
|
|
65
|
-
fontFamily: "Alpha",
|
|
65
|
+
fontFamily: "Alpha, Inter, Sans",
|
|
66
66
|
fontWeight: 500,
|
|
67
67
|
"text-transform": "uppercase",
|
|
68
68
|
},
|
|
69
69
|
h3: {
|
|
70
|
-
fontFamily: "Alpha",
|
|
70
|
+
fontFamily: "Alpha, Inter, Sans",
|
|
71
71
|
fontWeight: 500,
|
|
72
72
|
"text-transform": "uppercase",
|
|
73
73
|
},
|
|
74
74
|
h4: {
|
|
75
|
-
fontFamily: "Alpha",
|
|
75
|
+
fontFamily: "Alpha, Inter, Sans",
|
|
76
76
|
fontWeight: 500,
|
|
77
77
|
"text-transform": "uppercase",
|
|
78
78
|
},
|
|
79
79
|
h5: {
|
|
80
|
-
fontFamily: "Alpha",
|
|
80
|
+
fontFamily: "Alpha, Inter, Sans",
|
|
81
81
|
fontWeight: 500,
|
|
82
82
|
"text-transform": "uppercase",
|
|
83
83
|
},
|
|
84
84
|
large: {
|
|
85
|
-
fontFamily: "Inter",
|
|
85
|
+
fontFamily: "Inter, Sans",
|
|
86
86
|
},
|
|
87
87
|
largeLineHeight: {
|
|
88
|
-
fontFamily: "Inter",
|
|
88
|
+
fontFamily: "Inter, Sans",
|
|
89
89
|
lineHeight: 1.7,
|
|
90
90
|
},
|
|
91
91
|
body: {
|
|
92
|
-
fontFamily: "Inter",
|
|
92
|
+
fontFamily: "Inter, Sans",
|
|
93
93
|
},
|
|
94
94
|
bodyLineHeight: {
|
|
95
|
-
fontFamily: "Inter",
|
|
95
|
+
fontFamily: "Inter, Sans",
|
|
96
96
|
lineHeight: 1.7,
|
|
97
97
|
},
|
|
98
98
|
paragraph: {
|
|
99
|
-
fontFamily: "Inter",
|
|
99
|
+
fontFamily: "Inter, Sans",
|
|
100
100
|
},
|
|
101
101
|
paragraphLineHeight: {
|
|
102
|
-
fontFamily: "Inter",
|
|
102
|
+
fontFamily: "Inter, Sans",
|
|
103
103
|
lineHeight: 1.7,
|
|
104
104
|
},
|
|
105
105
|
small: {
|
|
106
|
-
fontFamily: "Inter",
|
|
106
|
+
fontFamily: "Inter, Sans",
|
|
107
107
|
},
|
|
108
108
|
extraSmall: {
|
|
109
|
-
fontFamily: "Inter",
|
|
109
|
+
fontFamily: "Inter, Sans",
|
|
110
110
|
},
|
|
111
111
|
tiny: {
|
|
112
|
-
fontFamily: "Inter",
|
|
112
|
+
fontFamily: "Inter, Sans",
|
|
113
113
|
},
|
|
114
114
|
micro: {
|
|
115
|
-
fontFamily: "Inter",
|
|
115
|
+
fontFamily: "Inter, Sans",
|
|
116
116
|
},
|
|
117
117
|
subtitle: {
|
|
118
|
-
fontFamily: "Inter",
|
|
118
|
+
fontFamily: "Inter, Sans",
|
|
119
119
|
fontWeight: 600,
|
|
120
120
|
"text-transform": "uppercase",
|
|
121
121
|
},
|
|
@@ -119,7 +119,7 @@ const getVariantColors = (p) => ({
|
|
|
119
119
|
}
|
|
120
120
|
`,
|
|
121
121
|
});
|
|
122
|
-
export const ButtonUnstyled =
|
|
122
|
+
export const ButtonUnstyled = baseStyled.button `
|
|
123
123
|
all: unset;
|
|
124
124
|
cursor: pointer;
|
|
125
125
|
|
|
@@ -157,7 +157,7 @@ export const Base = baseStyled.button.attrs((p) => {
|
|
|
157
157
|
&:active {
|
|
158
158
|
box-shadow: 0 0 0 4px ${(p) => rgba(p.theme.colors.primary.c60, 0.4)};
|
|
159
159
|
}
|
|
160
|
-
&:focus {
|
|
160
|
+
&:focus, &:hover {
|
|
161
161
|
box-shadow: 0 0 0 2px ${(p) => rgba(p.theme.colors.primary.c60, 0.4)};
|
|
162
162
|
}
|
|
163
163
|
|
|
@@ -14,6 +14,7 @@ export declare type InputProps<T = ValueType> = Omit<CommonProps, "value" | "onC
|
|
|
14
14
|
renderRight?: ((props: InputProps<T>) => React.ReactNode) | React.ReactNode;
|
|
15
15
|
unwrapped?: boolean;
|
|
16
16
|
containerProps?: InputContainerProps;
|
|
17
|
+
clearable?: boolean;
|
|
17
18
|
/**
|
|
18
19
|
* A function can be provided to serialize a value of any type to a string.
|
|
19
20
|
*
|
|
@@ -56,6 +57,7 @@ export declare const InputRenderRightContainer: import("styled-components").Styl
|
|
|
56
57
|
alignItems: string;
|
|
57
58
|
pr: string;
|
|
58
59
|
}, "overflow" | "p" | "color" | "size" | "rowGap" | "alignContent" | "alignItems" | "alignSelf" | "backgroundColor" | "borderBottomColor" | "borderBottomLeftRadius" | "borderBottomRightRadius" | "borderBottomStyle" | "borderBottomWidth" | "borderLeftColor" | "borderLeftStyle" | "borderLeftWidth" | "borderRightColor" | "borderRightStyle" | "borderRightWidth" | "borderTopColor" | "borderTopLeftRadius" | "borderTopRightRadius" | "borderTopStyle" | "borderTopWidth" | "bottom" | "columnGap" | "display" | "flexBasis" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "height" | "justifyContent" | "justifyItems" | "justifySelf" | "left" | "marginBottom" | "marginLeft" | "marginRight" | "marginTop" | "maxHeight" | "maxWidth" | "minHeight" | "minWidth" | "opacity" | "order" | "overflowX" | "overflowY" | "paddingBottom" | "paddingLeft" | "paddingRight" | "paddingTop" | "position" | "right" | "top" | "verticalAlign" | "width" | "zIndex" | "border" | "borderBottom" | "borderColor" | "borderLeft" | "borderRadius" | "borderRight" | "borderStyle" | "borderTop" | "borderWidth" | "flex" | "margin" | "padding" | "m" | "mt" | "mr" | "mb" | "ml" | "mx" | "marginX" | "my" | "marginY" | "pt" | "pr" | "pb" | "pl" | "px" | "paddingX" | "py" | "paddingY" | "bg" | "borderX" | "borderY">;
|
|
60
|
+
export declare const ClearableButtonUnstyled: import("styled-components").StyledComponent<"button", import("styled-components").DefaultTheme, {}, never>;
|
|
59
61
|
declare function Input<T = ValueType>(props: InputProps<T>, ref?: React.ForwardedRef<HTMLInputElement>): JSX.Element;
|
|
60
62
|
declare const _default: <T>(props: Omit<CommonProps, "onChange" | "value"> & {
|
|
61
63
|
value: T;
|
|
@@ -76,6 +78,7 @@ declare const _default: <T>(props: Omit<CommonProps, "onChange" | "value"> & {
|
|
|
76
78
|
as?: string | import("react").ComponentType<any> | undefined;
|
|
77
79
|
forwardedAs?: string | import("react").ComponentType<any> | undefined;
|
|
78
80
|
}) | undefined;
|
|
81
|
+
clearable?: boolean | undefined;
|
|
79
82
|
/**
|
|
80
83
|
* A function can be provided to serialize a value of any type to a string.
|
|
81
84
|
*
|
|
@@ -12,9 +12,11 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
12
12
|
import styled, { css } from "styled-components";
|
|
13
13
|
import { typography } from "styled-system";
|
|
14
14
|
import React, { useState, useMemo, useCallback } from "react";
|
|
15
|
+
import CircledCrossSolidMedium from "@ledgerhq/icons-ui/react/CircledCrossSolidMedium";
|
|
15
16
|
import FlexBox from "../../layout/Flex";
|
|
16
17
|
import Text from "../../asorted/Text";
|
|
17
18
|
import { rgba } from "../../../styles/helpers";
|
|
19
|
+
import { ButtonUnstyled } from "../../cta/Button";
|
|
18
20
|
export const InputContainer = styled.div `
|
|
19
21
|
display: flex;
|
|
20
22
|
height: 48px;
|
|
@@ -109,17 +111,23 @@ export const InputRenderRightContainer = styled(FlexBox).attrs(() => ({
|
|
|
109
111
|
alignItems: "center",
|
|
110
112
|
pr: "16px",
|
|
111
113
|
})) ``;
|
|
114
|
+
export const ClearableButtonUnstyled = styled(ButtonUnstyled) `
|
|
115
|
+
display: flex;
|
|
116
|
+
`;
|
|
112
117
|
// Yes, this is dirty. If you can figure out a better way please change the code :).
|
|
113
118
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
114
119
|
const IDENTITY = (_) => _;
|
|
115
120
|
function Input(props, ref) {
|
|
116
|
-
const { value, disabled, error, warning, onChange, onChangeEvent, renderLeft, renderRight, unwrapped, containerProps, serialize = IDENTITY, deserialize = IDENTITY } = props, htmlInputProps = __rest(props, ["value", "disabled", "error", "warning", "onChange", "onChangeEvent", "renderLeft", "renderRight", "unwrapped", "containerProps", "serialize", "deserialize"]);
|
|
121
|
+
const { value, disabled, error, warning, onChange, onChangeEvent, renderLeft, renderRight, unwrapped, containerProps, serialize = IDENTITY, deserialize = IDENTITY, clearable } = props, htmlInputProps = __rest(props, ["value", "disabled", "error", "warning", "onChange", "onChangeEvent", "renderLeft", "renderRight", "unwrapped", "containerProps", "serialize", "deserialize", "clearable"]);
|
|
117
122
|
const [focus, setFocus] = useState(false);
|
|
118
123
|
const inputValue = useMemo(() => serialize(value), [serialize, value]);
|
|
119
124
|
const handleChange = useCallback((e) => {
|
|
120
125
|
onChange && onChange(deserialize(e.target.value));
|
|
121
126
|
onChangeEvent && onChangeEvent(e);
|
|
122
127
|
}, [onChange, onChangeEvent, deserialize]);
|
|
128
|
+
const handleClear = useCallback(() => {
|
|
129
|
+
onChange && onChange(deserialize(""));
|
|
130
|
+
}, [onChange, deserialize]);
|
|
123
131
|
const inner = (React.createElement(React.Fragment, null,
|
|
124
132
|
typeof renderLeft === "function" ? renderLeft(props) : renderLeft,
|
|
125
133
|
React.createElement(BaseInput, Object.assign({ ref: ref }, htmlInputProps, { disabled: disabled, error: error, warning: warning, onChange: handleChange, value: inputValue, onFocus: (event) => {
|
|
@@ -129,6 +137,9 @@ function Input(props, ref) {
|
|
|
129
137
|
setFocus(false);
|
|
130
138
|
htmlInputProps.onBlur && htmlInputProps.onBlur(event);
|
|
131
139
|
} })),
|
|
140
|
+
clearable && inputValue && (React.createElement(FlexBox, { alignItems: "center", mr: 7 },
|
|
141
|
+
React.createElement(ClearableButtonUnstyled, { onClick: handleClear },
|
|
142
|
+
React.createElement(CircledCrossSolidMedium, { size: 18, color: "neutral.c50" })))),
|
|
132
143
|
typeof renderRight === "function" ? renderRight(props) : renderRight));
|
|
133
144
|
if (unwrapped) {
|
|
134
145
|
return (React.createElement(FlexBox, { alignItems: "stretch", style: { height: "100%" } }, inner));
|
|
@@ -26,11 +26,17 @@ export declare type Props = {
|
|
|
26
26
|
*/
|
|
27
27
|
children: React.ReactNode;
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* Vertical alignment of the dropdown relative to the dropdown button.
|
|
30
30
|
* Will automatically adjust to the document to avoid overflowing.
|
|
31
31
|
* Defaults to "bottom".
|
|
32
32
|
*/
|
|
33
33
|
placement?: Placement;
|
|
34
|
+
/**
|
|
35
|
+
* Controls whether the dropdown will flip its side to keep it in view
|
|
36
|
+
* in case there isn't enough space available. See https://floating-ui.com/docs/flip
|
|
37
|
+
* Defaults to false.
|
|
38
|
+
*/
|
|
39
|
+
flipDisabled?: boolean;
|
|
34
40
|
};
|
|
35
|
-
declare const DropdownGeneric: ({ label, closeOnClickOutside, closeOnClickInside, disabled, placement, children, }: Props) => JSX.Element;
|
|
41
|
+
declare const DropdownGeneric: ({ label, closeOnClickOutside, closeOnClickInside, disabled, placement, flipDisabled, children, }: Props) => JSX.Element;
|
|
36
42
|
export default DropdownGeneric;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
-
import { useFloating, getScrollParents, shift, flip } from "@floating-ui/react-dom";
|
|
2
|
+
import { useFloating, getScrollParents, shift, size, flip } from "@floating-ui/react-dom";
|
|
3
3
|
import styled from "styled-components";
|
|
4
4
|
import { Icons } from "../../../";
|
|
5
5
|
import Flex from "../../layout/Flex";
|
|
@@ -15,13 +15,13 @@ const ButtonContainer = styled(Box).attrs({
|
|
|
15
15
|
> :last-child {
|
|
16
16
|
/* targeting the dropdown icon */
|
|
17
17
|
${(p) => p.opened && "transform: rotate(180deg);"}
|
|
18
|
-
margin:
|
|
18
|
+
margin-left: ${(p) => p.theme.space[3]}px;
|
|
19
19
|
}
|
|
20
20
|
`;
|
|
21
21
|
const DropdownContainer = styled(Flex).attrs(({ theme }) => {
|
|
22
22
|
const isLight = theme.colors.type === "light";
|
|
23
23
|
return {
|
|
24
|
-
|
|
24
|
+
zIndex: 1,
|
|
25
25
|
flexDirection: "column",
|
|
26
26
|
padding: 3,
|
|
27
27
|
border: `1px solid ${theme.colors.neutral[isLight ? "c20" : "c30"]}`,
|
|
@@ -30,11 +30,14 @@ const DropdownContainer = styled(Flex).attrs(({ theme }) => {
|
|
|
30
30
|
color: theme.colors.neutral.c80,
|
|
31
31
|
};
|
|
32
32
|
}) `
|
|
33
|
+
overflow-y: auto;
|
|
33
34
|
box-shadow: 0px 6px 12px rgba(0, 0, 0, ${(p) => (p.theme.colors.type === "light" ? 0.04 : 0.08)});
|
|
34
35
|
`;
|
|
35
36
|
export const placements = ["bottom-start", "bottom", "bottom-end"];
|
|
36
|
-
const DropdownGeneric = ({ label, closeOnClickOutside = true, closeOnClickInside = false, disabled = false, placement = "bottom", children, }) => {
|
|
37
|
+
const DropdownGeneric = ({ label, closeOnClickOutside = true, closeOnClickInside = false, disabled = false, placement = "bottom", flipDisabled = false, children, }) => {
|
|
37
38
|
const divRef = useRef(null);
|
|
39
|
+
const [maxHeight, setMaxHeight] = useState();
|
|
40
|
+
const [maxWidth, setMaxWidth] = useState();
|
|
38
41
|
const [opened, setOpened] = useState(false);
|
|
39
42
|
const handleClickButton = useCallback(() => {
|
|
40
43
|
if (!disabled)
|
|
@@ -46,7 +49,17 @@ const DropdownGeneric = ({ label, closeOnClickOutside = true, closeOnClickInside
|
|
|
46
49
|
}, [setOpened, closeOnClickInside]);
|
|
47
50
|
const { x, y, reference, floating, strategy, update, refs } = useFloating({
|
|
48
51
|
placement: placements.includes(placement) ? placement : "bottom",
|
|
49
|
-
middleware: [
|
|
52
|
+
middleware: [
|
|
53
|
+
shift(),
|
|
54
|
+
...(flipDisabled ? [] : [flip()]),
|
|
55
|
+
size({
|
|
56
|
+
padding: 6,
|
|
57
|
+
apply({ height, width }) {
|
|
58
|
+
setMaxHeight(height);
|
|
59
|
+
setMaxWidth(width);
|
|
60
|
+
},
|
|
61
|
+
}),
|
|
62
|
+
],
|
|
50
63
|
});
|
|
51
64
|
const handleResizeOrScroll = useCallback(() => {
|
|
52
65
|
if (opened && !disabled)
|
|
@@ -70,7 +83,7 @@ const DropdownGeneric = ({ label, closeOnClickOutside = true, closeOnClickInside
|
|
|
70
83
|
parent.removeEventListener("resize", handleResizeOrScroll);
|
|
71
84
|
});
|
|
72
85
|
};
|
|
73
|
-
}, [
|
|
86
|
+
}, [flipDisabled, refs.reference, refs.floating, handleResizeOrScroll]);
|
|
74
87
|
useEffect(() => {
|
|
75
88
|
function handleClickOutside(event) {
|
|
76
89
|
if (closeOnClickOutside &&
|
|
@@ -86,10 +99,17 @@ const DropdownGeneric = ({ label, closeOnClickOutside = true, closeOnClickInside
|
|
|
86
99
|
};
|
|
87
100
|
}, [closeOnClickOutside, opened, setOpened, divRef]);
|
|
88
101
|
const color = disabled ? "neutral.c50" : "neutral.c100";
|
|
89
|
-
return (React.createElement(
|
|
102
|
+
return (React.createElement(Box, { ref: divRef },
|
|
90
103
|
React.createElement(ButtonContainer, { ref: reference, onClick: handleClickButton, disabled: disabled, opened: opened && !disabled },
|
|
91
104
|
React.createElement(Text, { variant: "paragraph", fontWeight: "medium", color: color }, label),
|
|
92
105
|
React.createElement(Icons.DropdownMedium, { size: 20, color: color })),
|
|
93
|
-
opened && !disabled && (React.createElement(DropdownContainer, { ref: floating, style: {
|
|
106
|
+
opened && !disabled && (React.createElement(DropdownContainer, { ref: floating, style: {
|
|
107
|
+
position: strategy,
|
|
108
|
+
top: y !== null && y !== void 0 ? y : "",
|
|
109
|
+
left: x !== null && x !== void 0 ? x : "",
|
|
110
|
+
maxHeight: maxHeight ? `${maxHeight}px` : "",
|
|
111
|
+
maxWidth: maxWidth ? "" : "",
|
|
112
|
+
// maxWidth: maxWidth ? `${maxWidth}px` : "", /* TODO: fix this */
|
|
113
|
+
}, onClick: handleClickInside }, children))));
|
|
94
114
|
};
|
|
95
115
|
export default DropdownGeneric;
|
|
@@ -22,6 +22,7 @@ declare const _default: React.ForwardRefExoticComponent<Omit<import("../BaseInpu
|
|
|
22
22
|
as?: string | import("react").ComponentType<any> | undefined;
|
|
23
23
|
forwardedAs?: string | import("react").ComponentType<any> | undefined;
|
|
24
24
|
}) | undefined;
|
|
25
|
+
clearable?: boolean | undefined;
|
|
25
26
|
serialize?: ((value: string) => string) | undefined;
|
|
26
27
|
deserialize?: ((value: string) => string) | undefined;
|
|
27
28
|
} & {
|
|
@@ -19,6 +19,7 @@ declare const _default: React.ForwardRefExoticComponent<Omit<import("../BaseInpu
|
|
|
19
19
|
as?: string | import("react").ComponentType<any> | undefined;
|
|
20
20
|
forwardedAs?: string | import("react").ComponentType<any> | undefined;
|
|
21
21
|
}) | undefined;
|
|
22
|
+
clearable?: boolean | undefined;
|
|
22
23
|
serialize?: ((value: number | undefined) => string) | undefined;
|
|
23
24
|
deserialize?: ((value: string) => number | undefined) | undefined;
|
|
24
25
|
} & {
|
|
@@ -19,6 +19,7 @@ declare const _default: React.ForwardRefExoticComponent<Omit<import("../BaseInpu
|
|
|
19
19
|
as?: string | import("react").ComponentType<any> | undefined;
|
|
20
20
|
forwardedAs?: string | import("react").ComponentType<any> | undefined;
|
|
21
21
|
}) | undefined;
|
|
22
|
+
clearable?: boolean | undefined;
|
|
22
23
|
serialize?: ((value: string) => string) | undefined;
|
|
23
24
|
deserialize?: ((value: string) => string) | undefined;
|
|
24
25
|
} & {
|
|
@@ -19,6 +19,7 @@ declare const _default: React.ForwardRefExoticComponent<Omit<import("../BaseInpu
|
|
|
19
19
|
as?: string | import("react").ComponentType<any> | undefined;
|
|
20
20
|
forwardedAs?: string | import("react").ComponentType<any> | undefined;
|
|
21
21
|
}) | undefined;
|
|
22
|
+
clearable?: boolean | undefined;
|
|
22
23
|
serialize?: ((value: string) => string) | undefined;
|
|
23
24
|
deserialize?: ((value: string) => string) | undefined;
|
|
24
25
|
} & {
|
|
@@ -19,6 +19,7 @@ declare const _default: React.ForwardRefExoticComponent<Omit<import("../BaseInpu
|
|
|
19
19
|
as?: string | import("react").ComponentType<any> | undefined;
|
|
20
20
|
forwardedAs?: string | import("react").ComponentType<any> | undefined;
|
|
21
21
|
}) | undefined;
|
|
22
|
+
clearable?: boolean | undefined;
|
|
22
23
|
serialize?: ((value: string) => string) | undefined;
|
|
23
24
|
deserialize?: ((value: string) => string) | undefined;
|
|
24
25
|
} & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -2,14 +2,22 @@ import React from "react";
|
|
|
2
2
|
import { Props as StepperProps } from "../progress/Stepper";
|
|
3
3
|
import { FlexBoxProps as FlexProps } from "../../layout/Flex";
|
|
4
4
|
export declare type StepProps = {
|
|
5
|
-
/**
|
|
6
|
-
* The label of the step.
|
|
7
|
-
*/
|
|
8
|
-
label: string;
|
|
9
5
|
/**
|
|
10
6
|
* A specific index, can be used to explicitely order steps.
|
|
11
7
|
*/
|
|
12
8
|
index?: number;
|
|
9
|
+
/**
|
|
10
|
+
* Custom header for this step.
|
|
11
|
+
*/
|
|
12
|
+
header?: React.ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* Custom footer for this step.
|
|
15
|
+
*/
|
|
16
|
+
footer?: React.ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* The label of the step.
|
|
19
|
+
*/
|
|
20
|
+
label: string;
|
|
13
21
|
/**
|
|
14
22
|
* Hides the step from the progress stepper.
|
|
15
23
|
*/
|
|
@@ -29,19 +37,34 @@ interface InnerProps {
|
|
|
29
37
|
*/
|
|
30
38
|
stepsLength: number;
|
|
31
39
|
}
|
|
40
|
+
declare type StepChild = React.ReactElement<StepProps>;
|
|
41
|
+
declare type SectionRenderFunc<ExtraProps> = (props: InnerProps & ExtraProps) => React.ReactNode;
|
|
42
|
+
declare type SectionStepRenderFunc<ExtraProps> = (args: InnerProps & ExtraProps & {
|
|
43
|
+
children: React.ReactNode;
|
|
44
|
+
}) => React.ReactNode;
|
|
32
45
|
export interface Props<ExtraProps> {
|
|
33
46
|
/**
|
|
34
47
|
* The index of the active step.
|
|
35
48
|
*/
|
|
36
49
|
activeIndex: number;
|
|
37
50
|
/**
|
|
38
|
-
* An optional header displayed above the stepper.
|
|
51
|
+
* An optional generic header displayed above the stepper.
|
|
52
|
+
*/
|
|
53
|
+
header?: SectionRenderFunc<ExtraProps>;
|
|
54
|
+
/**
|
|
55
|
+
* Custom rendering function to wrap the header (only used if the `header` is defined
|
|
56
|
+
* on the child for the current step.)
|
|
57
|
+
*/
|
|
58
|
+
renderStepHeader?: SectionStepRenderFunc<ExtraProps>;
|
|
59
|
+
/**
|
|
60
|
+
* An optional generic footer displayed below the body.
|
|
39
61
|
*/
|
|
40
|
-
|
|
62
|
+
footer?: SectionRenderFunc<ExtraProps>;
|
|
41
63
|
/**
|
|
42
|
-
*
|
|
64
|
+
* Custom rendering function to wrap the footer (only used if the `footer` is defined
|
|
65
|
+
* on the child for the current step.)
|
|
43
66
|
*/
|
|
44
|
-
|
|
67
|
+
renderStepFooter?: SectionStepRenderFunc<ExtraProps>;
|
|
45
68
|
/**
|
|
46
69
|
* Extra props that are passed to the header and footer render functions.
|
|
47
70
|
*/
|
|
@@ -61,17 +84,53 @@ export interface Props<ExtraProps> {
|
|
|
61
84
|
/**
|
|
62
85
|
* Custom rendering function to wrap children.
|
|
63
86
|
*/
|
|
64
|
-
renderChildren?: (args: {
|
|
87
|
+
renderChildren?: (args: InnerProps & ExtraProps & {
|
|
65
88
|
children: React.ReactNode;
|
|
66
89
|
}) => React.ReactNode;
|
|
67
|
-
/**
|
|
68
90
|
/**
|
|
69
91
|
* A list of children representing each step of the flow.
|
|
92
|
+
* Each child can have a prop `stepHeader` and/or `stepFooter` that will
|
|
93
|
+
* associate a custom header/footer to this particular step.
|
|
94
|
+
* The custom header/footer can be wrapped using the prop renderStepHeader/renderStepFooter.
|
|
70
95
|
*/
|
|
71
|
-
children:
|
|
96
|
+
children: StepChild | StepChild[];
|
|
72
97
|
}
|
|
73
|
-
declare function FlowStepper<ExtraProps>({ activeIndex, header, footer, extraProps, extraContainerProps, extraStepperProps, extraStepperContainerProps, renderChildren, children, }: Props<ExtraProps>): JSX.Element;
|
|
98
|
+
declare function FlowStepper<ExtraProps>({ activeIndex, header, renderStepHeader, footer, renderStepFooter, extraProps, extraContainerProps, extraStepperProps, extraStepperContainerProps, renderChildren, children, }: Props<ExtraProps>): JSX.Element;
|
|
74
99
|
declare namespace FlowStepper {
|
|
75
100
|
var Step: ({ children }: StepProps) => JSX.Element;
|
|
101
|
+
var Indexed: typeof FlowStepperIndexed;
|
|
76
102
|
}
|
|
77
103
|
export default FlowStepper;
|
|
104
|
+
export declare type IndexedStepProps = StepProps & {
|
|
105
|
+
/**
|
|
106
|
+
* String to identify the step. Must be different from sibling steps's `key` prop.
|
|
107
|
+
*/
|
|
108
|
+
itemKey: string;
|
|
109
|
+
};
|
|
110
|
+
declare type IndexedStepperChild = React.ReactElement<IndexedStepProps>;
|
|
111
|
+
export declare type IndexedProps<ExtraProps> = Omit<Props<ExtraProps>, "activeIndex" | "children"> & {
|
|
112
|
+
/**
|
|
113
|
+
* The key of the active step
|
|
114
|
+
*/
|
|
115
|
+
activeKey: string;
|
|
116
|
+
/**
|
|
117
|
+
* A list of children representing each step of the flow.
|
|
118
|
+
*/
|
|
119
|
+
children: IndexedStepperChild | IndexedStepperChild[];
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* This is a FlowStepper where each child must have an `itemKey: string` prop
|
|
123
|
+
* and the active step is defined by the `activeKey: string` prop.
|
|
124
|
+
*
|
|
125
|
+
* This allows for usages with a lot of steps where dealing with indices could be
|
|
126
|
+
* painful and error prone (for instance inserting/removing a step somewhere would shift
|
|
127
|
+
* the indices of the following steps and navigation would be impacted).
|
|
128
|
+
*
|
|
129
|
+
* By using string identifiers (`itemKey`) for each step, it's more "human readable"
|
|
130
|
+
* and less error prone to setup a navigation logic between steps.
|
|
131
|
+
*/
|
|
132
|
+
declare function FlowStepperIndexed<ExtraProps>(props: IndexedProps<ExtraProps>): JSX.Element;
|
|
133
|
+
declare namespace FlowStepperIndexed {
|
|
134
|
+
var Step: typeof IndexedStep;
|
|
135
|
+
}
|
|
136
|
+
declare function IndexedStep({ children }: IndexedStepProps): JSX.Element;
|
|
@@ -1,35 +1,84 @@
|
|
|
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
|
+
};
|
|
1
12
|
import React from "react";
|
|
2
13
|
import { isElement } from "react-is";
|
|
3
14
|
import Flex from "../../layout/Flex";
|
|
4
15
|
import { Stepper } from "..";
|
|
5
|
-
function FlowStepper({ activeIndex, header, footer, extraProps, extraContainerProps, extraStepperProps, extraStepperContainerProps, renderChildren, children, }) {
|
|
6
|
-
const { steps, innerContents } = React.Children.toArray(children).reduce((acc, child, idx) => {
|
|
16
|
+
function FlowStepper({ activeIndex, header, renderStepHeader, footer, renderStepFooter, extraProps, extraContainerProps, extraStepperProps, extraStepperContainerProps, renderChildren, children, }) {
|
|
17
|
+
const { steps, innerContents, stepFooter, stepHeader } = React.Children.toArray(children).reduce((acc, child, idx) => {
|
|
7
18
|
var _a;
|
|
8
19
|
const index = (_a = (isElement(child) && child.props.index)) !== null && _a !== void 0 ? _a : idx;
|
|
9
20
|
const label = isElement(child) && child.props.label;
|
|
10
21
|
const hidden = isElement(child) && child.props.hidden;
|
|
22
|
+
const stepHeader = isElement(child) && child.props.header;
|
|
23
|
+
const stepFooter = isElement(child) && child.props.footer;
|
|
11
24
|
if (label && !hidden) {
|
|
12
25
|
acc.steps[index] = label;
|
|
13
26
|
}
|
|
14
27
|
if (index === activeIndex) {
|
|
15
28
|
acc.innerContents = child;
|
|
29
|
+
acc.stepFooter = stepFooter;
|
|
30
|
+
acc.stepHeader = stepHeader;
|
|
16
31
|
}
|
|
17
32
|
return acc;
|
|
18
33
|
}, {
|
|
19
34
|
steps: [],
|
|
20
35
|
innerContents: null,
|
|
36
|
+
stepHeader: null,
|
|
37
|
+
stepFooter: null,
|
|
21
38
|
});
|
|
39
|
+
const renderArgs = Object.assign(Object.assign({}, extraProps), { activeIndex, stepsLength: steps.length });
|
|
40
|
+
function getSectionContents(renderFunc, stepSection, renderStepFunc) {
|
|
41
|
+
return stepSection
|
|
42
|
+
? renderStepFunc
|
|
43
|
+
? renderStepFunc(Object.assign(Object.assign({}, renderArgs), { children: stepSection }))
|
|
44
|
+
: stepSection
|
|
45
|
+
: renderFunc && renderFunc(renderArgs);
|
|
46
|
+
}
|
|
22
47
|
return (React.createElement(Flex, Object.assign({ flex: 1, flexDirection: "column" }, extraContainerProps),
|
|
23
|
-
header
|
|
24
|
-
header(Object.assign(Object.assign({}, extraProps), { activeIndex, stepsLength: steps.length })),
|
|
48
|
+
getSectionContents(header, stepHeader, renderStepHeader),
|
|
25
49
|
React.createElement(Flex, Object.assign({ my: 8, justifyContent: "center" }, extraStepperContainerProps),
|
|
26
50
|
React.createElement(Stepper, Object.assign({ activeIndex: activeIndex, steps: steps, flex: 1 }, extraStepperProps))),
|
|
27
|
-
React.createElement(Flex, { flex: 1, flexDirection: "column", position: "relative" }, renderChildren
|
|
28
|
-
|
|
29
|
-
|
|
51
|
+
React.createElement(Flex, { flex: 1, flexDirection: "column", position: "relative" }, renderChildren
|
|
52
|
+
? renderChildren(Object.assign(Object.assign({}, renderArgs), { children: innerContents }))
|
|
53
|
+
: innerContents),
|
|
54
|
+
getSectionContents(footer, stepFooter, renderStepFooter)));
|
|
30
55
|
}
|
|
31
56
|
function Step({ children }) {
|
|
32
57
|
return React.createElement(React.Fragment, null, children);
|
|
33
58
|
}
|
|
34
59
|
FlowStepper.Step = Step;
|
|
35
60
|
export default FlowStepper;
|
|
61
|
+
/**
|
|
62
|
+
* This is a FlowStepper where each child must have an `itemKey: string` prop
|
|
63
|
+
* and the active step is defined by the `activeKey: string` prop.
|
|
64
|
+
*
|
|
65
|
+
* This allows for usages with a lot of steps where dealing with indices could be
|
|
66
|
+
* painful and error prone (for instance inserting/removing a step somewhere would shift
|
|
67
|
+
* the indices of the following steps and navigation would be impacted).
|
|
68
|
+
*
|
|
69
|
+
* By using string identifiers (`itemKey`) for each step, it's more "human readable"
|
|
70
|
+
* and less error prone to setup a navigation logic between steps.
|
|
71
|
+
*/
|
|
72
|
+
function FlowStepperIndexed(props) {
|
|
73
|
+
const { activeKey, children } = props, otherProps = __rest(props, ["activeKey", "children"]);
|
|
74
|
+
const activeIndex = React.Children.toArray(children).findIndex((child) => {
|
|
75
|
+
const res = isElement(child) && child.props.itemKey === activeKey;
|
|
76
|
+
return res;
|
|
77
|
+
});
|
|
78
|
+
return (React.createElement(FlowStepper, Object.assign({}, otherProps, { activeIndex: activeIndex }), children));
|
|
79
|
+
}
|
|
80
|
+
function IndexedStep({ children }) {
|
|
81
|
+
return React.createElement(React.Fragment, null, children);
|
|
82
|
+
}
|
|
83
|
+
FlowStepperIndexed.Step = IndexedStep;
|
|
84
|
+
FlowStepper.Indexed = FlowStepperIndexed;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/react-ui",
|
|
3
3
|
"description": "Ledger Live - Desktop UI",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.4",
|
|
5
5
|
"author": "Ledger Live Team <team-live@ledger.fr>",
|
|
6
6
|
"repository": "https://github.com/LedgerHQ/ui",
|
|
7
7
|
"license": "MIT",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@floating-ui/react-dom": "^0.4.0",
|
|
31
|
-
"@ledgerhq/icons-ui": "^0.2.
|
|
31
|
+
"@ledgerhq/icons-ui": "^0.2.3",
|
|
32
32
|
"@ledgerhq/ui-shared": "^0.1.5",
|
|
33
33
|
"@tippyjs/react": "^4.2.6",
|
|
34
34
|
"@types/color": "^3.0.2",
|