@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.
- package/dist/components/Accordion/styles.d.ts +3 -1734
- package/dist/components/ActionList/ActionListItems/DataListItem.js +3 -1
- package/dist/components/ActionList/ActionListItems/ToggleListItem.js +3 -4
- package/dist/components/ActionList/ActionListItems/styles.d.ts +22 -10404
- package/dist/components/ActionList/ActionListItems/styles.js +18 -16
- package/dist/components/ActionList/styled.d.ts +12 -6936
- package/dist/components/Badge/Badge.d.ts +1 -578
- package/dist/components/BottomActionBar/BottomActionBar.d.ts +12 -0
- package/dist/components/BottomActionBar/BottomActionBar.js +80 -0
- package/dist/components/BottomActionBar/OverlayProvider.d.ts +8 -0
- package/dist/components/BottomActionBar/OverlayProvider.js +38 -0
- package/dist/components/BottomActionBar/index.d.ts +2 -0
- package/dist/components/BottomActionBar/index.js +7 -0
- package/dist/components/Button/Button.styles.d.ts +5 -2312
- package/dist/components/Card/Card.styles.d.ts +3 -1734
- package/dist/components/Cards/AccountCard/AccountCard.styles.d.ts +8 -4624
- package/dist/components/Cards/BalanceCard/BalanceCard.styles.d.ts +15 -8670
- package/dist/components/Cards/DisruptiveCard/DisruptiveCard.styles.d.ts +1 -578
- package/dist/components/Cards/HeroImageCard/HeroImageCard.styles.d.ts +3 -1734
- package/dist/components/Cards/IconDataCard/IconDataCard.styles.d.ts +4 -2312
- package/dist/components/Cards/IconTextCard/IconTextCard.styles.d.ts +3 -1734
- package/dist/components/Cards/IllustrationTextCard/IllustrationTextCard.styles.d.ts +5 -2890
- package/dist/components/Cards/IllustrationTextCard/IllustrationTextCard.styles.js +1 -2
- package/dist/components/Cards/LinkTextCard/LinkTextCard.styles.d.ts +5 -2890
- package/dist/components/Cards/OfferCard/OfferCard.d.ts +22 -0
- package/dist/components/Cards/OfferCard/OfferCard.js +36 -0
- package/dist/components/Cards/OfferCard/OfferCard.styles.d.ts +34 -0
- package/dist/components/Cards/OfferCard/OfferCard.styles.js +61 -0
- package/dist/components/Cards/OfferCard/index.d.ts +1 -0
- package/dist/components/Cards/OfferCard/index.js +17 -0
- package/dist/components/Cards/ProgressBarCard/ProgressBarCard.styles.d.ts +9 -5202
- package/dist/components/Cards/QuickLinkCard/QuickLinkCard.styles.d.ts +5 -2890
- package/dist/components/Cards/ServicesImageCard/ServicesImageCard.styles.d.ts +5 -2890
- package/dist/components/Cards/shared.styles.d.ts +10 -5780
- package/dist/components/Checkbox/styled.d.ts +6 -3468
- package/dist/components/CurrencyInput/styled.d.ts +4 -2312
- package/dist/components/DataTable/styles.d.ts +13 -7514
- package/dist/components/Disclosure/Disclosure.d.ts +1 -578
- package/dist/components/Em/Em.d.ts +1 -578
- package/dist/components/EmptyState/styles.d.ts +2 -1156
- package/dist/components/ErrorText/ErrorText.d.ts +1 -578
- package/dist/components/Grid/Col.d.ts +1 -578
- package/dist/components/HintText/HintText.d.ts +1 -578
- package/dist/components/Input/styled.d.ts +3 -1734
- package/dist/components/LabelText/LabelText.d.ts +1 -578
- package/dist/components/LargeValueReference/styles.d.ts +3 -1734
- package/dist/components/LineThrough/LineThrough.d.ts +1 -578
- package/dist/components/List/styled.d.ts +4 -2312
- package/dist/components/Margin/Margin.d.ts +1 -578
- package/dist/components/NavHeader/NavHeader.styles.d.ts +11 -6358
- package/dist/components/Notification/Notification.d.ts +2 -2
- package/dist/components/Notification/Notification.js +20 -12
- package/dist/components/Notification/Notification.styles.d.ts +13 -5202
- package/dist/components/Notification/Notification.styles.js +21 -2
- package/dist/components/PasswordInput/PasswordInput.styled.d.ts +1 -578
- package/dist/components/Radio/Radio.d.ts +2 -2
- package/dist/components/Radio/Radio.js +5 -43
- package/dist/components/Radio/Radio.styles.d.ts +9 -0
- package/dist/components/Radio/Radio.styles.js +74 -0
- package/dist/components/RadioCard/RadioCard.styles.d.ts +5 -2890
- package/dist/components/Rail/Rail.d.ts +12 -0
- package/dist/components/Rail/Rail.js +58 -0
- package/dist/components/Rail/RailIndicator.d.ts +7 -0
- package/dist/components/Rail/RailIndicator.js +81 -0
- package/dist/components/Rail/index.d.ts +1 -0
- package/dist/components/Rail/index.js +5 -0
- package/dist/components/Rail/styles.d.ts +13 -0
- package/dist/components/Rail/styles.js +55 -0
- package/dist/components/Rail/useRailPaging.d.ts +13 -0
- package/dist/components/Rail/useRailPaging.js +95 -0
- package/dist/components/SelectField/styled.d.ts +8 -4624
- package/dist/components/Strong/Strong.d.ts +1 -578
- package/dist/components/SubLabelText/SubLabelText.d.ts +1 -578
- package/dist/components/Tabs/Tab.d.ts +1 -578
- package/dist/components/Toast/Toast.d.ts +10 -4
- package/dist/components/Toast/Toast.js +40 -27
- package/dist/components/Toggle/styles.d.ts +4 -2312
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +2 -0
- package/dist/esm/components/ActionList/ActionListItems/DataListItem.js +3 -1
- package/dist/esm/components/ActionList/ActionListItems/ToggleListItem.js +5 -6
- package/dist/esm/components/ActionList/ActionListItems/styles.js +17 -15
- package/dist/esm/components/BottomActionBar/BottomActionBar.js +40 -0
- package/dist/esm/components/BottomActionBar/OverlayProvider.js +30 -0
- package/dist/esm/components/BottomActionBar/index.js +2 -0
- package/dist/esm/components/Cards/IllustrationTextCard/IllustrationTextCard.styles.js +1 -2
- package/dist/esm/components/Cards/OfferCard/OfferCard.js +32 -0
- package/dist/esm/components/Cards/OfferCard/OfferCard.styles.js +55 -0
- package/dist/esm/components/Cards/OfferCard/index.js +1 -0
- package/dist/esm/components/Notification/Notification.js +21 -13
- package/dist/esm/components/Notification/Notification.styles.js +20 -1
- package/dist/esm/components/Radio/Radio.js +4 -39
- package/dist/esm/components/Radio/Radio.styles.js +38 -0
- package/dist/esm/components/Rail/Rail.js +21 -0
- package/dist/esm/components/Rail/RailIndicator.js +44 -0
- package/dist/esm/components/Rail/index.js +1 -0
- package/dist/esm/components/Rail/styles.js +49 -0
- package/dist/esm/components/Rail/useRailPaging.js +92 -0
- package/dist/esm/components/Toast/Toast.js +40 -27
- package/dist/esm/components/index.js +2 -0
- package/dist/styled.native.d.ts +1 -3463
- 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';
|
package/dist/components/index.js
CHANGED
|
@@ -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 {
|
|
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 {
|
|
5
|
-
import { ActionListItemWrapper } from './styles';
|
|
5
|
+
import { ActionListItemWrapper, TextContainer } from './styles';
|
|
6
6
|
export const ToggleListItem = ({ testID, heading, hintText, checked, onToggle, }) => {
|
|
7
|
-
|
|
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
|
-
|
|
98
|
-
|
|
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)((
|
|
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
|
+
};
|
|
@@ -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,
|
|
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
|
-
|
|
28
|
-
|
|
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,
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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:
|
|
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
|
|
14
|
+
import { useTheme } from '../../styled.native';
|
|
16
15
|
import { HintText } from '../HintText';
|
|
17
16
|
import { LabelText } from '../LabelText';
|
|
18
|
-
|
|
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
|
-
|
|
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';
|