react-native-macos
Version:
A framework for building native macOS apps using React
248 lines (236 loc) • 6.54 kB
JavaScript
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule Button
* @flow
*/
'use strict';
const ColorPropType = require('ColorPropType');
const Platform = require('Platform');
const React = require('React');
const PropTypes = require('prop-types');
const StyleSheet = require('StyleSheet');
const Text = require('Text');
const TouchableNativeFeedback = require('TouchableNativeFeedback');
const TouchableOpacity = require('TouchableOpacity');
const View = require('View');
const invariant = require('fbjs/lib/invariant');
const requireNativeComponent = require('requireNativeComponent');
const NativeModules = require('NativeModules');
/**
* A basic button component that should render nicely on any platform. Supports
* a minimal level of customization.
*
* <center><img src="img/buttonExample.png"></img></center>
*
* If this button doesn't look right for your app, you can build your own
* button using [TouchableOpacity](docs/touchableopacity.html)
* or [TouchableNativeFeedback](docs/touchablenativefeedback.html).
* For inspiration, look at the [source code for this button component](https://github.com/facebook/react-native/blob/master/Libraries/Components/Button.js).
* Or, take a look at the [wide variety of button components built by the community](https://js.coach/react-native?search=button).
*
* Example usage:
*
* ```
* <Button
* onPress={onPressLearnMore}
* title="Learn More"
* color="#841584"
* accessibilityLabel="Learn more about this purple button"
* />
* ```
*
*/
class Button extends React.Component {
static propTypes = {
/**
* Text to display inside the button
*/
title: PropTypes.string,
/**
* Text to display for blindness accessibility features
*/
accessibilityLabel: PropTypes.string,
/**
* Color of the text (iOS), or background color of the button (Android)
*/
color: ColorPropType,
/**
* If true, disable all interactions for this component.
*/
disabled: PropTypes.bool,
/**
* Handler to be called when the user taps the button
*/
onPress: PropTypes.func,
/**
* Used to locate this view in end-to-end tests.
*/
testID: PropTypes.string,
/**
* macOS Specific
*/
type: PropTypes.oneOf([
'momentaryLight',
'push',
'switch',
'toggle',
'radio',
'onOff',
'accelerator',
]),
/*
* https://developer.apple.com/library/mac/documentation/UserExperience/Conceptual/OSXHIGuidelines/SystemProvided.html
*/
systemImage: PropTypes.string,
alternateTitle: PropTypes.string,
image: PropTypes.oneOfType([
PropTypes.shape({
uri: PropTypes.string,
}),
// Opaque type returned by require('./image.jpg')
PropTypes.number,
]),
alternateImage: PropTypes.oneOfType([
PropTypes.shape({
uri: PropTypes.string,
}),
// Opaque type returned by require('./image.jpg')
PropTypes.number,
]),
bezelStyle: PropTypes.oneOf([
'rounded',
'regularSquare',
'thickSquare',
'thickerSquare',
'disclosure',
'shadowlessSquare',
'circular',
'texturedSquare',
'helpButton',
'smallSquare',
'texturedRounded',
'roundRect',
'recessed',
'roundedDisclosure',
'inline',
]),
toolTip: PropTypes.string,
allowsMixedState: PropTypes.bool,
state: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]),
style: PropTypes.any,
};
render() {
const {
accessibilityLabel,
color,
onPress,
title,
disabled,
testID,
} = this.props;
const buttonStyles = [styles.button];
const textStyles = [styles.text];
const Touchable = Platform.OS === 'android'
? TouchableNativeFeedback
: TouchableOpacity;
if (color && Platform.OS === 'ios') {
textStyles.push({ color: color });
} else if (color) {
buttonStyles.push({ backgroundColor: color });
}
if (disabled) {
buttonStyles.push(styles.buttonDisabled);
textStyles.push(styles.textDisabled);
}
if (Platform.OS === 'ios' || Platform.OS === 'android') {
invariant(
typeof title === 'string',
'The title prop of a Button must be a string'
);
}
const formattedTitle = Platform.OS === 'android'
? title.toUpperCase()
: title;
const accessibilityTraits = ['button'];
if (disabled) {
accessibilityTraits.push('disabled');
}
if (Platform.OS === 'macos') {
return (
<RCTButton {...this.props} style={[styles.button, this.props.style]} />
);
}
return (
<Touchable
accessibilityComponentType="button"
accessibilityLabel={accessibilityLabel}
accessibilityTraits={accessibilityTraits}
testID={testID}
disabled={disabled}
onPress={onPress}>
<View style={buttonStyles}>
<Text style={textStyles} disabled={disabled}>{formattedTitle}</Text>
</View>
</Touchable>
);
}
}
// Material design blue from https://material.google.com/style/color.html#color-color-palette
let defaultBlue = '#2196F3';
if (Platform.OS === 'ios') {
// Measured default tintColor from iOS 10
defaultBlue = '#0C42FD';
}
const RCTButton = requireNativeComponent('RCTButton', Button, {
nativeOnly: {},
});
const styles = StyleSheet.create({
button: Platform.select({
ios: {},
android: {
elevation: 4,
backgroundColor: defaultBlue,
borderRadius: 2,
},
macos: {
height: NativeModules.ButtonManager.ComponentHeight,
width: NativeModules.ButtonManager.ComponentWidth,
},
}),
text: Platform.select({
ios: {
color: defaultBlue,
textAlign: 'center',
padding: 8,
fontSize: 18,
},
android: {
textAlign: 'center',
color: 'white',
padding: 8,
fontWeight: '500',
},
}),
buttonDisabled: Platform.select({
ios: {},
android: {
elevation: 0,
backgroundColor: '#dfdfdf',
},
}),
textDisabled: Platform.select({
ios: {
color: '#cdcdcd',
},
android: {
color: '#a1a1a1',
},
}),
});
module.exports = Button;