@fluentui-react-native/drawer 0.1.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/.eslintrc.js +3 -0
- package/CHANGELOG.json +20 -0
- package/CHANGELOG.md +13 -0
- package/SPEC.md +1 -0
- package/babel.config.js +1 -0
- package/jest.config.js +2 -0
- package/just.config.js +3 -0
- package/lib/Drawer.d.ts +4 -0
- package/lib/Drawer.d.ts.map +1 -0
- package/lib/Drawer.js +51 -0
- package/lib/Drawer.js.map +1 -0
- package/lib/Drawer.styling.d.ts +4 -0
- package/lib/Drawer.styling.d.ts.map +1 -0
- package/lib/Drawer.styling.js +47 -0
- package/lib/Drawer.styling.js.map +1 -0
- package/lib/Drawer.types.d.ts +184 -0
- package/lib/Drawer.types.d.ts.map +1 -0
- package/lib/Drawer.types.js +2 -0
- package/lib/Drawer.types.js.map +1 -0
- package/lib/DrawerTokens.d.ts +5 -0
- package/lib/DrawerTokens.d.ts.map +1 -0
- package/lib/DrawerTokens.js +37 -0
- package/lib/DrawerTokens.js.map +1 -0
- package/lib/__tests__/Drawer.test.d.ts +2 -0
- package/lib/__tests__/Drawer.test.d.ts.map +1 -0
- package/lib/__tests__/Drawer.test.js +16 -0
- package/lib/__tests__/Drawer.test.js.map +1 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -0
- package/lib/useDrawer.d.ts +3 -0
- package/lib/useDrawer.d.ts.map +1 -0
- package/lib/useDrawer.js +85 -0
- package/lib/useDrawer.js.map +1 -0
- package/lib-commonjs/Drawer.d.ts +4 -0
- package/lib-commonjs/Drawer.d.ts.map +1 -0
- package/lib-commonjs/Drawer.js +55 -0
- package/lib-commonjs/Drawer.js.map +1 -0
- package/lib-commonjs/Drawer.styling.d.ts +4 -0
- package/lib-commonjs/Drawer.styling.d.ts.map +1 -0
- package/lib-commonjs/Drawer.styling.js +50 -0
- package/lib-commonjs/Drawer.styling.js.map +1 -0
- package/lib-commonjs/Drawer.types.d.ts +184 -0
- package/lib-commonjs/Drawer.types.d.ts.map +1 -0
- package/lib-commonjs/Drawer.types.js +5 -0
- package/lib-commonjs/Drawer.types.js.map +1 -0
- package/lib-commonjs/DrawerTokens.d.ts +5 -0
- package/lib-commonjs/DrawerTokens.d.ts.map +1 -0
- package/lib-commonjs/DrawerTokens.js +41 -0
- package/lib-commonjs/DrawerTokens.js.map +1 -0
- package/lib-commonjs/__tests__/Drawer.test.d.ts +2 -0
- package/lib-commonjs/__tests__/Drawer.test.d.ts.map +1 -0
- package/lib-commonjs/__tests__/Drawer.test.js +41 -0
- package/lib-commonjs/__tests__/Drawer.test.js.map +1 -0
- package/lib-commonjs/index.d.ts +4 -0
- package/lib-commonjs/index.d.ts.map +1 -0
- package/lib-commonjs/index.js +8 -0
- package/lib-commonjs/index.js.map +1 -0
- package/lib-commonjs/useDrawer.d.ts +3 -0
- package/lib-commonjs/useDrawer.d.ts.map +1 -0
- package/lib-commonjs/useDrawer.js +89 -0
- package/lib-commonjs/useDrawer.js.map +1 -0
- package/package.json +59 -0
- package/src/Drawer.styling.ts +59 -0
- package/src/Drawer.tsx +51 -0
- package/src/Drawer.types.ts +221 -0
- package/src/DrawerTokens.ts +40 -0
- package/src/__tests__/Drawer.test.tsx +22 -0
- package/src/__tests__/__snapshots__/Drawer.test.tsx.snap +20 -0
- package/src/index.ts +3 -0
- package/src/useDrawer.ts +90 -0
- package/svgs.d.ts +4 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Theme, UseStylingOptions } from '@fluentui-react-native/framework';
|
|
2
|
+
import { buildProps } from '@fluentui-react-native/framework';
|
|
3
|
+
|
|
4
|
+
import { DrawerName } from './Drawer.types';
|
|
5
|
+
import type { DrawerTokens, DrawerSlotProps, DrawerProps } from './Drawer.types';
|
|
6
|
+
import { defaultDrawerTokens } from './DrawerTokens';
|
|
7
|
+
|
|
8
|
+
export const stylingSettings: UseStylingOptions<DrawerProps, DrawerSlotProps, DrawerTokens> = {
|
|
9
|
+
tokens: [defaultDrawerTokens, DrawerName],
|
|
10
|
+
tokensThatAreAlsoProps: 'all',
|
|
11
|
+
states: ['left', 'right', 'bottom'],
|
|
12
|
+
slotProps: {
|
|
13
|
+
scrimContent: buildProps(
|
|
14
|
+
(tokens: DrawerTokens, _theme: Theme) => ({
|
|
15
|
+
style: {
|
|
16
|
+
position: 'absolute',
|
|
17
|
+
top: 0,
|
|
18
|
+
left: 0,
|
|
19
|
+
width: '100%',
|
|
20
|
+
height: '100%',
|
|
21
|
+
backgroundColor: tokens.scrimColor,
|
|
22
|
+
opacity: tokens.scrimOpacity,
|
|
23
|
+
},
|
|
24
|
+
}),
|
|
25
|
+
['scrimColor'],
|
|
26
|
+
),
|
|
27
|
+
content: buildProps(
|
|
28
|
+
(tokens: DrawerTokens, _theme: Theme) => ({
|
|
29
|
+
style: {
|
|
30
|
+
position: 'absolute',
|
|
31
|
+
height: tokens.height,
|
|
32
|
+
width: tokens.width,
|
|
33
|
+
elevation: tokens.drawerElevation,
|
|
34
|
+
borderTopEndRadius: tokens.drawerCornerRadius,
|
|
35
|
+
borderTopStartRadius: tokens.drawerCornerRadius,
|
|
36
|
+
right: tokens.rightPosition,
|
|
37
|
+
left: tokens.leftPosition,
|
|
38
|
+
bottom: tokens.bottomPosition,
|
|
39
|
+
top: tokens.topPosition,
|
|
40
|
+
backgroundColor: tokens.drawerBackgroundColor,
|
|
41
|
+
},
|
|
42
|
+
}),
|
|
43
|
+
['drawerBackgroundColor', 'drawerElevation', 'height', 'width'],
|
|
44
|
+
),
|
|
45
|
+
handle: buildProps(
|
|
46
|
+
(tokens: DrawerTokens, _theme: Theme) => ({
|
|
47
|
+
style: {
|
|
48
|
+
width: tokens.handleWidth,
|
|
49
|
+
height: tokens.handleHeight,
|
|
50
|
+
borderRadius: tokens.handleCornerRadius,
|
|
51
|
+
backgroundColor: tokens.handleBackgroundColor,
|
|
52
|
+
alignSelf: tokens.handleAlignment,
|
|
53
|
+
marginTop: tokens.handleMarginTop,
|
|
54
|
+
},
|
|
55
|
+
}),
|
|
56
|
+
['handleWidth', 'handleHeight', 'handleCornerRadius', 'handleBackgroundColor', 'handleAlignment', 'handleMarginTop'],
|
|
57
|
+
),
|
|
58
|
+
},
|
|
59
|
+
};
|
package/src/Drawer.tsx
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** @jsx withSlots */
|
|
2
|
+
import { Animated, Modal, TouchableWithoutFeedback, View } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import type { UseSlots } from '@fluentui-react-native/framework';
|
|
5
|
+
import { compose, mergeProps, withSlots } from '@fluentui-react-native/framework';
|
|
6
|
+
|
|
7
|
+
import { stylingSettings } from './Drawer.styling';
|
|
8
|
+
import type { DrawerType, DrawerProps } from './Drawer.types';
|
|
9
|
+
import { DrawerName } from './Drawer.types';
|
|
10
|
+
import { useDrawer } from './useDrawer';
|
|
11
|
+
|
|
12
|
+
export const drawerLookup = (layer: string, userProps: DrawerProps): boolean => {
|
|
13
|
+
return userProps[layer] || layer === userProps['drawerPosition'];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const Drawer = compose<DrawerType>({
|
|
17
|
+
displayName: DrawerName,
|
|
18
|
+
...stylingSettings,
|
|
19
|
+
slots: {
|
|
20
|
+
modal: Modal,
|
|
21
|
+
scrim: TouchableWithoutFeedback,
|
|
22
|
+
scrimContent: Animated.View,
|
|
23
|
+
content: Animated.View,
|
|
24
|
+
handle: View,
|
|
25
|
+
},
|
|
26
|
+
useRender: (userProps: DrawerProps, useSlots: UseSlots<DrawerType>) => {
|
|
27
|
+
const drawerProps = useDrawer(userProps).props;
|
|
28
|
+
const Slots = useSlots(userProps, (layer) => drawerLookup(layer, drawerProps));
|
|
29
|
+
return (final: DrawerProps, children: React.ReactNode) => {
|
|
30
|
+
const { open, onClose, onScrimClick, animationConfig, drawerPosition, showHandle, ...rest } = mergeProps(drawerProps, final);
|
|
31
|
+
return (
|
|
32
|
+
<Slots.modal
|
|
33
|
+
{...rest}
|
|
34
|
+
visible={open}
|
|
35
|
+
onRequestClose={onClose}
|
|
36
|
+
supportedOrientations={['portrait', 'portrait-upside-down', 'landscape', 'landscape-left', 'landscape-right']}
|
|
37
|
+
animationType="none"
|
|
38
|
+
transparent
|
|
39
|
+
>
|
|
40
|
+
<Slots.scrim onPress={onScrimClick}>
|
|
41
|
+
<Slots.scrimContent style={[{ opacity: animationConfig.animatedOpacity }]} />
|
|
42
|
+
</Slots.scrim>
|
|
43
|
+
<Slots.content style={animationConfig.animatedStyle}>
|
|
44
|
+
{drawerPosition === 'bottom' && showHandle && <Slots.handle />}
|
|
45
|
+
{children}
|
|
46
|
+
</Slots.content>
|
|
47
|
+
</Slots.modal>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
});
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import type { Animated, ColorValue, FlexAlignType, ModalProps, TouchableWithoutFeedbackProps, ViewProps } from 'react-native';
|
|
2
|
+
|
|
3
|
+
import type { InteractionEvent, PressableFocusProps } from '@fluentui-react-native/interactive-hooks';
|
|
4
|
+
|
|
5
|
+
export const DrawerName = 'Drawer';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Specifies the possible position of the Drawer.
|
|
9
|
+
*/
|
|
10
|
+
export type DrawerPositionType = 'bottom' | 'left' | 'right';
|
|
11
|
+
|
|
12
|
+
export interface DrawerTokens {
|
|
13
|
+
/**
|
|
14
|
+
* The color of the scrim.
|
|
15
|
+
* */
|
|
16
|
+
scrimColor?: ColorValue;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The opacity of the scrim.
|
|
20
|
+
* */
|
|
21
|
+
scrimOpacity?: number;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Width of the handle.
|
|
25
|
+
*/
|
|
26
|
+
handleWidth?: number;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Height of the handle.
|
|
30
|
+
*/
|
|
31
|
+
handleHeight?: number;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The background color of the handle.
|
|
35
|
+
* */
|
|
36
|
+
handleBackgroundColor?: ColorValue;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The corner radius of the handle.
|
|
40
|
+
* */
|
|
41
|
+
handleCornerRadius?: number;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The top margin of the handle.
|
|
45
|
+
* */
|
|
46
|
+
handleMarginTop?: number;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The bottom margin of the handle.
|
|
50
|
+
* */
|
|
51
|
+
|
|
52
|
+
handleMarginBottom?: number;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The start margin of the handle.
|
|
56
|
+
* */
|
|
57
|
+
|
|
58
|
+
handleMarginStart?: number;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The end margin of the handle.
|
|
62
|
+
* */
|
|
63
|
+
|
|
64
|
+
handleMarginEnd?: number;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The flex alignment of the handle.
|
|
68
|
+
* */
|
|
69
|
+
handleAlignment?: FlexAlignType;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The background for drawer
|
|
73
|
+
* */
|
|
74
|
+
|
|
75
|
+
drawerBackgroundColor?: ColorValue;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The corner radius of the Drawer
|
|
79
|
+
* @default 0
|
|
80
|
+
* */
|
|
81
|
+
drawerCornerRadius?: number;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The elevation of the Drawer
|
|
85
|
+
* @default 5
|
|
86
|
+
* @platform android
|
|
87
|
+
* */
|
|
88
|
+
drawerElevation?: number;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The width of the Drawer
|
|
92
|
+
* Note: Only applicable when position is 'left' or 'right'
|
|
93
|
+
* @default '100%'
|
|
94
|
+
* */
|
|
95
|
+
width?: number | string;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* The height of the Drawer
|
|
99
|
+
* Note: Only applicable when position is 'bottom'
|
|
100
|
+
* @default '40%'
|
|
101
|
+
* */
|
|
102
|
+
height?: number | string;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* The shadow color of the Drawer
|
|
106
|
+
* @platform iOS
|
|
107
|
+
* */
|
|
108
|
+
shadowColor?: ColorValue;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The shadow offset of the Drawer
|
|
112
|
+
* @platform iOS
|
|
113
|
+
* */
|
|
114
|
+
shadowOffset?: { width: number; height: number };
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The shadow opacity of the Drawer
|
|
118
|
+
* @platform iOS
|
|
119
|
+
* */
|
|
120
|
+
shadowOpacity?: number;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The shadow radius of the Drawer
|
|
124
|
+
* @platform iOS
|
|
125
|
+
* */
|
|
126
|
+
|
|
127
|
+
shadowRadius?: number;
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Positions/Behaviours of the Drawer, This is used to apply different tokens for different positions.
|
|
131
|
+
*/
|
|
132
|
+
|
|
133
|
+
left?: DrawerTokens;
|
|
134
|
+
right?: DrawerTokens;
|
|
135
|
+
bottom?: DrawerTokens;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Coordinate position of the Drawer, This is used to position the Drawer at a particular coordinate.
|
|
139
|
+
*/
|
|
140
|
+
leftPosition?: number;
|
|
141
|
+
rightPosition?: number;
|
|
142
|
+
bottomPosition?: number;
|
|
143
|
+
topPosition?: number;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface DrawerProps extends PressableFocusProps {
|
|
147
|
+
/*
|
|
148
|
+
** An accessibility label for screen readers. Set on the text Drawer.
|
|
149
|
+
*/
|
|
150
|
+
accessibilityLabel?: string;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Visibility of the Drawer
|
|
154
|
+
*/
|
|
155
|
+
open?: boolean;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Callback when the Drawer is closed
|
|
159
|
+
* */
|
|
160
|
+
onClose?: (e: InteractionEvent) => void;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Callback when the Drawer is opened
|
|
164
|
+
* */
|
|
165
|
+
onOpen?: (e: InteractionEvent) => void;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Callback when the scrim is clicked
|
|
169
|
+
* */
|
|
170
|
+
onScrimClick?: (e: InteractionEvent) => void;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* The content of the Drawer
|
|
174
|
+
* */
|
|
175
|
+
children?: React.ReactNode;
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* The behavior of the Drawer
|
|
179
|
+
* @default 'left'
|
|
180
|
+
* */
|
|
181
|
+
drawerPosition?: DrawerPositionType;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* The behavior is for only bottom drawer in which content is scrollable without expanding the bottom drawer
|
|
185
|
+
* @default false
|
|
186
|
+
* */
|
|
187
|
+
isContentScrollableUnexpanded?: boolean;
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The behavior is for only bottom drawer in which handle can be hidden for some usecases
|
|
191
|
+
* @default true
|
|
192
|
+
* */
|
|
193
|
+
showHandle?: boolean;
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* The width of the Drawer
|
|
197
|
+
* Animation configuration for the Drawer
|
|
198
|
+
* */
|
|
199
|
+
animationConfig?: {
|
|
200
|
+
animatedOpacity: Animated.AnimatedInterpolation;
|
|
201
|
+
animatedStyle: { transform: { translateX: Animated.AnimatedInterpolation }[] | { translateY: Animated.AnimatedInterpolation }[] };
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface DrawerInfo {
|
|
206
|
+
props: DrawerProps;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export interface DrawerSlotProps {
|
|
210
|
+
modal: ModalProps;
|
|
211
|
+
scrim: TouchableWithoutFeedbackProps;
|
|
212
|
+
scrimContent: Animated.AnimatedProps<ViewProps>;
|
|
213
|
+
content: Animated.AnimatedProps<ViewProps>;
|
|
214
|
+
handle: ViewProps;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export interface DrawerType {
|
|
218
|
+
props: DrawerProps;
|
|
219
|
+
tokens: DrawerTokens;
|
|
220
|
+
slotProps: DrawerSlotProps;
|
|
221
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Theme } from '@fluentui-react-native/framework';
|
|
2
|
+
import { globalTokens } from '@fluentui-react-native/theme-tokens';
|
|
3
|
+
import type { TokenSettings } from '@fluentui-react-native/use-styling';
|
|
4
|
+
|
|
5
|
+
import type { DrawerTokens } from './Drawer.types';
|
|
6
|
+
|
|
7
|
+
export const defaultDrawerTokens: TokenSettings<DrawerTokens, Theme> = (t: Theme) =>
|
|
8
|
+
({
|
|
9
|
+
scrimColor: '#00000080', // to be replace with token in future based on design guidance
|
|
10
|
+
drawerBackgroundColor: t.colors.neutralBackground2,
|
|
11
|
+
handleBackgroundColor: t.colors.neutralStroke1,
|
|
12
|
+
handleWidth: globalTokens.size360,
|
|
13
|
+
handleHeight: globalTokens.size40,
|
|
14
|
+
handleCornerRadius: globalTokens.size20,
|
|
15
|
+
handleAlignment: 'center',
|
|
16
|
+
handleMarginTop: globalTokens.size80,
|
|
17
|
+
handleMarginBottom: globalTokens.sizeNone,
|
|
18
|
+
handleMarginEnd: globalTokens.sizeNone,
|
|
19
|
+
handleMarginStart: globalTokens.sizeNone,
|
|
20
|
+
drawerElevation: globalTokens.size100,
|
|
21
|
+
topPosition: 0,
|
|
22
|
+
left: {
|
|
23
|
+
height: '100%',
|
|
24
|
+
width: '80%',
|
|
25
|
+
leftPosition: 0,
|
|
26
|
+
drawerCornerRadius: 0,
|
|
27
|
+
},
|
|
28
|
+
right: {
|
|
29
|
+
height: '100%',
|
|
30
|
+
width: '80%',
|
|
31
|
+
rightPosition: 0,
|
|
32
|
+
drawerCornerRadius: 0,
|
|
33
|
+
},
|
|
34
|
+
bottom: {
|
|
35
|
+
bottomPosition: 0,
|
|
36
|
+
width: '100%',
|
|
37
|
+
drawerCornerRadius: globalTokens.corner.radius120,
|
|
38
|
+
height: '50%',
|
|
39
|
+
},
|
|
40
|
+
} as DrawerTokens);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Text } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import * as renderer from 'react-test-renderer';
|
|
5
|
+
|
|
6
|
+
import { Drawer } from '../Drawer';
|
|
7
|
+
|
|
8
|
+
// mocks out setTimeout and other timer functions with mock functions , test will fail without this as we're using Animated API
|
|
9
|
+
jest.useFakeTimers();
|
|
10
|
+
|
|
11
|
+
describe('Drawer component tests', () => {
|
|
12
|
+
it('Drawer default', () => {
|
|
13
|
+
const tree = renderer
|
|
14
|
+
.create(
|
|
15
|
+
<Drawer open={false} drawerPosition="left">
|
|
16
|
+
<Text>Hello</Text>
|
|
17
|
+
</Drawer>,
|
|
18
|
+
)
|
|
19
|
+
.toJSON();
|
|
20
|
+
expect(tree).toMatchSnapshot();
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`Drawer component tests Drawer default 1`] = `
|
|
4
|
+
<Modal
|
|
5
|
+
animationType="none"
|
|
6
|
+
hardwareAccelerated={false}
|
|
7
|
+
onRequestClose={[Function]}
|
|
8
|
+
supportedOrientations={
|
|
9
|
+
Array [
|
|
10
|
+
"portrait",
|
|
11
|
+
"portrait-upside-down",
|
|
12
|
+
"landscape",
|
|
13
|
+
"landscape-left",
|
|
14
|
+
"landscape-right",
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
transparent={true}
|
|
18
|
+
visible={false}
|
|
19
|
+
/>
|
|
20
|
+
`;
|
package/src/index.ts
ADDED
package/src/useDrawer.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { useRef, useEffect, useState, useCallback } from 'react';
|
|
2
|
+
import { Animated, Dimensions } from 'react-native';
|
|
3
|
+
|
|
4
|
+
import type { InteractionEvent } from '@fluentui-react-native/interactive-hooks';
|
|
5
|
+
|
|
6
|
+
import type { DrawerProps, DrawerInfo } from './Drawer.types';
|
|
7
|
+
|
|
8
|
+
const { height, width } = Dimensions.get('window');
|
|
9
|
+
|
|
10
|
+
export const useDrawer = (props: DrawerProps): DrawerInfo => {
|
|
11
|
+
const { onBlur, onFocus, accessibilityLabel, open, drawerPosition = 'left', showHandle = true, children, ...rest } = props;
|
|
12
|
+
const animatedValue = useRef(new Animated.Value(0)).current;
|
|
13
|
+
const [internalOpen, setInternalOpen] = useState(open);
|
|
14
|
+
const [isFirstOpen, setIsFirstOpen] = useState(true);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (open) {
|
|
18
|
+
setInternalOpen(true);
|
|
19
|
+
Animated.timing(animatedValue, {
|
|
20
|
+
toValue: 1,
|
|
21
|
+
duration: 300,
|
|
22
|
+
useNativeDriver: true,
|
|
23
|
+
}).start();
|
|
24
|
+
} else {
|
|
25
|
+
if (isFirstOpen) {
|
|
26
|
+
setIsFirstOpen(false);
|
|
27
|
+
} else {
|
|
28
|
+
Animated.parallel([
|
|
29
|
+
Animated.timing(animatedValue, {
|
|
30
|
+
toValue: 0,
|
|
31
|
+
duration: 300,
|
|
32
|
+
useNativeDriver: true,
|
|
33
|
+
}),
|
|
34
|
+
]).start(() => {
|
|
35
|
+
setInternalOpen(false);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}, [animatedValue, open]);
|
|
40
|
+
|
|
41
|
+
const onClose = useCallback(
|
|
42
|
+
(e: InteractionEvent) => {
|
|
43
|
+
props?.onClose && props.onClose(e);
|
|
44
|
+
},
|
|
45
|
+
[props?.onClose],
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
const onScrimClick = useCallback(
|
|
49
|
+
(e: InteractionEvent) => {
|
|
50
|
+
props?.onScrimClick && props.onScrimClick(e);
|
|
51
|
+
},
|
|
52
|
+
[props?.onScrimClick],
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const animatedTranslateX = animatedValue.interpolate({
|
|
56
|
+
inputRange: [0, 1],
|
|
57
|
+
outputRange: drawerPosition === 'left' ? [-width * 0.8, 0] : drawerPosition === 'right' ? [width * 0.8, 0] : [0, 0],
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const animatedTranslateY = animatedValue.interpolate({
|
|
61
|
+
inputRange: [0, 1],
|
|
62
|
+
outputRange: [height, height * 0.5],
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const animatedOpacity = animatedValue.interpolate({
|
|
66
|
+
inputRange: [0, 1],
|
|
67
|
+
outputRange: [0, 0.5],
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const animatedStyle = {
|
|
71
|
+
transform:
|
|
72
|
+
drawerPosition === 'left' || drawerPosition === 'right' ? [{ translateX: animatedTranslateX }] : [{ translateY: animatedTranslateY }],
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
props: {
|
|
77
|
+
...rest,
|
|
78
|
+
onClose,
|
|
79
|
+
onScrimClick,
|
|
80
|
+
animationConfig: {
|
|
81
|
+
animatedOpacity,
|
|
82
|
+
animatedStyle,
|
|
83
|
+
},
|
|
84
|
+
drawerPosition: drawerPosition ?? 'left',
|
|
85
|
+
children,
|
|
86
|
+
showHandle,
|
|
87
|
+
open: internalOpen,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
};
|
package/svgs.d.ts
ADDED