@ovotech/element-native 5.6.0 → 5.7.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.
Files changed (102) hide show
  1. package/dist/components/Accordion/styles.d.ts +3 -1734
  2. package/dist/components/ActionList/ActionListItems/DataListItem.js +3 -1
  3. package/dist/components/ActionList/ActionListItems/ToggleListItem.js +3 -4
  4. package/dist/components/ActionList/ActionListItems/styles.d.ts +22 -10404
  5. package/dist/components/ActionList/ActionListItems/styles.js +18 -16
  6. package/dist/components/ActionList/styled.d.ts +12 -6936
  7. package/dist/components/Badge/Badge.d.ts +1 -578
  8. package/dist/components/BottomActionBar/BottomActionBar.d.ts +12 -0
  9. package/dist/components/BottomActionBar/BottomActionBar.js +80 -0
  10. package/dist/components/BottomActionBar/OverlayProvider.d.ts +8 -0
  11. package/dist/components/BottomActionBar/OverlayProvider.js +38 -0
  12. package/dist/components/BottomActionBar/index.d.ts +2 -0
  13. package/dist/components/BottomActionBar/index.js +7 -0
  14. package/dist/components/Button/Button.styles.d.ts +5 -2312
  15. package/dist/components/Card/Card.styles.d.ts +3 -1734
  16. package/dist/components/Cards/AccountCard/AccountCard.styles.d.ts +8 -4624
  17. package/dist/components/Cards/BalanceCard/BalanceCard.styles.d.ts +15 -8670
  18. package/dist/components/Cards/DisruptiveCard/DisruptiveCard.styles.d.ts +1 -578
  19. package/dist/components/Cards/HeroImageCard/HeroImageCard.styles.d.ts +3 -1734
  20. package/dist/components/Cards/IconDataCard/IconDataCard.styles.d.ts +4 -2312
  21. package/dist/components/Cards/IconTextCard/IconTextCard.styles.d.ts +3 -1734
  22. package/dist/components/Cards/IllustrationTextCard/IllustrationTextCard.styles.d.ts +5 -2890
  23. package/dist/components/Cards/IllustrationTextCard/IllustrationTextCard.styles.js +1 -2
  24. package/dist/components/Cards/LinkTextCard/LinkTextCard.styles.d.ts +5 -2890
  25. package/dist/components/Cards/OfferCard/OfferCard.d.ts +22 -0
  26. package/dist/components/Cards/OfferCard/OfferCard.js +36 -0
  27. package/dist/components/Cards/OfferCard/OfferCard.styles.d.ts +34 -0
  28. package/dist/components/Cards/OfferCard/OfferCard.styles.js +61 -0
  29. package/dist/components/Cards/OfferCard/index.d.ts +1 -0
  30. package/dist/components/Cards/OfferCard/index.js +17 -0
  31. package/dist/components/Cards/ProgressBarCard/ProgressBarCard.styles.d.ts +9 -5202
  32. package/dist/components/Cards/QuickLinkCard/QuickLinkCard.styles.d.ts +5 -2890
  33. package/dist/components/Cards/ServicesImageCard/ServicesImageCard.styles.d.ts +5 -2890
  34. package/dist/components/Cards/shared.styles.d.ts +10 -5780
  35. package/dist/components/Checkbox/styled.d.ts +6 -3468
  36. package/dist/components/CurrencyInput/styled.d.ts +4 -2312
  37. package/dist/components/DataTable/styles.d.ts +13 -7514
  38. package/dist/components/Disclosure/Disclosure.d.ts +1 -578
  39. package/dist/components/Em/Em.d.ts +1 -578
  40. package/dist/components/EmptyState/styles.d.ts +2 -1156
  41. package/dist/components/ErrorText/ErrorText.d.ts +1 -578
  42. package/dist/components/Grid/Col.d.ts +1 -578
  43. package/dist/components/HintText/HintText.d.ts +1 -578
  44. package/dist/components/Input/styled.d.ts +3 -1734
  45. package/dist/components/LabelText/LabelText.d.ts +1 -578
  46. package/dist/components/LargeValueReference/styles.d.ts +3 -1734
  47. package/dist/components/LineThrough/LineThrough.d.ts +1 -578
  48. package/dist/components/List/styled.d.ts +4 -2312
  49. package/dist/components/Margin/Margin.d.ts +1 -578
  50. package/dist/components/NavHeader/NavHeader.styles.d.ts +11 -6358
  51. package/dist/components/Notification/Notification.d.ts +2 -2
  52. package/dist/components/Notification/Notification.js +20 -12
  53. package/dist/components/Notification/Notification.styles.d.ts +13 -5202
  54. package/dist/components/Notification/Notification.styles.js +21 -2
  55. package/dist/components/PasswordInput/PasswordInput.styled.d.ts +1 -578
  56. package/dist/components/Radio/Radio.d.ts +2 -2
  57. package/dist/components/Radio/Radio.js +5 -43
  58. package/dist/components/Radio/Radio.styles.d.ts +9 -0
  59. package/dist/components/Radio/Radio.styles.js +74 -0
  60. package/dist/components/RadioCard/RadioCard.styles.d.ts +5 -2890
  61. package/dist/components/Rail/Rail.d.ts +12 -0
  62. package/dist/components/Rail/Rail.js +58 -0
  63. package/dist/components/Rail/RailIndicator.d.ts +7 -0
  64. package/dist/components/Rail/RailIndicator.js +81 -0
  65. package/dist/components/Rail/index.d.ts +1 -0
  66. package/dist/components/Rail/index.js +5 -0
  67. package/dist/components/Rail/styles.d.ts +13 -0
  68. package/dist/components/Rail/styles.js +55 -0
  69. package/dist/components/Rail/useRailPaging.d.ts +13 -0
  70. package/dist/components/Rail/useRailPaging.js +95 -0
  71. package/dist/components/SelectField/styled.d.ts +8 -4624
  72. package/dist/components/Strong/Strong.d.ts +1 -578
  73. package/dist/components/SubLabelText/SubLabelText.d.ts +1 -578
  74. package/dist/components/Tabs/Tab.d.ts +1 -578
  75. package/dist/components/Toast/Toast.d.ts +10 -4
  76. package/dist/components/Toast/Toast.js +40 -27
  77. package/dist/components/Toggle/styles.d.ts +4 -2312
  78. package/dist/components/index.d.ts +2 -0
  79. package/dist/components/index.js +2 -0
  80. package/dist/esm/components/ActionList/ActionListItems/DataListItem.js +3 -1
  81. package/dist/esm/components/ActionList/ActionListItems/ToggleListItem.js +5 -6
  82. package/dist/esm/components/ActionList/ActionListItems/styles.js +17 -15
  83. package/dist/esm/components/BottomActionBar/BottomActionBar.js +40 -0
  84. package/dist/esm/components/BottomActionBar/OverlayProvider.js +30 -0
  85. package/dist/esm/components/BottomActionBar/index.js +2 -0
  86. package/dist/esm/components/Cards/IllustrationTextCard/IllustrationTextCard.styles.js +1 -2
  87. package/dist/esm/components/Cards/OfferCard/OfferCard.js +32 -0
  88. package/dist/esm/components/Cards/OfferCard/OfferCard.styles.js +55 -0
  89. package/dist/esm/components/Cards/OfferCard/index.js +1 -0
  90. package/dist/esm/components/Notification/Notification.js +21 -13
  91. package/dist/esm/components/Notification/Notification.styles.js +20 -1
  92. package/dist/esm/components/Radio/Radio.js +4 -39
  93. package/dist/esm/components/Radio/Radio.styles.js +38 -0
  94. package/dist/esm/components/Rail/Rail.js +21 -0
  95. package/dist/esm/components/Rail/RailIndicator.js +44 -0
  96. package/dist/esm/components/Rail/index.js +1 -0
  97. package/dist/esm/components/Rail/styles.js +49 -0
  98. package/dist/esm/components/Rail/useRailPaging.js +92 -0
  99. package/dist/esm/components/Toast/Toast.js +40 -27
  100. package/dist/esm/components/index.js +2 -0
  101. package/dist/styled.native.d.ts +1 -3463
  102. package/package.json +2 -2
