@proximus/lavender-drawer-native 0.1.0-alpha.15
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/PxDrawer.d.ts +20 -0
- package/dist/PxDrawer.d.ts.map +1 -0
- package/dist/PxDrawer.js +109 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1 -0
- package/package.json +21 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AccessibilityProps } from 'react-native';
|
|
3
|
+
type DrawerSide = 'left' | 'right';
|
|
4
|
+
export interface DrawerProps extends AccessibilityProps {
|
|
5
|
+
title?: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
isOpen: boolean;
|
|
8
|
+
toggleSheet?: () => void;
|
|
9
|
+
side?: DrawerSide;
|
|
10
|
+
testID?: string;
|
|
11
|
+
children?: React.ReactNode;
|
|
12
|
+
onClose: () => void;
|
|
13
|
+
accessibilityAnnouncementMessage?: string;
|
|
14
|
+
accessibilityCloseButtonLabel?: string;
|
|
15
|
+
accessibilityCloseButtonHint?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function PxDrawer({ title, description, isOpen, toggleSheet, side, testID, children, onClose, accessibilityAnnouncementMessage, ...accessibilityProps }: DrawerProps): React.JSX.Element;
|
|
18
|
+
export declare function TopZone(props: Partial<DrawerProps>): React.JSX.Element;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=PxDrawer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PxDrawer.d.ts","sourceRoot":"","sources":["../src/PxDrawer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAC3D,OAAO,EAEL,kBAAkB,EAOnB,MAAM,cAAc,CAAC;AAOtB,KAAK,UAAU,GAAG,MAAM,GAAG,OAAO,CAAC;AAInC,MAAM,WAAW,WAAY,SAAQ,kBAAkB;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,MAAM,EAAE,OAAO,CAAC;IAEhB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IAEzB,IAAI,CAAC,EAAE,UAAU,CAAC;IAGlB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE3B,OAAO,EAAE,MAAM,IAAI,CAAC;IAEpB,gCAAgC,CAAC,EAAE,MAAM,CAAC;IAC1C,6BAA6B,CAAC,EAAE,MAAM,CAAC;IACvC,4BAA4B,CAAC,EAAE,MAAM,CAAC;CACvC;AAGD,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,WAAW,EACX,MAAM,EACN,WAAW,EACX,IAAa,EACb,MAAM,EACN,QAAQ,EACR,OAAO,EACP,gCAAgC,EAChC,GAAG,kBAAkB,EACtB,EAAE,WAAW,qBAgHb;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,qBAqDlD"}
|
package/dist/PxDrawer.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { AccessibilityInfo, Animated, Dimensions, Modal, StyleSheet, TouchableOpacity, View, } from 'react-native';
|
|
3
|
+
import { a11y, e2eID } from '@proximus/lavender-common-native';
|
|
4
|
+
import { useTheme } from '@proximus/lavender-styling-native';
|
|
5
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
6
|
+
import { Body, Header } from '@proximus/lavender-texts-native';
|
|
7
|
+
import { PxButtonIcon } from '@proximus/lavender-buttonicon-native';
|
|
8
|
+
const DURATION_DEFAULT = 300;
|
|
9
|
+
// A simple side drawer implemented with React Native Animated
|
|
10
|
+
export function PxDrawer({ title, description, isOpen, toggleSheet, side = 'left', testID, children, onClose, accessibilityAnnouncementMessage, ...accessibilityProps }) {
|
|
11
|
+
const baseId = testID ?? 'PxDrawer';
|
|
12
|
+
const screenWidth = Dimensions.get('window').width;
|
|
13
|
+
const drawerWidth = Math.round(screenWidth * 0.9);
|
|
14
|
+
const { theme } = useTheme();
|
|
15
|
+
const { bottom, top } = useSafeAreaInsets();
|
|
16
|
+
// progress: 0 (closed) -> 1 (open)
|
|
17
|
+
const progress = useRef(new Animated.Value(isOpen ? 1 : 0)).current;
|
|
18
|
+
// Control Modal visibility so the drawer truly covers the entire screen
|
|
19
|
+
const [visible, setVisible] = useState(isOpen);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
// Ensure the modal is visible before starting the open animation
|
|
22
|
+
if (isOpen && !visible) {
|
|
23
|
+
setVisible(true);
|
|
24
|
+
}
|
|
25
|
+
Animated.timing(progress, {
|
|
26
|
+
toValue: isOpen ? 1 : 0,
|
|
27
|
+
duration: DURATION_DEFAULT,
|
|
28
|
+
useNativeDriver: true,
|
|
29
|
+
}).start(({ finished }) => {
|
|
30
|
+
if (finished && !isOpen) {
|
|
31
|
+
// After close animation completes, hide the modal
|
|
32
|
+
setVisible(false);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}, [isOpen, progress, visible]);
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (accessibilityAnnouncementMessage && visible) {
|
|
38
|
+
// Announce to screen readers that the drawer has appeared
|
|
39
|
+
AccessibilityInfo.announceForAccessibility(accessibilityAnnouncementMessage);
|
|
40
|
+
}
|
|
41
|
+
}, [accessibilityAnnouncementMessage, visible]);
|
|
42
|
+
// Translate from off-screen to 0 depending on side
|
|
43
|
+
const offscreen = side === 'left' ? -drawerWidth : drawerWidth;
|
|
44
|
+
const translateX = progress.interpolate({
|
|
45
|
+
inputRange: [0, 1],
|
|
46
|
+
outputRange: [offscreen, 0],
|
|
47
|
+
});
|
|
48
|
+
const backdropOpacity = progress.interpolate({
|
|
49
|
+
inputRange: [0, 1],
|
|
50
|
+
outputRange: [0, 1],
|
|
51
|
+
});
|
|
52
|
+
const pointerEvents = isOpen ? 'auto' : 'none';
|
|
53
|
+
return (React.createElement(Modal, { ...e2eID(`${baseId}.Modal`), ...a11y(accessibilityProps), visible: visible, transparent: true, animationType: "none", onRequestClose: toggleSheet, statusBarTranslucent: true },
|
|
54
|
+
React.createElement(View, { style: styles.modalRoot, pointerEvents: "box-none", ...e2eID(`${baseId}.Root`) },
|
|
55
|
+
React.createElement(Animated.View, { style: [styles.backdrop, { opacity: backdropOpacity }], pointerEvents: pointerEvents },
|
|
56
|
+
React.createElement(TouchableOpacity, { style: { flex: 1 }, onPress: toggleSheet, ...e2eID(`${baseId}.Backdrop`) })),
|
|
57
|
+
React.createElement(Animated.View, { style: [
|
|
58
|
+
styles.drawer,
|
|
59
|
+
{
|
|
60
|
+
width: drawerWidth,
|
|
61
|
+
left: side === 'left' ? 0 : undefined,
|
|
62
|
+
right: side === 'right' ? 0 : undefined,
|
|
63
|
+
transform: [{ translateX }],
|
|
64
|
+
backgroundColor: theme.t('ColorBackgroundSurfaceLight'),
|
|
65
|
+
paddingTop: top + theme.t('SpacingXsMobile').number,
|
|
66
|
+
paddingBottom: bottom,
|
|
67
|
+
},
|
|
68
|
+
], ...e2eID(`${baseId}.Panel`) },
|
|
69
|
+
React.createElement(View, { style: {
|
|
70
|
+
flex: 1,
|
|
71
|
+
gap: theme.t('SpacingSMobile').number,
|
|
72
|
+
padding: theme.t('SpacingSMobile').number,
|
|
73
|
+
} },
|
|
74
|
+
React.createElement(TopZone, { title, description, testID, onClose }),
|
|
75
|
+
children)))));
|
|
76
|
+
}
|
|
77
|
+
export function TopZone(props) {
|
|
78
|
+
const { title, description, testID, onClose, accessibilityCloseButtonLabel, accessibilityCloseButtonHint, } = props;
|
|
79
|
+
const { theme } = useTheme();
|
|
80
|
+
return (React.createElement(View, { style: {
|
|
81
|
+
flexDirection: 'row',
|
|
82
|
+
alignItems: 'flex-start',
|
|
83
|
+
} },
|
|
84
|
+
React.createElement(View, { style: {
|
|
85
|
+
flex: 1,
|
|
86
|
+
gap: theme.t('SpacingHeadingToSubtitleMobile').number,
|
|
87
|
+
} },
|
|
88
|
+
React.createElement(Header, { style: {
|
|
89
|
+
color: theme.t('ColorTextBrandDefault'),
|
|
90
|
+
fontSize: theme.t('TextSizeHeadingXlMobile').number,
|
|
91
|
+
}, ...(testID && e2eID(`${testID}-drawer-title`)) }, title),
|
|
92
|
+
React.createElement(Body, { style: { fontSize: theme.t('TextSizeBodyLMobile').number }, ...(testID && e2eID(`${testID}-drawer-description`)) }, description)),
|
|
93
|
+
React.createElement(View, null,
|
|
94
|
+
React.createElement(PxButtonIcon, { onPress: onClose, iconName: 'cross', variant: 'secondary', size: 'small', testID: `${testID}-drawer-close-button`, accessibilityLabel: accessibilityCloseButtonLabel || 'Close drawer', accessibilityHint: accessibilityCloseButtonHint }))));
|
|
95
|
+
}
|
|
96
|
+
const styles = StyleSheet.create({
|
|
97
|
+
modalRoot: {
|
|
98
|
+
flex: 1,
|
|
99
|
+
},
|
|
100
|
+
drawer: {
|
|
101
|
+
position: 'absolute',
|
|
102
|
+
top: 0,
|
|
103
|
+
bottom: 0,
|
|
104
|
+
},
|
|
105
|
+
backdrop: {
|
|
106
|
+
...StyleSheet.absoluteFillObject,
|
|
107
|
+
backgroundColor: 'rgba(0, 0, 0, 0.3)',
|
|
108
|
+
},
|
|
109
|
+
});
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './PxDrawer';
|
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@proximus/lavender-drawer-native",
|
|
3
|
+
"version": "0.1.0-alpha.15",
|
|
4
|
+
"description": "Lavender drawer component",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"peerDependencies": {
|
|
12
|
+
"@proximus/lavender-buttonicon-native": "*",
|
|
13
|
+
"@proximus/lavender-common-native": "*",
|
|
14
|
+
"@proximus/lavender-icon-native": "*",
|
|
15
|
+
"@proximus/lavender-styling-native": "*",
|
|
16
|
+
"@proximus/lavender-texts-native": "*"
|
|
17
|
+
},
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
}
|
|
21
|
+
}
|