forked from microsoft/fluentui-react-native
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathButton.tsx
115 lines (106 loc) · 4.37 KB
/
Button.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/** @jsxRuntime classic */
/** @jsx withSlots */
import * as React from 'react';
import { View } from 'react-native';
import { filterViewProps } from '@fluentui-react-native/adapters';
import { Icon, createIconProps } from '@fluentui-react-native/icon';
import { useAsPressable, useKeyProps, useViewCommandFocus, useOnPressWithFocus } from '@fluentui-react-native/interactive-hooks';
import { Text } from '@fluentui-react-native/text';
import { backgroundColorTokens, borderTokens, textTokens, foregroundColorTokens, getPaletteFromTheme } from '@fluentui-react-native/tokens';
import type { ISlots } from '@uifabricshared/foundation-composable';
import { withSlots } from '@uifabricshared/foundation-composable';
import type { IUseComposeStyling } from '@uifabricshared/foundation-compose';
import { compose } from '@uifabricshared/foundation-compose';
import { mergeSettings } from '@uifabricshared/foundation-settings';
import { settings } from './Button.settings';
import type { IButtonSlotProps, IButtonState, IButtonProps, IButtonRenderData, IButtonType } from './Button.types';
import { buttonName } from './Button.types';
/**
* @deprecated This component is deprecated in favor of ButtonV1. This Button will be removed when the package moves to 1.0.0.
* At that point, ButtonV1 will be renamed to Button. Please see MIGRATION.md for details on how to move to the new Button.
*/
export const Button = compose<IButtonType>({
displayName: buttonName,
usePrepareProps: (userProps: IButtonProps, useStyling: IUseComposeStyling<IButtonType>) => {
const defaultComponentRef = React.useRef(null);
const {
icon,
startIcon,
endIcon,
content,
onAccessibilityTap = userProps.onClick,
accessibilityLabel = userProps.content,
componentRef = defaultComponentRef,
testID,
onClick,
...rest
} = userProps;
// Ensure focus is placed on button after click
const onPressWithFocus = useOnPressWithFocus(componentRef, onClick);
// attach the pressable state handlers
const pressable = useAsPressable({ ...rest, onPress: onPressWithFocus });
const onKeyProps = useKeyProps(onClick, ' ', 'Enter');
// set up state
const state: IButtonState = {
info: {
...pressable.state,
disabled: !!userProps.disabled,
content: !!content,
startIcon: !!startIcon || !!icon,
endIcon: !!endIcon,
},
};
const buttonRef = useViewCommandFocus(componentRef);
// grab the styling information, referencing the state as well as the props
const styleProps = useStyling(userProps, (override: string) => state.info[override] || userProps[override]);
// create the merged slot props
const slotProps = mergeSettings<IButtonSlotProps>(styleProps, {
root: {
...pressable.props,
ref: buttonRef,
onAccessibilityTap: onAccessibilityTap,
accessibilityLabel: accessibilityLabel,
accessibilityState: { disabled: state.info.disabled },
...onKeyProps,
testID,
},
content: { children: content },
startIcon: createIconProps(startIcon || icon),
endIcon: createIconProps(endIcon),
});
return { slotProps, state };
},
settings,
render: (Slots: ISlots<IButtonSlotProps>, renderData: IButtonRenderData, ...children: React.ReactNode[]) => {
const info = renderData.state!.info;
return (
<Slots.root>
<Slots.borderWrapper>
<Slots.stack>
{info.startIcon && <Slots.startIcon />}
{info.content && <Slots.content />}
{children}
{info.endIcon && <Slots.endIcon />}
</Slots.stack>
</Slots.borderWrapper>
</Slots.root>
);
},
slots: {
root: View,
stack: { slotType: View, filter: filterViewProps },
borderWrapper: { slotType: View, filter: filterViewProps },
startIcon: { slotType: Icon as React.ComponentType },
content: Text,
endIcon: { slotType: Icon as React.ComponentType },
},
styles: {
root: [backgroundColorTokens, borderTokens],
stack: [],
borderWrapper: [{ source: 'wrapperBorderColor', lookup: getPaletteFromTheme, target: 'borderColor' }],
startIcon: [{ source: 'iconColor', lookup: getPaletteFromTheme, target: 'color' }],
content: [textTokens, foregroundColorTokens],
endIcon: [{ source: 'iconColor', lookup: getPaletteFromTheme, target: 'color' }],
},
});
export default Button;