@@ -2,6 +2,7 @@ export * from './Accordion';
2
2
  export * from './ActionCard';
3
3
  export * from './ActionList';
4
4
  export * from './Badge';
5
+ export * from './BottomActionBar';
5
6
  export * from './Button';
6
7
  export * from './Card';
7
8
  export * from './Cards';
@@ -40,6 +41,7 @@ export * from './PhoneInput';
40
41
  export * from './Pictogram';
41
42
  export * from './Radio';
42
43
  export * from './RadioCard';
44
+ export * from './Rail';
43
45
  export * from './RemoteImage';
44
46
  export * from './ScreenView';
45
47
  export * from './SegmentedControls';
@@ -18,6 +18,7 @@ __exportStar(require("./Accordion"), exports);
18
18
  __exportStar(require("./ActionCard"), exports);
19
19
  __exportStar(require("./ActionList"), exports);
20
20
  __exportStar(require("./Badge"), exports);
21
+ __exportStar(require("./BottomActionBar"), exports);
21
22
  __exportStar(require("./Button"), exports);
22
23
  __exportStar(require("./Card"), exports);
23
24
  __exportStar(require("./Cards"), exports);
@@ -56,6 +57,7 @@ __exportStar(require("./PhoneInput"), exports);
56
57
  __exportStar(require("./Pictogram"), exports);
57
58
  __exportStar(require("./Radio"), exports);
58
59
  __exportStar(require("./RadioCard"), exports);
60
+ __exportStar(require("./Rail"), exports);
59
61
  __exportStar(require("./RemoteImage"), exports);
60
62
  __exportStar(require("./ScreenView"), exports);
61
63
  __exportStar(require("./SegmentedControls"), exports);
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useFontScaling } from '../../../hooks/use-font-scaling';
2
3
  import { useTheme } from '../../../styled.native';
3
4
  import { Icon } from '../../Icon';
4
5
  import { LabelText } from '../../LabelText';
@@ -9,9 +10,10 @@ export const DataListItem = ({ testID, graphic, progressRingPercentage, heading,
9
10
  const theme = useTheme();
10
11
  const isError = statusText === 'Error';
11
12
  const hasProgressRing = progressRingPercentage !== undefined;
13
+ const { isFontScalingLarge } = useFontScaling();
12
14
  const IconContent = (graphic === null || graphic === void 0 ? void 0 : graphic.type) === 'icon' ? (_jsx(GraphicContainer, { isIcon: true, hasProgress: hasProgressRing, children: _jsx(Icon, { name: graphic.icon, size: 24, color: graphic.iconColor ? graphic.iconColor : theme.color.brand.brand }) })) : null;
13
15
  return (_jsxs(ActionListItemWrapper, { testID: testID, children: [(graphic === null || graphic === void 0 ? void 0 : graphic.type) === 'icon' &&
14
16
  (hasProgressRing ? (_jsx(ProgressRing, { percentage: progressRingPercentage, children: IconContent })) : (IconContent)), (graphic === null || graphic === void 0 ? void 0 : graphic.type) === 'image' && (_jsx(GraphicContainer, { children: _jsx(StyledImage, { source: typeof graphic.image === 'string'
15
17
  ? { uri: graphic.image }
16
- : graphic.image, resizeMode: "cover", accessibilityLabel: 'Data List Image' }) })), _jsxs(LeftTextContainer, { children: [heading && _jsx(LabelText, { children: heading }), subHeading && _jsx(P, { size: "sm", children: subHeading }), statusText && (_jsx(StatusText, { size: "sm", isError: isError, children: statusText }))] }), _jsxs(RightTextContainer, { children: [_jsxs(DirectionAndValueTextContainer, { children: [directionLabel && (_jsx(DirectionLabelContainer, { children: _jsx(OnSurfaceP, { size: "sm", children: directionLabel }) })), valueText && (_jsx(ValueTextContainer, { children: _jsx(DataValueText, { isError: isError, size: "lg", children: valueText }) }))] }), valueSubText && _jsx(OnSurfaceP, { size: "sm", children: valueSubText })] })] }));
18
+ : graphic.image, resizeMode: "cover", accessibilityLabel: 'Data List Image' }) })), _jsxs(LeftTextContainer, { children: [heading && _jsx(LabelText, { children: heading }), subHeading && _jsx(P, { size: "sm", children: subHeading }), statusText && (_jsx(StatusText, { size: "sm", isError: isError, children: statusText }))] }), _jsxs(RightTextContainer, { children: [_jsxs(DirectionAndValueTextContainer, { children: [directionLabel && (_jsx(DirectionLabelContainer, { scaledUpFont: isFontScalingLarge, children: _jsx(OnSurfaceP, { size: "sm", children: directionLabel }) })), valueText && (_jsx(ValueTextContainer, { scaledUpFont: isFontScalingLarge, children: _jsx(DataValueText, { isError: isError, size: "lg", children: valueText }) }))] }), valueSubText && _jsx(OnSurfaceP, { size: "sm", children: valueSubText })] })] }));
17
19
  };
