@ankhorage/surface 3.4.6 → 4.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/CHANGELOG.md +13 -0
- package/README.md +1 -6
- package/dist/examples/DocsExamples.d.ts.map +1 -1
- package/dist/examples/DocsExamples.js +0 -6
- package/dist/examples/DocsExamples.js.map +1 -1
- package/dist/features/bottom-sheet/BottomSheetContext.d.ts +4 -0
- package/dist/features/bottom-sheet/BottomSheetContext.d.ts.map +1 -0
- package/dist/features/bottom-sheet/BottomSheetContext.js +3 -0
- package/dist/features/bottom-sheet/BottomSheetContext.js.map +1 -0
- package/dist/features/bottom-sheet/BottomSheetProvider.d.ts +6 -0
- package/dist/features/bottom-sheet/BottomSheetProvider.d.ts.map +1 -0
- package/dist/features/bottom-sheet/BottomSheetProvider.js +61 -0
- package/dist/features/bottom-sheet/BottomSheetProvider.js.map +1 -0
- package/dist/features/bottom-sheet/public.d.ts +4 -0
- package/dist/features/bottom-sheet/public.d.ts.map +1 -0
- package/dist/features/bottom-sheet/public.js +3 -0
- package/dist/features/bottom-sheet/public.js.map +1 -0
- package/dist/features/bottom-sheet/useBottomSheet.d.ts +4 -0
- package/dist/features/bottom-sheet/useBottomSheet.d.ts.map +1 -0
- package/dist/features/bottom-sheet/useBottomSheet.js +11 -0
- package/dist/features/bottom-sheet/useBottomSheet.js.map +1 -0
- package/dist/index.d.ts +0 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -3
- package/dist/index.js.map +1 -1
- package/dist/types/bottomSheet.d.ts +18 -0
- package/dist/types/bottomSheet.d.ts.map +1 -0
- package/dist/types/bottomSheet.js +2 -0
- package/dist/types/bottomSheet.js.map +1 -0
- package/package.json +17 -3
- package/src/examples/DocsExamples.tsx +0 -6
- package/src/features/bottom-sheet/BottomSheetContext.ts +5 -0
- package/src/features/bottom-sheet/BottomSheetProvider.tsx +129 -0
- package/src/features/bottom-sheet/public.ts +3 -0
- package/src/features/bottom-sheet/useBottomSheet.test.tsx +18 -0
- package/src/features/bottom-sheet/useBottomSheet.ts +15 -0
- package/src/index.test.ts +40 -12
- package/src/index.ts +0 -22
- package/src/types/bottomSheet.ts +19 -0
- package/dist/components/action-sheet/ActionSheet.d.ts +0 -4
- package/dist/components/action-sheet/ActionSheet.d.ts.map +0 -1
- package/dist/components/action-sheet/ActionSheet.js +0 -77
- package/dist/components/action-sheet/ActionSheet.js.map +0 -1
- package/dist/components/action-sheet/ActionSheetItem.d.ts +0 -4
- package/dist/components/action-sheet/ActionSheetItem.d.ts.map +0 -1
- package/dist/components/action-sheet/ActionSheetItem.js +0 -27
- package/dist/components/action-sheet/ActionSheetItem.js.map +0 -1
- package/dist/components/action-sheet/index.d.ts +0 -4
- package/dist/components/action-sheet/index.d.ts.map +0 -1
- package/dist/components/action-sheet/index.js +0 -3
- package/dist/components/action-sheet/index.js.map +0 -1
- package/dist/components/action-sheet/types.d.ts +0 -27
- package/dist/components/action-sheet/types.d.ts.map +0 -1
- package/dist/components/action-sheet/types.js +0 -2
- package/dist/components/action-sheet/types.js.map +0 -1
- package/dist/components/drawer/Drawer.d.ts +0 -4
- package/dist/components/drawer/Drawer.d.ts.map +0 -1
- package/dist/components/drawer/Drawer.js +0 -62
- package/dist/components/drawer/Drawer.js.map +0 -1
- package/dist/components/drawer/index.d.ts +0 -3
- package/dist/components/drawer/index.d.ts.map +0 -1
- package/dist/components/drawer/index.js +0 -2
- package/dist/components/drawer/index.js.map +0 -1
- package/dist/components/drawer/types.d.ts +0 -12
- package/dist/components/drawer/types.d.ts.map +0 -1
- package/dist/components/drawer/types.js +0 -2
- package/dist/components/drawer/types.js.map +0 -1
- package/dist/components/navigation/DrawerNavigation.d.ts +0 -4
- package/dist/components/navigation/DrawerNavigation.d.ts.map +0 -1
- package/dist/components/navigation/DrawerNavigation.js +0 -13
- package/dist/components/navigation/DrawerNavigation.js.map +0 -1
- package/dist/components/navigation/DrawerNavigationItem.d.ts +0 -4
- package/dist/components/navigation/DrawerNavigationItem.d.ts.map +0 -1
- package/dist/components/navigation/DrawerNavigationItem.js +0 -9
- package/dist/components/navigation/DrawerNavigationItem.js.map +0 -1
- package/dist/components/navigation/NavigationItem.d.ts +0 -4
- package/dist/components/navigation/NavigationItem.d.ts.map +0 -1
- package/dist/components/navigation/NavigationItem.js +0 -41
- package/dist/components/navigation/NavigationItem.js.map +0 -1
- package/dist/components/navigation/NavigationList.d.ts +0 -4
- package/dist/components/navigation/NavigationList.d.ts.map +0 -1
- package/dist/components/navigation/NavigationList.js +0 -9
- package/dist/components/navigation/NavigationList.js.map +0 -1
- package/dist/components/navigation/TabBar.d.ts +0 -4
- package/dist/components/navigation/TabBar.d.ts.map +0 -1
- package/dist/components/navigation/TabBar.js +0 -15
- package/dist/components/navigation/TabBar.js.map +0 -1
- package/dist/components/navigation/TabBarItem.d.ts +0 -4
- package/dist/components/navigation/TabBarItem.d.ts.map +0 -1
- package/dist/components/navigation/TabBarItem.js +0 -44
- package/dist/components/navigation/TabBarItem.js.map +0 -1
- package/dist/components/navigation/helpers.d.ts +0 -15
- package/dist/components/navigation/helpers.d.ts.map +0 -1
- package/dist/components/navigation/helpers.js +0 -48
- package/dist/components/navigation/helpers.js.map +0 -1
- package/dist/components/navigation/index.d.ts +0 -8
- package/dist/components/navigation/index.d.ts.map +0 -1
- package/dist/components/navigation/index.js +0 -7
- package/dist/components/navigation/index.js.map +0 -1
- package/dist/components/navigation/types.d.ts +0 -58
- package/dist/components/navigation/types.d.ts.map +0 -1
- package/dist/components/navigation/types.js +0 -2
- package/dist/components/navigation/types.js.map +0 -1
- package/src/components/action-sheet/ActionSheet.tsx +0 -130
- package/src/components/action-sheet/ActionSheetItem.tsx +0 -59
- package/src/components/action-sheet/index.ts +0 -3
- package/src/components/action-sheet/types.ts +0 -29
- package/src/components/drawer/Drawer.tsx +0 -100
- package/src/components/drawer/index.ts +0 -2
- package/src/components/drawer/types.ts +0 -13
- package/src/components/navigation/DrawerNavigation.tsx +0 -32
- package/src/components/navigation/DrawerNavigationItem.tsx +0 -23
- package/src/components/navigation/NavigationItem.tsx +0 -79
- package/src/components/navigation/NavigationList.tsx +0 -31
- package/src/components/navigation/TabBar.tsx +0 -31
- package/src/components/navigation/TabBarItem.tsx +0 -79
- package/src/components/navigation/helpers.test.ts +0 -74
- package/src/components/navigation/helpers.ts +0 -81
- package/src/components/navigation/index.ts +0 -16
- package/src/components/navigation/policy.test.ts +0 -140
- package/src/components/navigation/types.ts +0 -66
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import { Box, Inline, Stack } from '../../layout';
|
|
4
|
-
import { ButtonBase } from '../../primitives/button-base';
|
|
5
|
-
import { Text } from '../../primitives/text';
|
|
6
|
-
import type { ActionSheetItemProps } from './types';
|
|
7
|
-
|
|
8
|
-
export function ActionSheetItem({
|
|
9
|
-
label,
|
|
10
|
-
description,
|
|
11
|
-
leading,
|
|
12
|
-
trailing,
|
|
13
|
-
color,
|
|
14
|
-
disabled = false,
|
|
15
|
-
selected = false,
|
|
16
|
-
interactionPolicy = 'enabled',
|
|
17
|
-
onPress,
|
|
18
|
-
testID,
|
|
19
|
-
}: ActionSheetItemProps) {
|
|
20
|
-
return (
|
|
21
|
-
<ButtonBase
|
|
22
|
-
accessibilityRole="button"
|
|
23
|
-
accessibilityState={{ disabled, selected }}
|
|
24
|
-
disabled={disabled}
|
|
25
|
-
interactionPolicy={interactionPolicy}
|
|
26
|
-
onPress={onPress}
|
|
27
|
-
radius="m"
|
|
28
|
-
testID={testID}
|
|
29
|
-
>
|
|
30
|
-
{(state) => (
|
|
31
|
-
<Box
|
|
32
|
-
px="m"
|
|
33
|
-
py="m"
|
|
34
|
-
radius="m"
|
|
35
|
-
style={{
|
|
36
|
-
opacity: state.disabled ? 0.56 : 1,
|
|
37
|
-
}}
|
|
38
|
-
>
|
|
39
|
-
<Inline align="center" gap="m" justify="space-between" wrap="nowrap">
|
|
40
|
-
{leading ? <Box>{leading}</Box> : null}
|
|
41
|
-
<Box flex={1}>
|
|
42
|
-
<Stack gap="xxs">
|
|
43
|
-
<Text color={color} variant="body" weight={selected ? 'semiBold' : 'medium'}>
|
|
44
|
-
{label}
|
|
45
|
-
</Text>
|
|
46
|
-
{description ? (
|
|
47
|
-
<Text emphasis="muted" variant="bodySmall">
|
|
48
|
-
{description}
|
|
49
|
-
</Text>
|
|
50
|
-
) : null}
|
|
51
|
-
</Stack>
|
|
52
|
-
</Box>
|
|
53
|
-
{trailing ? <Box>{trailing}</Box> : null}
|
|
54
|
-
</Inline>
|
|
55
|
-
</Box>
|
|
56
|
-
)}
|
|
57
|
-
</ButtonBase>
|
|
58
|
-
);
|
|
59
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type React from 'react';
|
|
2
|
-
|
|
3
|
-
import type { InteractionPolicy } from '../../interactionPolicy';
|
|
4
|
-
import type { SurfaceColor } from '../../surfaceColor';
|
|
5
|
-
|
|
6
|
-
export interface ActionSheetProps {
|
|
7
|
-
visible: boolean;
|
|
8
|
-
onDismiss?: (() => void) | undefined;
|
|
9
|
-
title?: React.ReactNode;
|
|
10
|
-
description?: React.ReactNode;
|
|
11
|
-
children?: React.ReactNode;
|
|
12
|
-
cancelLabel?: React.ReactNode;
|
|
13
|
-
closeOnBackdrop?: boolean;
|
|
14
|
-
interactionPolicy?: InteractionPolicy;
|
|
15
|
-
testID?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface ActionSheetItemProps {
|
|
19
|
-
label: React.ReactNode;
|
|
20
|
-
description?: React.ReactNode;
|
|
21
|
-
leading?: React.ReactNode;
|
|
22
|
-
trailing?: React.ReactNode;
|
|
23
|
-
color?: SurfaceColor;
|
|
24
|
-
disabled?: boolean;
|
|
25
|
-
selected?: boolean;
|
|
26
|
-
interactionPolicy?: InteractionPolicy;
|
|
27
|
-
onPress?: (() => void) | undefined;
|
|
28
|
-
testID?: string;
|
|
29
|
-
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Pressable, View } from 'react-native';
|
|
3
|
-
|
|
4
|
-
import { FocusScope } from '../../internal/focus/FocusScope';
|
|
5
|
-
import { Portal } from '../../internal/overlay/Portal';
|
|
6
|
-
import { resolvePointerEvents } from '../../internal/resolvePointerEvents';
|
|
7
|
-
import { resolveOverlayAnimation } from '../../internal/resolvers';
|
|
8
|
-
import { Box, Surface } from '../../layout';
|
|
9
|
-
import { useTheme } from '../../theme/ThemeContext';
|
|
10
|
-
import type { DrawerProps } from './types';
|
|
11
|
-
|
|
12
|
-
const boxNonePointerEvents = resolvePointerEvents('box-none');
|
|
13
|
-
|
|
14
|
-
export function Drawer({
|
|
15
|
-
visible,
|
|
16
|
-
onDismiss,
|
|
17
|
-
position = 'right',
|
|
18
|
-
children,
|
|
19
|
-
closeOnBackdrop = true,
|
|
20
|
-
interactionPolicy = 'enabled',
|
|
21
|
-
testID,
|
|
22
|
-
}: DrawerProps) {
|
|
23
|
-
const { theme } = useTheme();
|
|
24
|
-
const animation = resolveOverlayAnimation('drawer');
|
|
25
|
-
const passive = interactionPolicy === 'passive';
|
|
26
|
-
|
|
27
|
-
if (!visible) {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
return (
|
|
32
|
-
<Portal layer="drawer" visible={visible}>
|
|
33
|
-
<View
|
|
34
|
-
{...boxNonePointerEvents.props}
|
|
35
|
-
style={[
|
|
36
|
-
boxNonePointerEvents.style,
|
|
37
|
-
{
|
|
38
|
-
bottom: 0,
|
|
39
|
-
left: 0,
|
|
40
|
-
position: 'absolute',
|
|
41
|
-
right: 0,
|
|
42
|
-
top: 0,
|
|
43
|
-
},
|
|
44
|
-
]}
|
|
45
|
-
>
|
|
46
|
-
<Pressable
|
|
47
|
-
onPress={passive ? undefined : closeOnBackdrop ? onDismiss : undefined}
|
|
48
|
-
style={{
|
|
49
|
-
backgroundColor: theme.semantics.neutral.text,
|
|
50
|
-
bottom: 0,
|
|
51
|
-
left: 0,
|
|
52
|
-
opacity: animation.backdropOpacity,
|
|
53
|
-
position: 'absolute',
|
|
54
|
-
right: 0,
|
|
55
|
-
top: 0,
|
|
56
|
-
}}
|
|
57
|
-
testID={testID ? `${testID}-backdrop` : undefined}
|
|
58
|
-
/>
|
|
59
|
-
<FocusScope
|
|
60
|
-
active={visible}
|
|
61
|
-
onEscape={passive ? undefined : onDismiss}
|
|
62
|
-
testID={testID ? `${testID}-focus` : undefined}
|
|
63
|
-
>
|
|
64
|
-
<Box
|
|
65
|
-
pointerEvents="box-none"
|
|
66
|
-
style={{
|
|
67
|
-
flex: 1,
|
|
68
|
-
justifyContent: 'flex-start',
|
|
69
|
-
}}
|
|
70
|
-
>
|
|
71
|
-
<View
|
|
72
|
-
accessible
|
|
73
|
-
accessibilityViewIsModal
|
|
74
|
-
style={{
|
|
75
|
-
alignSelf: position === 'left' ? 'flex-start' : 'flex-end',
|
|
76
|
-
height: '100%',
|
|
77
|
-
maxWidth: 420,
|
|
78
|
-
width: '88%',
|
|
79
|
-
}}
|
|
80
|
-
>
|
|
81
|
-
<Surface
|
|
82
|
-
p="l"
|
|
83
|
-
style={{
|
|
84
|
-
height: '100%',
|
|
85
|
-
shadowOpacity: 0.14,
|
|
86
|
-
shadowRadius: 14,
|
|
87
|
-
shadowOffset: { width: position === 'left' ? 4 : -4, height: 0 },
|
|
88
|
-
}}
|
|
89
|
-
testID={testID}
|
|
90
|
-
variant="raised"
|
|
91
|
-
>
|
|
92
|
-
{children}
|
|
93
|
-
</Surface>
|
|
94
|
-
</View>
|
|
95
|
-
</Box>
|
|
96
|
-
</FocusScope>
|
|
97
|
-
</View>
|
|
98
|
-
</Portal>
|
|
99
|
-
);
|
|
100
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type React from 'react';
|
|
2
|
-
|
|
3
|
-
import type { InteractionPolicy } from '../../interactionPolicy';
|
|
4
|
-
|
|
5
|
-
export interface DrawerProps {
|
|
6
|
-
visible: boolean;
|
|
7
|
-
onDismiss?: (() => void) | undefined;
|
|
8
|
-
position?: 'left' | 'right';
|
|
9
|
-
children?: React.ReactNode;
|
|
10
|
-
closeOnBackdrop?: boolean;
|
|
11
|
-
interactionPolicy?: InteractionPolicy;
|
|
12
|
-
testID?: string;
|
|
13
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import { Stack } from '../../layout';
|
|
4
|
-
import { DrawerNavigationItem } from './DrawerNavigationItem';
|
|
5
|
-
import type { DrawerNavigationProps } from './types';
|
|
6
|
-
|
|
7
|
-
export function DrawerNavigation({
|
|
8
|
-
items,
|
|
9
|
-
header,
|
|
10
|
-
footer,
|
|
11
|
-
compact = false,
|
|
12
|
-
testID,
|
|
13
|
-
interactionPolicy,
|
|
14
|
-
}: DrawerNavigationProps) {
|
|
15
|
-
return (
|
|
16
|
-
<Stack gap={compact ? 's' : 'm'} testID={testID}>
|
|
17
|
-
{header}
|
|
18
|
-
<Stack gap={compact ? 'xs' : 's'}>
|
|
19
|
-
{items.map((item) => (
|
|
20
|
-
<DrawerNavigationItem
|
|
21
|
-
compact={compact}
|
|
22
|
-
interactionPolicy={interactionPolicy}
|
|
23
|
-
item={item}
|
|
24
|
-
key={item.id}
|
|
25
|
-
testID={testID}
|
|
26
|
-
/>
|
|
27
|
-
))}
|
|
28
|
-
</Stack>
|
|
29
|
-
{footer}
|
|
30
|
-
</Stack>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import { NavigationItem } from './NavigationItem';
|
|
4
|
-
import type { DrawerNavigationItemProps } from './types';
|
|
5
|
-
|
|
6
|
-
export function DrawerNavigationItem({
|
|
7
|
-
item,
|
|
8
|
-
compact = false,
|
|
9
|
-
testID,
|
|
10
|
-
interactionPolicy,
|
|
11
|
-
}: DrawerNavigationItemProps) {
|
|
12
|
-
return (
|
|
13
|
-
<NavigationItem
|
|
14
|
-
compact={compact}
|
|
15
|
-
interactionPolicy={interactionPolicy}
|
|
16
|
-
item={{
|
|
17
|
-
...item,
|
|
18
|
-
accessibilityRole: item.accessibilityRole ?? 'button',
|
|
19
|
-
}}
|
|
20
|
-
testID={testID}
|
|
21
|
-
/>
|
|
22
|
-
);
|
|
23
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View } from 'react-native';
|
|
3
|
-
|
|
4
|
-
import { Box } from '../../layout';
|
|
5
|
-
import { ButtonBase } from '../../primitives/button-base';
|
|
6
|
-
import { Icon } from '../../primitives/icon';
|
|
7
|
-
import { Text } from '../../primitives/text';
|
|
8
|
-
import { useTheme } from '../../theme/ThemeContext';
|
|
9
|
-
import { resolveNavigationAccessibilityState, resolveNavigationItemPresentation } from './helpers';
|
|
10
|
-
import type { NavigationItemProps } from './types';
|
|
11
|
-
|
|
12
|
-
export function NavigationItem({
|
|
13
|
-
item,
|
|
14
|
-
compact = false,
|
|
15
|
-
testID,
|
|
16
|
-
interactionPolicy,
|
|
17
|
-
}: NavigationItemProps) {
|
|
18
|
-
const { theme } = useTheme();
|
|
19
|
-
const active = Boolean(item.active);
|
|
20
|
-
const disabled = Boolean(item.disabled);
|
|
21
|
-
const resolvedTestID = item.testID ?? (testID ? `${testID}-item-${item.id}` : undefined);
|
|
22
|
-
const resolvedAccessibilityState = resolveNavigationAccessibilityState(
|
|
23
|
-
active,
|
|
24
|
-
disabled,
|
|
25
|
-
item.accessibilityState,
|
|
26
|
-
);
|
|
27
|
-
|
|
28
|
-
return (
|
|
29
|
-
<ButtonBase
|
|
30
|
-
accessibilityLabel={item.accessibilityLabel}
|
|
31
|
-
accessibilityRole={item.accessibilityRole ?? 'button'}
|
|
32
|
-
accessibilityState={resolvedAccessibilityState}
|
|
33
|
-
disabled={disabled}
|
|
34
|
-
interactionPolicy={interactionPolicy}
|
|
35
|
-
onPress={item.onPress}
|
|
36
|
-
testID={resolvedTestID}
|
|
37
|
-
>
|
|
38
|
-
{(state) => {
|
|
39
|
-
const presentation = resolveNavigationItemPresentation(theme, {
|
|
40
|
-
active,
|
|
41
|
-
disabled,
|
|
42
|
-
state,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<Box
|
|
47
|
-
px="m"
|
|
48
|
-
py={compact ? 's' : 'm'}
|
|
49
|
-
radius="m"
|
|
50
|
-
style={{
|
|
51
|
-
backgroundColor: presentation.backgroundColor,
|
|
52
|
-
flexDirection: 'row',
|
|
53
|
-
alignItems: 'center',
|
|
54
|
-
opacity: presentation.opacity,
|
|
55
|
-
}}
|
|
56
|
-
>
|
|
57
|
-
{item.icon ? (
|
|
58
|
-
<View style={{ marginRight: theme.spacing.s }}>
|
|
59
|
-
<Icon {...item.icon} color={presentation.contentColor} size={compact ? 's' : 'm'} />
|
|
60
|
-
</View>
|
|
61
|
-
) : null}
|
|
62
|
-
<Box flex={1}>
|
|
63
|
-
<Text
|
|
64
|
-
color={active && !disabled ? 'primary' : undefined}
|
|
65
|
-
emphasis={disabled ? 'muted' : 'default'}
|
|
66
|
-
numberOfLines={1}
|
|
67
|
-
variant={compact ? 'bodySmall' : 'body'}
|
|
68
|
-
weight="medium"
|
|
69
|
-
>
|
|
70
|
-
{item.label}
|
|
71
|
-
</Text>
|
|
72
|
-
</Box>
|
|
73
|
-
{item.badge ? <View style={{ marginLeft: theme.spacing.s }}>{item.badge}</View> : null}
|
|
74
|
-
</Box>
|
|
75
|
-
);
|
|
76
|
-
}}
|
|
77
|
-
</ButtonBase>
|
|
78
|
-
);
|
|
79
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import { Stack } from '../../layout';
|
|
4
|
-
import { NavigationItem } from './NavigationItem';
|
|
5
|
-
import type { NavigationListProps } from './types';
|
|
6
|
-
|
|
7
|
-
export function NavigationList({
|
|
8
|
-
items,
|
|
9
|
-
orientation = 'vertical',
|
|
10
|
-
compact = false,
|
|
11
|
-
testID,
|
|
12
|
-
interactionPolicy,
|
|
13
|
-
}: NavigationListProps) {
|
|
14
|
-
return (
|
|
15
|
-
<Stack
|
|
16
|
-
direction={orientation === 'horizontal' ? 'row' : 'column'}
|
|
17
|
-
gap={compact ? 'xs' : 's'}
|
|
18
|
-
testID={testID}
|
|
19
|
-
>
|
|
20
|
-
{items.map((item) => (
|
|
21
|
-
<NavigationItem
|
|
22
|
-
compact={compact}
|
|
23
|
-
interactionPolicy={interactionPolicy}
|
|
24
|
-
item={item}
|
|
25
|
-
key={item.id}
|
|
26
|
-
testID={testID}
|
|
27
|
-
/>
|
|
28
|
-
))}
|
|
29
|
-
</Stack>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import { Box } from '../../layout';
|
|
4
|
-
import { useTheme } from '../../theme/ThemeContext';
|
|
5
|
-
import { TabBarItem } from './TabBarItem';
|
|
6
|
-
import type { TabBarProps } from './types';
|
|
7
|
-
|
|
8
|
-
export function TabBar({ items, compact = false, testID, interactionPolicy }: TabBarProps) {
|
|
9
|
-
const { theme } = useTheme();
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<Box
|
|
13
|
-
style={{
|
|
14
|
-
flexDirection: 'row',
|
|
15
|
-
borderTopColor: theme.semantics.border.default,
|
|
16
|
-
borderTopWidth: 1,
|
|
17
|
-
}}
|
|
18
|
-
testID={testID}
|
|
19
|
-
>
|
|
20
|
-
{items.map((item) => (
|
|
21
|
-
<TabBarItem
|
|
22
|
-
compact={compact}
|
|
23
|
-
interactionPolicy={interactionPolicy}
|
|
24
|
-
item={item}
|
|
25
|
-
key={item.id}
|
|
26
|
-
testID={testID}
|
|
27
|
-
/>
|
|
28
|
-
))}
|
|
29
|
-
</Box>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View } from 'react-native';
|
|
3
|
-
|
|
4
|
-
import { Box } from '../../layout';
|
|
5
|
-
import { ButtonBase } from '../../primitives/button-base';
|
|
6
|
-
import { Icon } from '../../primitives/icon';
|
|
7
|
-
import { Text } from '../../primitives/text';
|
|
8
|
-
import { useTheme } from '../../theme/ThemeContext';
|
|
9
|
-
import { resolveNavigationAccessibilityState, resolveNavigationItemPresentation } from './helpers';
|
|
10
|
-
import type { TabBarItemProps } from './types';
|
|
11
|
-
|
|
12
|
-
export function TabBarItem({ item, compact = false, testID, interactionPolicy }: TabBarItemProps) {
|
|
13
|
-
const { theme } = useTheme();
|
|
14
|
-
const active = Boolean(item.active);
|
|
15
|
-
const disabled = Boolean(item.disabled);
|
|
16
|
-
const resolvedTestID = item.testID ?? (testID ? `${testID}-item-${item.id}` : undefined);
|
|
17
|
-
const resolvedAccessibilityState = resolveNavigationAccessibilityState(
|
|
18
|
-
active,
|
|
19
|
-
disabled,
|
|
20
|
-
item.accessibilityState,
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<ButtonBase
|
|
25
|
-
accessibilityLabel={item.accessibilityLabel}
|
|
26
|
-
accessibilityRole={item.accessibilityRole ?? 'tab'}
|
|
27
|
-
accessibilityState={resolvedAccessibilityState}
|
|
28
|
-
disabled={disabled}
|
|
29
|
-
interactionPolicy={interactionPolicy}
|
|
30
|
-
onPress={item.onPress}
|
|
31
|
-
style={{ flex: 1 }}
|
|
32
|
-
testID={resolvedTestID}
|
|
33
|
-
>
|
|
34
|
-
{(state) => {
|
|
35
|
-
const presentation = resolveNavigationItemPresentation(theme, {
|
|
36
|
-
active,
|
|
37
|
-
disabled,
|
|
38
|
-
state,
|
|
39
|
-
});
|
|
40
|
-
const contentColor = disabled
|
|
41
|
-
? theme.semantics.content.muted
|
|
42
|
-
: active
|
|
43
|
-
? theme.semantics.action.primary.base
|
|
44
|
-
: theme.semantics.content.muted;
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<Box
|
|
48
|
-
px="m"
|
|
49
|
-
py={compact ? 's' : 'm'}
|
|
50
|
-
style={{
|
|
51
|
-
flex: 1,
|
|
52
|
-
alignItems: 'center',
|
|
53
|
-
justifyContent: 'center',
|
|
54
|
-
backgroundColor: presentation.backgroundColor,
|
|
55
|
-
opacity: presentation.opacity,
|
|
56
|
-
}}
|
|
57
|
-
>
|
|
58
|
-
{item.icon ? (
|
|
59
|
-
<View style={{ marginBottom: item.label ? theme.spacing.xs : 0 }}>
|
|
60
|
-
<Icon {...item.icon} color={contentColor} size={compact ? 's' : 'm'} />
|
|
61
|
-
</View>
|
|
62
|
-
) : null}
|
|
63
|
-
{item.label ? (
|
|
64
|
-
<Text
|
|
65
|
-
color={active && !disabled ? 'primary' : undefined}
|
|
66
|
-
emphasis={active && !disabled ? 'default' : 'muted'}
|
|
67
|
-
numberOfLines={1}
|
|
68
|
-
variant={compact ? 'bodySmall' : 'label'}
|
|
69
|
-
weight="medium"
|
|
70
|
-
>
|
|
71
|
-
{item.label}
|
|
72
|
-
</Text>
|
|
73
|
-
) : null}
|
|
74
|
-
</Box>
|
|
75
|
-
);
|
|
76
|
-
}}
|
|
77
|
-
</ButtonBase>
|
|
78
|
-
);
|
|
79
|
-
}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'bun:test';
|
|
2
|
-
|
|
3
|
-
import { createTheme } from '../../theme/createTheme';
|
|
4
|
-
import { resolveNavigationAccessibilityState, resolveNavigationItemPresentation } from './helpers';
|
|
5
|
-
|
|
6
|
-
describe('navigation helpers', () => {
|
|
7
|
-
it('forces selected and disabled when active/disabled are true', () => {
|
|
8
|
-
expect(
|
|
9
|
-
resolveNavigationAccessibilityState(true, true, {
|
|
10
|
-
selected: false,
|
|
11
|
-
disabled: false,
|
|
12
|
-
}),
|
|
13
|
-
).toEqual({
|
|
14
|
-
selected: true,
|
|
15
|
-
disabled: true,
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('preserves user-provided state when not active/disabled', () => {
|
|
20
|
-
expect(
|
|
21
|
-
resolveNavigationAccessibilityState(false, false, {
|
|
22
|
-
disabled: false,
|
|
23
|
-
selected: false,
|
|
24
|
-
expanded: true,
|
|
25
|
-
}),
|
|
26
|
-
).toEqual({
|
|
27
|
-
disabled: false,
|
|
28
|
-
selected: false,
|
|
29
|
-
expanded: true,
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('resolves active presentation via primary soft semantics', () => {
|
|
34
|
-
const theme = createTheme();
|
|
35
|
-
const state = { pressed: false, hovered: true, focused: false, disabled: false };
|
|
36
|
-
const resolved = resolveNavigationItemPresentation(theme, {
|
|
37
|
-
active: true,
|
|
38
|
-
disabled: false,
|
|
39
|
-
state,
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
expect(resolved.backgroundColor).toBe(theme.semantics.action.primary.softHover);
|
|
43
|
-
expect(resolved.contentColor).toBe(theme.semantics.action.primary.onSoftHoverText);
|
|
44
|
-
expect(resolved.opacity).toBe(1);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('resolves inactive presentation via neutral hover/active semantics', () => {
|
|
48
|
-
const theme = createTheme();
|
|
49
|
-
const state = { pressed: true, hovered: true, focused: false, disabled: false };
|
|
50
|
-
const resolved = resolveNavigationItemPresentation(theme, {
|
|
51
|
-
active: false,
|
|
52
|
-
disabled: false,
|
|
53
|
-
state,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
expect(resolved.backgroundColor).toBe(theme.semantics.neutral.surfaceActive);
|
|
57
|
-
expect(resolved.contentColor).toBe(theme.semantics.content.default);
|
|
58
|
-
expect(resolved.opacity).toBe(1);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('ignores hover/pressed presentation when disabled', () => {
|
|
62
|
-
const theme = createTheme();
|
|
63
|
-
const state = { pressed: true, hovered: true, focused: false, disabled: true };
|
|
64
|
-
const resolved = resolveNavigationItemPresentation(theme, {
|
|
65
|
-
active: true,
|
|
66
|
-
disabled: true,
|
|
67
|
-
state,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
expect(resolved.backgroundColor).toBe(theme.semantics.surface.disabled);
|
|
71
|
-
expect(resolved.contentColor).toBe(theme.semantics.content.disabled);
|
|
72
|
-
expect(resolved.opacity).toBe(1);
|
|
73
|
-
});
|
|
74
|
-
});
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import type { AccessibilityState } from 'react-native';
|
|
2
|
-
|
|
3
|
-
import type { InteractionState } from '../../internal/resolvers/resolveInteractiveState';
|
|
4
|
-
import type { SurfaceTheme } from '../../theme/types';
|
|
5
|
-
|
|
6
|
-
export function resolveNavigationAccessibilityState(
|
|
7
|
-
active: boolean,
|
|
8
|
-
disabled: boolean,
|
|
9
|
-
accessibilityState?: AccessibilityState,
|
|
10
|
-
): AccessibilityState {
|
|
11
|
-
const resolved: AccessibilityState = { ...(accessibilityState ?? {}) };
|
|
12
|
-
|
|
13
|
-
if (active) {
|
|
14
|
-
resolved.selected = true;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (disabled) {
|
|
18
|
-
resolved.disabled = true;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return resolved;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface ResolvedNavigationItemPresentation {
|
|
25
|
-
backgroundColor: string;
|
|
26
|
-
contentColor: string;
|
|
27
|
-
opacity: number;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function resolveNavigationItemPresentation(
|
|
31
|
-
theme: SurfaceTheme,
|
|
32
|
-
{
|
|
33
|
-
active,
|
|
34
|
-
disabled,
|
|
35
|
-
state,
|
|
36
|
-
}: {
|
|
37
|
-
active: boolean;
|
|
38
|
-
disabled: boolean;
|
|
39
|
-
state: InteractionState;
|
|
40
|
-
},
|
|
41
|
-
): ResolvedNavigationItemPresentation {
|
|
42
|
-
const interactionState = disabled ? { ...state, hovered: false, pressed: false } : state;
|
|
43
|
-
|
|
44
|
-
if (disabled) {
|
|
45
|
-
return {
|
|
46
|
-
backgroundColor: theme.semantics.surface.disabled,
|
|
47
|
-
contentColor: theme.semantics.content.disabled,
|
|
48
|
-
opacity: 1,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const contentColor = active
|
|
53
|
-
? interactionState.pressed
|
|
54
|
-
? theme.semantics.action.primary.onSoftActiveText
|
|
55
|
-
: interactionState.hovered
|
|
56
|
-
? theme.semantics.action.primary.onSoftHoverText
|
|
57
|
-
: theme.semantics.action.primary.onSoftText
|
|
58
|
-
: theme.semantics.content.default;
|
|
59
|
-
|
|
60
|
-
if (active) {
|
|
61
|
-
return {
|
|
62
|
-
backgroundColor: interactionState.pressed
|
|
63
|
-
? theme.semantics.action.primary.softActive
|
|
64
|
-
: interactionState.hovered
|
|
65
|
-
? theme.semantics.action.primary.softHover
|
|
66
|
-
: theme.semantics.action.primary.softBg,
|
|
67
|
-
contentColor,
|
|
68
|
-
opacity: 1,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
backgroundColor: interactionState.pressed
|
|
74
|
-
? theme.semantics.neutral.surfaceActive
|
|
75
|
-
: interactionState.hovered
|
|
76
|
-
? theme.semantics.neutral.surfaceHover
|
|
77
|
-
: 'transparent',
|
|
78
|
-
contentColor,
|
|
79
|
-
opacity: 1,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export { DrawerNavigation } from './DrawerNavigation';
|
|
2
|
-
export { DrawerNavigationItem } from './DrawerNavigationItem';
|
|
3
|
-
export { NavigationItem } from './NavigationItem';
|
|
4
|
-
export { NavigationList } from './NavigationList';
|
|
5
|
-
export { TabBar } from './TabBar';
|
|
6
|
-
export { TabBarItem } from './TabBarItem';
|
|
7
|
-
export type {
|
|
8
|
-
DrawerNavigationItemProps,
|
|
9
|
-
DrawerNavigationProps,
|
|
10
|
-
NavigationItemIcon,
|
|
11
|
-
NavigationItemProps,
|
|
12
|
-
NavigationItemSpec,
|
|
13
|
-
NavigationListProps,
|
|
14
|
-
TabBarItemProps,
|
|
15
|
-
TabBarProps,
|
|
16
|
-
} from './types';
|