@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.
@@ -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 = styled.button `
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
- * Horizontal position of the dropdown relative to the dropdown button.
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: 0px ${(p) => p.theme.space[3]}px;
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
- display: "flex",
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: [shift(), flip()],
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
- }, [opened, disabled, refs.reference, refs.floating, handleResizeOrScroll]);
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("div", { ref: divRef },
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: { overflow: "visible", position: strategy, top: y !== null && y !== void 0 ? y : "", left: x !== null && x !== void 0 ? x : "" }, onClick: handleClickInside }, children))));
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
- header?: (props: InnerProps & ExtraProps) => React.ReactNode;
62
+ footer?: SectionRenderFunc<ExtraProps>;
41
63
  /**
42
- * An optional footer displayed below the body.
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
- footer?: (props: InnerProps & ExtraProps) => React.ReactNode;
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: React.ReactElement<StepProps> | React.ReactElement<StepProps>[];
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 ? renderChildren({ children: innerContents }) : innerContents),
28
- footer &&
29
- footer(Object.assign(Object.assign({}, extraProps), { activeIndex, stepsLength: steps.length }))));
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.1",
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.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",