@@ -1,9 +1,8 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useTheme } from '../../../styled.native';
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Switch } from 'react-native';
3
+ import { HintText } from '../../HintText';
3
4
  import { P } from '../../P';
4
- import { Toggle } from '../../Toggle';
5
- import { ActionListItemWrapper } from './styles';
5
+ import { ActionListItemWrapper, TextContainer } from './styles';
6
6
  export const ToggleListItem = ({ testID, heading, hintText, checked, onToggle, }) => {
7
- const theme = useTheme();
8
- return (_jsx(ActionListItemWrapper, { testID: testID ? `${testID}-toggle` : undefined, children: _jsx(Toggle, { checked: checked, onPress: onToggle, accessibilityLabel: typeof heading === 'string' ? heading : undefined, label: _jsx(P, { children: heading }), hint: hintText, toggleBackgroundColor: theme.color.brand.brand }) }));
7
+ return (_jsxs(ActionListItemWrapper, { testID: testID ? `${testID}-toggle` : undefined, children: [_jsxs(TextContainer, { children: [_jsx(P, { children: heading }), hintText && _jsx(HintText, { children: hintText })] }), _jsx(Switch, { value: checked, onValueChange: onToggle, accessibilityRole: "switch", accessibilityLabel: heading, accessibilityState: { checked } })] }));
9
8
  };
@@ -11,6 +11,11 @@ export const ActionListItemWrapper = styled(View)(({ theme }) => {
11
11
  padding: ${numToPx(theme.space[400])} 0;
12
12
  `;
13
13
  });
14
+ export const TextContainer = styled(View)(() => {
15
+ return css `
16
+ flex: 1;
17
+ `;
18
+ });
14
19
  // Editable List Item
15
20
  export const EditableListContainer = styled(View)(({ theme }) => {
16
21
  return css `
@@ -46,11 +51,6 @@ export const NavigationListContainer = styled(View)(({ theme }) => {
46
51
  gap: ${numToPx(theme.space[100])};
47
52
  `;
48
53
  });
49
- export const TextContainer = styled(View)(() => {
50
- return css `
51
- flex: 1;
52
- `;
53
- });
54
54
  export const SubHeading = styled(P)(({ theme }) => {
55
55
  return css `
56
56
  color: ${theme.color.alert.info};
@@ -60,12 +60,14 @@ export const SubHeading = styled(P)(({ theme }) => {
60
60
  export const LeftTextContainer = styled(View)(({ theme }) => {
61
61
  return css `
62
62
  flex: 1;
63
+ min-width: 0;
64
+ flex-shrink: 1;
63
65
  gap: ${numToPx(theme.space[100])};
64
66
  `;
65
67
  });
66
68
  export const RightTextContainer = styled(View)(({ theme }) => {
67
69
  return css `
68
- flex: 1;
70
+ flex-shrink: 1;
69
71
  gap: ${numToPx(theme.space[100])};
70
72
  align-items: flex-end;
71
73
  `;
@@ -81,9 +83,9 @@ export const StatusText = styled(P)(({ theme, isError, }) => {
81
83
  color: ${isError ? theme.color.alert.error : theme.color.alert.info};
82
84
  `;
83
85
  });
84
- export const ValueTextContainer = styled(View)(({ theme }) => {
86
+ export const ValueTextContainer = styled(View)(({ theme, scaledUpFont, }) => {
85
87
  return css `
86
- min-width: ${numToPx(theme.space[2400])};
88
+ min-width: ${scaledUpFont ? 138 : numToPx(theme.space[2400])};
87
89
  align-items: flex-end;
88
90
  `;
89
91
  });
@@ -92,24 +94,24 @@ export const DataValueText = styled(P)(({ theme, isError, }) => {
92
94
  color: ${isError ? theme.color.alert.error : theme.color.surface.onSurface};
93
95
  `;
94
96
  });
95
- export const DirectionLabelContainer = styled(View)(({ theme }) => {
97
+ export const DirectionLabelContainer = styled(View)(({ theme, scaledUpFont }) => {
96
98
  return css `
97
- min-width: ${numToPx(theme.space[600])};
98
- align-items: flex-end;
99
- `;
99
+ min-width: ${scaledUpFont
100
+ ? numToPx(theme.space[900])
101
+ : numToPx(theme.space[600])};
102
+ align-items: flex-end;
103
+ `;
100
104
  });
101
105
  export const OnSurfaceP = styled(P)(({ theme }) => {
102
106
  return css `
103
107
  color: ${theme.color.surface.onSurfaceVariant};
104
108
  `;
105
109
  });
106
- export const DirectionAndValueTextContainer = styled(View)(({ theme }) => {
110
+ export const DirectionAndValueTextContainer = styled(View)(() => {
107
111
  return css `
108
112
  align-items: flex-end;
109
113
  justify-content: space-between;
110
- width: 100%;
111
114
  flex-direction: row;
112
- margin-left: ${numToPx(theme.space[300])};
113
115
  `;
114
116
  });
115
117
  export const PROGESS_RING_INNER = 42;
@@ -0,0 +1,40 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { useSafeAreaInsets } from 'react-native-safe-area-context';
4
+ import styled, { useTheme } from '../../styled.native';
5
+ import { Button } from '../Button';
6
+ import { Stack } from '../Stack';
7
+ import { useOverlayContext } from './OverlayProvider';
8
+ const BottomActionContainer = styled.View(({ theme, background }) => ({
9
+ width: '100%',
10
+ bottom: 0,
11
+ position: 'absolute',
12
+ borderTopWidth: theme.border.width.sm,
13
+ borderTopColor: theme.color.surface.border,
14
+ backgroundColor: background === 'surface'
15
+ ? theme.color.surface.surface
16
+ : background === 'bright'
17
+ ? theme.color.surface.bright
18
+ : 'transparent',
19
+ paddingTop: theme.space[300],
20
+ paddingHorizontal: theme.space[400],
21
+ }));
22
+ export const BottomActionBar = ({ surfaceAction, outlineAction, background = 'surface', }) => {
23
+ const theme = useTheme();
24
+ const overlay = useOverlayContext();
25
+ const insets = useSafeAreaInsets();
26
+ const paddingBottom = insets.bottom + theme.space[100];
27
+ React.useEffect(() => {
28
+ overlay.mount('BottomAction', _jsx(BottomActionContainer, { background: background, pointerEvents: "auto", style: { paddingBottom: paddingBottom }, children: _jsxs(Stack, { spaceBetween: 3, children: [surfaceAction && (_jsx(Button, { fullWidth: true, variant: "surface", onPress: surfaceAction.onPress, children: surfaceAction.label })), outlineAction && (_jsx(Button, { fullWidth: true, variant: "outline", onPress: outlineAction.onPress, children: outlineAction.label }))] }) }));
29
+ return () => overlay.unmount('BottomAction');
30
+ }, [
31
+ overlay,
32
+ background,
33
+ paddingBottom,
34
+ surfaceAction === null || surfaceAction === void 0 ? void 0 : surfaceAction.label,
35
+ surfaceAction === null || surfaceAction === void 0 ? void 0 : surfaceAction.onPress,
36
+ outlineAction === null || outlineAction === void 0 ? void 0 : outlineAction.label,
37
+ outlineAction === null || outlineAction === void 0 ? void 0 : outlineAction.onPress,
38
+ ]);
39
+ return null;
40
+ };
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { StyleSheet, View } from 'react-native';
4
+ import styled from '../../styled.native';
5
+ const OverlayContext = React.createContext(null);
6
+ const StyledView = styled.View({
7
+ flex: 1,
8
+ });
9
+ export const BottomActionBarOverlayProvider = ({ children }) => {
10
+ const [entries, setEntries] = React.useState([]);
11
+ const api = React.useMemo(() => ({
12
+ mount: (key, node) => {
13
+ setEntries(prev => {
14
+ const next = prev.filter(e => e.key !== key);
15
+ next.push({ key, node });
16
+ return next;
17
+ });
18
+ },
19
+ unmount: key => {
20
+ setEntries(prev => prev.filter(e => e.key !== key));
21
+ },
22
+ }), []);
23
+ return (_jsx(OverlayContext.Provider, { value: api, children: _jsxs(StyledView, { children: [children, _jsx(View, { style: StyleSheet.absoluteFill, pointerEvents: "box-none", children: entries.map(e => (_jsx(React.Fragment, { children: e.node }, e.key))) })] }) }));
24
+ };
25
+ export const useOverlayContext = () => {
26
+ const ctx = React.useContext(OverlayContext);
27
+ if (!ctx)
28
+ throw new Error('BottomActionOverlayProvider is missing above in the tree');
29
+ return ctx;
30
+ };
@@ -0,0 +1,2 @@
1
+ export { BottomActionBar } from './BottomActionBar';
2
+ export { BottomActionBarOverlayProvider } from './OverlayProvider';
@@ -5,6 +5,7 @@ export const CardWithIllustrationText = styled(CardWithMinHeight)(({ theme, isSm
5
5
  paddingTop: hasBadge ? theme.space[800] : theme.space[400],
6
6
  display: 'flex',
7
7
  flexDirection: isSmall ? 'column-reverse' : 'row',
8
+ justifyContent: 'space-between',
8
9
  }));
9
10
  export const TextContent = styled(View)(({ isSmall, theme }) => ({
10
11
  flex: isSmall ? undefined : 1,
@@ -17,8 +18,6 @@ export const HeadingContainer = styled(View)(({ theme, isSmall }) => ({
17
18
  export const ImageContent = styled(View)(({ theme, isSmall, hasBadge }) => ({
18
19
  width: isSmall ? theme.space[1600] : theme.space[3000],
19
20
  height: isSmall ? theme.space[1600] : theme.space[3000],
20
- justifyContent: 'center',
21
- alignItems: 'center',
22
21
  alignSelf: isSmall ? undefined : 'center',
23
22
  marginTop: hasBadge && !isSmall ? -theme.space[400] : 0,
24
23
  }));
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useState } from 'react';
3
+ import { useTheme } from '../../../styled.native';
4
+ import { Icon } from '../../Icon';
5
+ import { P } from '../../P';
6
+ import { ContainerWithCardBadge } from '../components';
7
+ import { checkIsSmall } from '../utils';
8
+ import { CardImage, CardWithOffer, EyebrowContainer, EyebrowText, HeadingText, IllustrationContainer, ImageContainer, SubHeadingContainer, TextContent, } from './OfferCard.styles';
9
+ const GraphicContent = ({ graphic }) => {
10
+ if (!graphic) {
11
+ return null;
12
+ }
13
+ const resizeMode = graphic.type === 'image' ? 'cover' : 'contain';
14
+ return (_jsx(CardImage, { source: typeof graphic.source === 'string'
15
+ ? { uri: graphic.source }
16
+ : graphic.source, resizeMode: resizeMode }));
17
+ };
18
+ export const OfferCard = ({ badgeText, graphic, eyebrowText, eyebrowIcon, heading, subHeading, size = 'default', onPress, }) => {
19
+ const theme = useTheme();
20
+ const hasBadge = !!badgeText;
21
+ const isSmall = checkIsSmall(size);
22
+ const [cardHeight, setCardHeight] = useState(0);
23
+ const onLayout = useCallback((e) => {
24
+ const { height: layoutHeight } = e.nativeEvent.layout;
25
+ setCardHeight(layoutHeight);
26
+ }, []);
27
+ const CardContent = (_jsxs(CardWithOffer, { isSmall: isSmall, onPress: onPress, onLayout: onLayout, children: [_jsxs(TextContent, { isSmall: isSmall, hasBadge: hasBadge, children: [(eyebrowIcon || eyebrowText) && (_jsxs(EyebrowContainer, { children: [eyebrowIcon && (_jsx(Icon, { name: eyebrowIcon, color: theme.color.brand.dim })), eyebrowText && _jsx(EyebrowText, { size: "sm", children: eyebrowText })] })), _jsx(HeadingText, { isSmall: isSmall, children: heading }), subHeading && (_jsx(SubHeadingContainer, { children: _jsx(P, { size: "sm", children: subHeading }) }))] }), (graphic === null || graphic === void 0 ? void 0 : graphic.type) === 'illustration' && (_jsx(IllustrationContainer, { hasBadge: hasBadge, isSmall: isSmall, children: _jsx(GraphicContent, { graphic: graphic }) })), (graphic === null || graphic === void 0 ? void 0 : graphic.type) === 'image' && (_jsx(ImageContainer, { isSmall: isSmall, cardHeight: cardHeight, children: _jsx(GraphicContent, { graphic: graphic }) }))] }));
28
+ if (!hasBadge) {
29
+ return CardContent;
30
+ }
31
+ return (_jsx(ContainerWithCardBadge, { badgeText: badgeText, children: CardContent }));
32
+ };
@@ -0,0 +1,55 @@
1
+ import { Image, View } from 'react-native';
2
+ import { Heading4, P } from '../..';
3
+ import styled from '../../../styled.native';
4
+ import { CardWithMinHeight, SMALL_CARD_HEIGHT } from '../shared.styles';
5
+ export const CardWithOffer = styled(CardWithMinHeight)(({ isSmall }) => ({
6
+ padding: 0,
7
+ display: 'flex',
8
+ flexDirection: isSmall ? 'column-reverse' : 'row',
9
+ borderWidth: 0,
10
+ justifyContent: 'space-between',
11
+ }));
12
+ export const TextContent = styled(View)(({ isSmall, hasBadge, theme }) => ({
13
+ flex: isSmall ? undefined : 1,
14
+ paddingHorizontal: theme.space[400],
15
+ paddingTop: !isSmall && hasBadge ? theme.space[800] : theme.space[400],
16
+ paddingBottom: theme.space[400],
17
+ alignSelf: isSmall ? undefined : 'flex-end',
18
+ }));
19
+ export const EyebrowContainer = styled(View)(({ theme }) => ({
20
+ flexDirection: 'row',
21
+ gap: theme.space[50],
22
+ marginBottom: theme.space[100],
23
+ }));
24
+ export const EyebrowText = styled(P)(({ theme }) => ({
25
+ color: theme.color.brand.dim,
26
+ }));
27
+ export const HeadingText = styled(Heading4)(({ isSmall, theme }) => ({
28
+ color: theme.color.surface.onSurface,
29
+ fontSize: isSmall ? theme.font.size.md.mediaQuery.sm : undefined,
30
+ lineHeight: isSmall ? theme.font.lineHeight.md.mediaQuery.sm : undefined,
31
+ }));
32
+ export const SubHeadingContainer = styled(View)(({ theme }) => ({
33
+ marginTop: theme.space[100],
34
+ }));
35
+ export const IllustrationContainer = styled(View)(({ theme, isSmall, hasBadge }) => ({
36
+ width: isSmall ? theme.space[1600] : theme.space[3000],
37
+ height: isSmall ? theme.space[1600] : theme.space[3000],
38
+ alignSelf: isSmall ? undefined : 'center',
39
+ marginBottom: isSmall ? 0 : theme.space[400],
40
+ marginTop: hasBadge ? theme.space[800] : theme.space[400],
41
+ marginLeft: isSmall ? theme.space[400] : 0,
42
+ }));
43
+ export const ImageContainer = styled(View)(({ theme, isSmall, cardHeight = 0 }) => ({
44
+ height: isSmall
45
+ ? theme.space[2400]
46
+ : cardHeight > 0
47
+ ? cardHeight
48
+ : SMALL_CARD_HEIGHT,
49
+ width: !isSmall ? theme.space[3500] : undefined,
50
+ flexShrink: 0,
51
+ }));
52
+ export const CardImage = styled(Image)({
53
+ width: '100%',
54
+ height: '100%',
55
+ });
@@ -0,0 +1 @@
1
+ export * from './OfferCard';
@@ -16,30 +16,38 @@ import { useTheme } from '../../styled.native';
16
16
  import { Icon } from '../Icon';
17
17
  import { P } from '../P';
18
18
  import { Strong } from '../Strong';
19
- import { ContentContainer, DismissButton, NotificationBox, NotificationContentBox, NotificationShadow, StyledIcon, TitleContainer, VariantIconBackground, VariantIconContainer, } from './Notification.styles';
19
+ import { ContentContainer, DismissButton, NotificationBox, NotificationContentBox, NotificationShadow, StyledIcon, TappableNotification, TitleContainer, VariantIconBackground, VariantIconContainer, } from './Notification.styles';
20
20
  import { mapVariantToIconName } from './utils';
21
21
  export const Notification = (_a) => {
22
- var { variant = 'info', children, title, subtitle, noMargin, isTappable = false, dismissible, onDismiss, ref } = _a, rest = __rest(_a, ["variant", "children", "title", "subtitle", "noMargin", "isTappable", "dismissible", "onDismiss", "ref"]);
22
+ var { variant = 'info', children, title, subtitle, noMargin, onPress, dismissible = true, onDismiss, ref } = _a, rest = __rest(_a, ["variant", "children", "title", "subtitle", "noMargin", "onPress", "dismissible", "onDismiss", "ref"]);
23
23
  const [dismissed, setDismissed] = useState(false);
24
24
  if (dismissed) {
25
25
  return null;
26
26
  }
27
- if (isTappable || dismissible) {
28
- return (_jsx(NotificationShadow, { children: _jsx(NotificationContent, Object.assign({ variant: variant, title: title, subtitle: subtitle, noMargin: noMargin, isTappable: isTappable, dismissible: dismissible, onDismiss: onDismiss, setDismissed: setDismissed, ref: ref }, rest, { children: children })) }));
27
+ const isClickable = !!onPress;
28
+ if (isClickable || dismissible) {
29
+ return (_jsx(NotificationShadow, { children: _jsx(NotificationContent, Object.assign({ variant: variant, title: title, subtitle: subtitle, noMargin: noMargin, onPress: isClickable ? onPress : undefined, dismissible: dismissible, onDismiss: onDismiss, setDismissed: setDismissed, ref: ref }, rest, { children: children })) }));
29
30
  }
30
- return (_jsx(NotificationContent, Object.assign({ variant: variant, title: title, subtitle: subtitle, noMargin: noMargin, isTappable: isTappable, dismissible: dismissible, onDismiss: onDismiss, setDismissed: setDismissed, ref: ref }, rest, { children: children })));
31
+ return (_jsx(NotificationContent, Object.assign({ variant: variant, title: title, subtitle: subtitle, noMargin: noMargin, onPress: onPress, dismissible: dismissible, onDismiss: onDismiss, setDismissed: setDismissed, ref: ref }, rest, { children: children })));
31
32
  };
32
33
  const NotificationContent = (_a) => {
33
- var { variant = 'info', children, title, subtitle, noMargin, dismissible, onDismiss, setDismissed, ref } = _a, rest = __rest(_a, ["variant", "children", "title", "subtitle", "noMargin", "dismissible", "onDismiss", "setDismissed", "ref"]);
34
+ var { variant = 'info', children, title, subtitle, noMargin, dismissible, onDismiss, setDismissed, onPress, ref } = _a, rest = __rest(_a, ["variant", "children", "title", "subtitle", "noMargin", "dismissible", "onDismiss", "setDismissed", "onPress", "ref"]);
34
35
  const theme = useTheme();
35
- return (_jsx(View, Object.assign({ ref: ref }, rest, { children: _jsxs(NotificationBox, { noMargin: noMargin, testID: "nb-notification", children: [_jsx(VariantIconBackground, { variant: variant, children: _jsx(VariantIconContainer, { children: _jsx(StyledIcon, { variant: variant, size: theme.unit[800], name: mapVariantToIconName(variant) }) }) }), _jsxs(ContentContainer, { children: [_jsxs(TitleContainer, { children: [title && (_jsx(P, { size: "md", children: _jsx(Strong, { children: title }) })), subtitle && _jsx(P, { size: "sm", children: subtitle }), children && (_jsx(NotificationContentBox, { testID: "el-notification-box", children: children }))] }), dismissible ? (_jsx(DismissButton, { accessible: true, accessibilityLabel: "Dismiss", testID: "nb-notification-dismiss", onPress: () => {
36
- setDismissed(true);
37
- if (onDismiss) {
38
- onDismiss();
39
- }
40
- }, children: _jsx(Icon, { color: theme.button.surface.color.fgInverted, name: "cross", size: theme.space[400] }) })) : null] })] }) })));
36
+ const hasChildren = !!children;
37
+ const handleDismiss = () => {
38
+ if (onDismiss) {
39
+ onDismiss();
40
+ }
41
+ setDismissed(true);
42
+ };
43
+ return (_jsxs(View, Object.assign({ ref: ref }, rest, { children: [!!onPress && (_jsx(TappableNotification, { dismissible: dismissible, hasChildren: hasChildren, onPress: onPress })), _jsxs(NotificationBox, { noMargin: noMargin, testID: "nb-notification", children: [_jsx(VariantIconBackground, { variant: variant, children: _jsx(VariantIconContainer, { children: _jsx(StyledIcon, { variant: variant, size: theme.unit[800], name: mapVariantToIconName(variant) }) }) }), _jsxs(ContentContainer, { children: [_jsxs(TitleContainer, { children: [title && (_jsx(P, { size: "md", children: _jsx(Strong, { children: title }) })), subtitle && _jsx(P, { size: "sm", children: subtitle }), children && (_jsx(NotificationContentBox, { testID: "el-notification-box", children: children }))] }), dismissible ? (_jsx(DismissButton, { accessible: true, accessibilityLabel: "Dismiss", testID: "nb-notification-dismiss", hitSlop: {
44
+ top: theme.space[300],
45
+ right: theme.space[400],
46
+ bottom: theme.space[100],
47
+ left: theme.space[100],
48
+ }, onPress: handleDismiss, children: _jsx(Icon, { color: theme.button.surface.color.fgInverted, name: "cross", size: theme.space[400] }) })) : null] })] })] })));
41
49
  };
42
50
  export const SuccessNotification = (props) => (_jsx(Notification, Object.assign({ variant: "success" }, props)));
43
51
  export const InfoNotification = (props) => (_jsx(Notification, Object.assign({ variant: "info" }, props)));
44
52
  export const WarningNotification = (props) => (_jsx(Notification, Object.assign({ variant: "warning" }, props)));
45
- export const ErrorNotification = (props) => (_jsx(Notification, Object.assign({ variant: "error" }, props)));
53
+ export const ErrorNotification = (props) => (_jsx(Notification, Object.assign({ variant: "error", dismissible: false }, props)));
@@ -7,7 +7,7 @@ export const NotificationShadow = styled(View)(({ theme }) => {
7
7
  return css `
8
8
  shadow-color: ${theme.color.brand.dark};
9
9
  shadow-offset: 0 ${numToPx(theme.space[100])};
10
- shadow-opacity: ${theme.opacity.transparent};
10
+ shadow-opacity: 0.1;
11
11
  shadow-radius: ${numToPx(theme.space[100])};
12
12
  elevation: 6;
13
13
  `;
@@ -27,6 +27,25 @@ export const NotificationContentBox = styled.View(({ theme }) => {
27
27
  padding-right: ${numToPx(theme.space[300])};
28
28
  `;
29
29
  });
30
+ export const TappableNotification = styled.TouchableOpacity(({ dismissible, hasChildren, theme }) => {
31
+ return css `
32
+ position: absolute;
33
+ left: 0;
34
+ height: ${hasChildren ? numToPx(theme.space[1200]) : '80%'};
35
+ width: ${dismissible ? '86%' : '100%'};
36
+ z-index: 1;
37
+ border-top-left-radius: ${numToPx(theme.border.radius.md)};
38
+ border-top-right-radius: ${dismissible
39
+ ? 0
40
+ : numToPx(theme.border.radius.md)};
41
+ border-bottom-right-radius: ${dismissible
42
+ ? numToPx(theme.border.radius.md)
43
+ : 0};
44
+ border-bottom-left-radius: ${hasChildren
45
+ ? 0
46
+ : numToPx(theme.border.radius.md)};
47
+ `;
48
+ });
30
49
  export const DismissButton = styled.TouchableOpacity(({ theme }) => {
31
50
  return css `
32
51
  display: flex;
@@ -10,56 +10,21 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
- import { numToPx } from '@ovotech/element-core';
14
13
  import { TouchableOpacity, View, } from 'react-native';
15
- import styled from '../../styled.native';
14
+ import { useTheme } from '../../styled.native';
16
15
  import { HintText } from '../HintText';
17
16
  import { LabelText } from '../LabelText';
18
- const StyledRadioInputWrapper = styled.View(({ theme }) => {
19
- return `
20
- width: ${numToPx(theme.space[600])};
21
- height: ${numToPx(theme.space[600])};
22
- margin-right: 10px;
23
- `;
24
- });
25
- const StyledRadioInput = styled.View(({ theme, invalid, checked }) => {
26
- return `
27
- width: ${numToPx(theme.space[600])};
28
- height: ${numToPx(theme.space[600])};
29
- border: ${numToPx(theme.border.width.md)} solid;
30
- align-items: center;
31
- justify-content: center;
32
- border-radius: ${numToPx(theme.space[600])};
33
- border-color: ${invalid
34
- ? theme.input.color.borderError
35
- : checked
36
- ? theme.input.color.selected
37
- : theme.input.color.border};
38
- background: ${checked ? theme.input.color.selectedTint : 'transparent'};
39
- `;
40
- });
41
- const StyledRadioInputDot = styled.View(({ theme, checked }) => {
42
- return `
43
- width: ${numToPx(theme.space[300])};
44
- height: ${numToPx(theme.space[300])};
45
- border-radius: ${numToPx(theme.space[300])};
46
- background: ${theme.input.color.selected};
47
- opacity: ${checked ? 1 : 0};
48
- `;
49
- });
17
+ import { StyledRadioInput, StyledRadioInputDot, StyledRadioInputWrapper, StyledWrapper, } from './Radio.styles';
50
18
  const Input = (_a) => {
51
19
  var { checked, invalid, testID } = _a, rest = __rest(_a, ["checked", "invalid", "testID"]);
52
20
  return (_jsx(StyledRadioInputWrapper, Object.assign({}, rest, { children: _jsx(StyledRadioInput, { invalid: invalid, checked: checked, testID: testID, children: _jsx(StyledRadioInputDot, { checked: checked }) }) })));
53
21
  };
54
- const StyledWrapper = styled.View(({ theme }) => `
55
- padding-top: ${numToPx(theme.space[300])};
56
- flex-direction: row;
57
- `);
58
22
  const Radio = (_a) => {
59
23
  var { label, hint, checked, invalid,
60
24
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
61
25
  value, // "value" is needed for RadioGroup, but isn't actually used in the radio anywhere
62
26
  activeOpacity = 0.8, testID, ref } = _a, rest = __rest(_a, ["label", "hint", "checked", "invalid", "value", "activeOpacity", "testID", "ref"]);
63
- return (_jsx(TouchableOpacity, Object.assign({ ref: ref, accessible: true, accessibilityRole: "radio", activeOpacity: activeOpacity, accessibilityState: { checked } }, rest, { children: _jsxs(StyledWrapper, { children: [_jsx(Input, { checked: checked, invalid: invalid, testID: testID }), _jsxs(View, { style: { flexShrink: 1 }, children: [_jsx(LabelText, { children: label }), hint ? _jsx(HintText, { children: hint }) : null] })] }) })));
27
+ const theme = useTheme();
28
+ return (_jsx(TouchableOpacity, Object.assign({ ref: ref, accessible: true, accessibilityRole: "radio", activeOpacity: activeOpacity, accessibilityState: { checked } }, rest, { children: _jsxs(StyledWrapper, { children: [_jsx(Input, { checked: checked, invalid: invalid, testID: testID }), _jsxs(View, { style: { flexShrink: 1 }, children: [_jsx(LabelText, { style: { fontFamily: theme.native.font.family.book }, children: label }), hint ? _jsx(HintText, { children: hint }) : null] })] }) })));
64
29
  };
65
30
  export { Radio };
@@ -0,0 +1,38 @@
1
+ import { numToPx } from '@ovotech/element-core';
2
+ import styled, { css } from '../../styled.native';
3
+ export const StyledWrapper = styled.View(({ theme }) => css `
4
+ padding-top: ${numToPx(theme.space[300])};
5
+ flex-direction: row;
6
+ `);
7
+ export const StyledRadioInputDot = styled.View(({ theme, checked }) => {
8
+ return css `
9
+ width: ${numToPx(theme.space[300])};
10
+ height: ${numToPx(theme.space[300])};
11
+ border-radius: ${numToPx(theme.space[300])};
12
+ background: ${theme.input.color.selected};
13
+ opacity: ${checked ? 1 : 0};
14
+ `;
15
+ });
16
+ export const StyledRadioInput = styled.View(({ theme, invalid, checked }) => {
17
+ return css `
18
+ width: ${numToPx(theme.space[600])};
19
+ height: ${numToPx(theme.space[600])};
20
+ border: ${numToPx(theme.border.width.md)} solid;
21
+ align-items: center;
22
+ justify-content: center;
23
+ border-radius: ${numToPx(theme.space[600])};
24
+ border-color: ${invalid
25
+ ? theme.input.color.borderError
26
+ : checked
27
+ ? theme.input.color.selected
28
+ : theme.input.color.border};
29
+ background: ${checked ? theme.input.color.selectedTint : 'transparent'};
30
+ `;
31
+ });
32
+ export const StyledRadioInputWrapper = styled.View(({ theme }) => {
33
+ return css `
34
+ width: ${numToPx(theme.space[600])};
35
+ height: ${numToPx(theme.space[600])};
36
+ margin-right: 10px;
37
+ `;
38
+ });
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { useMemo } from 'react';
3
+ import { View, } from 'react-native';
4
+ import { Icon } from '../Icon';
5
+ import { P } from '../P';
6
+ import { Strong } from '../Strong';
7
+ import { RailIndicator } from './RailIndicator';
8
+ import { Header, HeadingText, IconContainer, RailItemWrapper, StyledRail, } from './styles';
9
+ import { useRailPaging } from './useRailPaging';
10
+ const DEFAULT_MAX_CHILDREN = 6;
11
+ export const Rail = ({ children, indicator = true, icon, heading, subHeading, maxChildren = DEFAULT_MAX_CHILDREN, }) => {
12
+ const allItems = useMemo(() => React.Children.toArray(children), [children]);
13
+ const items = useMemo(() => allItems.slice(0, Math.max(0, maxChildren)), [allItems, maxChildren]);
14
+ const paging = useRailPaging({ itemCount: items.length });
15
+ const hasIndicator = indicator && paging.isScrollable;
16
+ return (_jsxs(View, { children: [_jsxs(Header, { children: [icon && (_jsx(IconContainer, { children: _jsx(Icon, { name: icon, size: 24 }) })), (heading || subHeading) && (_jsxs(HeadingText, { children: [heading && (_jsx(P, { size: "lg", children: _jsx(Strong, { children: heading }) })), subHeading && _jsx(P, { size: "sm", children: subHeading })] }))] }), _jsxs(View, { onLayout: e => paging.onContainerLayout(e.nativeEvent.layout.width), children: [_jsx(StyledRail, { horizontal: true, hasIndicator: hasIndicator, showsHorizontalScrollIndicator: false, contentContainerStyle: { flexDirection: 'row' }, decelerationRate: "fast", snapToOffsets: paging.snapOffsets, snapToAlignment: "start", disableIntervalMomentum: true, scrollEventThrottle: 16, onMomentumScrollEnd: (e) => paging.onMomentumEnd(e.nativeEvent.contentOffset.x), onContentSizeChange: w => paging.onContentSizeChange(w), children: items.map((child, index) => (_jsx(RailItemWrapper, { onLayout: (e) => {
17
+ if (index !== 0)
18
+ return;
19
+ paging.onItemLayout(e.nativeEvent.layout.width);
20
+ }, children: child }, `Rail-item-${index}`))) }), hasIndicator && (_jsx(RailIndicator, { dotCount: items.length, activeStartIndex: paging.activeStartIndex, visibleCount: paging.visibleCount }))] })] }));
21
+ };
@@ -0,0 +1,44 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useMemo, useState } from 'react';
3
+ import Animated, { useAnimatedStyle, useDerivedValue, withTiming, } from 'react-native-reanimated';
4
+ import { useTheme } from '../../styled.native';
5
+ import { DotContainer, RailIndicatorContainer } from './styles';
6
+ export const RailIndicator = ({ dotCount, activeStartIndex, visibleCount, }) => {
7
+ const theme = useTheme();
8
+ const DOT = theme.space[200];
9
+ const GAP = theme.space[200];
10
+ const PADDING = theme.space[350];
11
+ const [containerWidth, setContainerWidth] = useState(0);
12
+ const onContainerLayout = useCallback((e) => {
13
+ var _a, _b, _c;
14
+ const w = (_c = (_b = (_a = e === null || e === void 0 ? void 0 : e.nativeEvent) === null || _a === void 0 ? void 0 : _a.layout) === null || _b === void 0 ? void 0 : _b.width) !== null && _c !== void 0 ? _c : 0;
15
+ if (w > 0)
16
+ setContainerWidth(w);
17
+ }, []);
18
+ if (dotCount <= 0)
19
+ return null;
20
+ const start = Math.min(Math.max(0, activeStartIndex), dotCount - 1);
21
+ const visible = Math.max(1, Math.min(visibleCount, dotCount - start));
22
+ const rowWidth = useMemo(() => {
23
+ return dotCount * DOT + (dotCount - 1) * GAP;
24
+ }, [dotCount, DOT, GAP]);
25
+ const step = DOT + GAP;
26
+ const animatedLeft = useDerivedValue(() => {
27
+ if (containerWidth <= 0)
28
+ return 0;
29
+ const innerWidth = Math.max(0, containerWidth - 2 * PADDING);
30
+ const rowLeft = PADDING + Math.max(0, (innerWidth - rowWidth) / 2);
31
+ return withTiming(rowLeft + start * step, { duration: 150 });
32
+ }, [containerWidth, PADDING, rowWidth, start, step]);
33
+ const animatedWidth = useDerivedValue(() => {
34
+ const w = visible * DOT + Math.max(0, visible - 1) * GAP;
35
+ return withTiming(w, { duration: 150 });
36
+ }, [visible, DOT, GAP]);
37
+ const pillStyle = useAnimatedStyle(() => ({
38
+ position: 'absolute',
39
+ left: animatedLeft.value,
40
+ width: animatedWidth.value,
41
+ opacity: containerWidth > 0 ? 1 : 0,
42
+ }));
43
+ return (_jsxs(RailIndicatorContainer, { onLayout: onContainerLayout, children: [Array.from({ length: dotCount }).map((_, index) => (_jsx(DotContainer, { isActive: false }, `dot-${index}`))), _jsx(Animated.View, { pointerEvents: "none", style: pillStyle, children: _jsx(DotContainer, { isActive: true, style: { width: '100%' } }) })] }));
44
+ };
@@ -0,0 +1 @@
1
+ export { Rail } from './Rail';