Merge pull request #2932 from saghul/refactor-bottomsheet
[RN] Refactor SimpleBottomSheet
This commit is contained in:
commit
ab7e572162
|
@ -0,0 +1,84 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import React, { Component, type Node } from 'react';
|
||||||
|
import { Modal, TouchableWithoutFeedback, View } from 'react-native';
|
||||||
|
|
||||||
|
import { bottomSheetStyles as styles } from './styles';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of {@code BottomSheet}'s React {@code Component} prop types.
|
||||||
|
*/
|
||||||
|
type Props = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The children to be displayed within this component.
|
||||||
|
*/
|
||||||
|
children: Node,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for the cancel event, which happens when the user dismisses
|
||||||
|
* the sheet.
|
||||||
|
*/
|
||||||
|
onCancel: ?Function
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A component emulating Android's BottomSheet. For all intents and purposes,
|
||||||
|
* this component has been designed to work and behave as a {@code Dialog}.
|
||||||
|
*/
|
||||||
|
export default class BottomSheet extends Component<Props> {
|
||||||
|
/**
|
||||||
|
* Initializes a new {@code BottomSheet} instance.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this._onCancel = this._onCancel.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements React's {@link Component#render()}.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
* @returns {ReactElement}
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
return [
|
||||||
|
<View
|
||||||
|
key = 'overlay'
|
||||||
|
style = { styles.overlay } />,
|
||||||
|
<Modal
|
||||||
|
animationType = { 'slide' }
|
||||||
|
key = 'modal'
|
||||||
|
onRequestClose = { this._onCancel }
|
||||||
|
transparent = { true }
|
||||||
|
visible = { true }>
|
||||||
|
<View style = { styles.container }>
|
||||||
|
<TouchableWithoutFeedback
|
||||||
|
onPress = { this._onCancel } >
|
||||||
|
<View style = { styles.backdrop } />
|
||||||
|
</TouchableWithoutFeedback>
|
||||||
|
<View style = { styles.sheet }>
|
||||||
|
{ this.props.children }
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
</Modal>
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
_onCancel: () => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels the dialog by calling the onCancel prop callback.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_onCancel() {
|
||||||
|
const { onCancel } = this.props;
|
||||||
|
|
||||||
|
onCancel && onCancel();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,206 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
|
||||||
import {
|
|
||||||
Modal,
|
|
||||||
Text,
|
|
||||||
TouchableHighlight,
|
|
||||||
TouchableWithoutFeedback,
|
|
||||||
View
|
|
||||||
} from 'react-native';
|
|
||||||
import { connect } from 'react-redux';
|
|
||||||
|
|
||||||
import { Icon } from '../../font-icons';
|
|
||||||
|
|
||||||
import { simpleBottomSheet as styles } from './styles';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Underlay color for the buttons on the sheet.
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
const BUTTON_UNDERLAY_COLOR = '#eee';
|
|
||||||
|
|
||||||
type Option = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the icon which will be rendered on the right.
|
|
||||||
*/
|
|
||||||
iconName: string,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if the element is selected (will be highlighted in blue),
|
|
||||||
* false otherwise.
|
|
||||||
*/
|
|
||||||
selected: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Text which will be rendered in the row.
|
|
||||||
*/
|
|
||||||
text: string
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of {@code SimpleBottomSheet}'s React {@code Component} prop types.
|
|
||||||
*/
|
|
||||||
type Props = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for the cancel event, which happens when the user dismisses
|
|
||||||
* the sheet.
|
|
||||||
*/
|
|
||||||
onCancel: Function,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for the event when an option has been selected in the sheet.
|
|
||||||
*/
|
|
||||||
onSubmit: Function,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Array of options which will be rendered as rows.
|
|
||||||
*/
|
|
||||||
options: Array<Option>
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A component emulating Android's BottomSheet, in a simplified form.
|
|
||||||
* It supports text options with an icon, which the user can tap. The style has
|
|
||||||
* been implemented following the Material Design guidelines for bottom
|
|
||||||
* sheets: https://material.io/guidelines/components/bottom-sheets.html
|
|
||||||
*
|
|
||||||
* For all intents and purposes, this component has been designed to work and
|
|
||||||
* behave as a {@code Dialog}.
|
|
||||||
*/
|
|
||||||
class SimpleBottomSheet extends Component<Props> {
|
|
||||||
/**
|
|
||||||
* Initializes a new {@code SimpleBottomSheet} instance.
|
|
||||||
*
|
|
||||||
* @param {Object} props - The read-only React {@code Component} props with
|
|
||||||
* which the new instance is to be initialized.
|
|
||||||
*/
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this._onButtonPress = this._onButtonPress.bind(this);
|
|
||||||
this._onCancel = this._onCancel.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements React's {@link Component#render()}.
|
|
||||||
*
|
|
||||||
* @inheritdoc
|
|
||||||
* @returns {ReactElement}
|
|
||||||
*/
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
animationType = { 'slide' }
|
|
||||||
onRequestClose = { this._onCancel }
|
|
||||||
transparent = { true }
|
|
||||||
visible = { true }>
|
|
||||||
<View style = { styles.container }>
|
|
||||||
<TouchableWithoutFeedback
|
|
||||||
onPress = { this._onCancel } >
|
|
||||||
<View style = { styles.overlay } />
|
|
||||||
</TouchableWithoutFeedback>
|
|
||||||
<View style = { styles.sheet }>
|
|
||||||
<View style = { styles.rowsWrapper }>
|
|
||||||
{ this._renderOptions() }
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</Modal>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onButtonPress: (?Object) => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle pressing of one of the options. The sheet will be hidden and the
|
|
||||||
* onSubmit prop will be called with the selected option.
|
|
||||||
*
|
|
||||||
* @param {Object} option - The option which the user selected.
|
|
||||||
* @private
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
_onButtonPress(option) {
|
|
||||||
const { onSubmit } = this.props;
|
|
||||||
|
|
||||||
onSubmit && onSubmit(option);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onCancel: () => void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancels the dialog by calling the onCancel prop callback.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
_onCancel() {
|
|
||||||
const { onCancel } = this.props;
|
|
||||||
|
|
||||||
onCancel && onCancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders sheet rows based on the options prop.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @returns {Array} - Array of rows to be rendered in the sheet.
|
|
||||||
*/
|
|
||||||
_renderOptions() {
|
|
||||||
return this.props.options.map(
|
|
||||||
(option, index) => this._renderRow(option, index));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders a single row of the sheet.
|
|
||||||
*
|
|
||||||
* @param {Object} option - Single option which needs to be rendered.
|
|
||||||
* @param {int} index - Option index, used as a key for React.
|
|
||||||
* @private
|
|
||||||
* @returns {ReactElement} - A row element with an icon and text.
|
|
||||||
*/
|
|
||||||
_renderRow(option, index) {
|
|
||||||
const { iconName, selected, text } = option;
|
|
||||||
const selectedStyle = selected ? styles.rowSelectedText : {};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TouchableHighlight
|
|
||||||
key = { index }
|
|
||||||
|
|
||||||
// TODO The following disables an eslint error alerting about a
|
|
||||||
// known potential/theoretical performance pernalty:
|
|
||||||
//
|
|
||||||
// A bind call or arrow function in a JSX prop will create a
|
|
||||||
// brand new function on every single render. This is bad for
|
|
||||||
// performance, as it will result in the garbage collector being
|
|
||||||
// invoked way more than is necessary. It may also cause
|
|
||||||
// unnecessary re-renders if a brand new function is passed as a
|
|
||||||
// prop to a component that uses reference equality check on the
|
|
||||||
// prop to determine if it should update.
|
|
||||||
//
|
|
||||||
// I'm not addressing the potential/theoretical performance
|
|
||||||
// penalty at the time of this writing because it doesn't seem
|
|
||||||
// to me that it's a practical performance penalty in the case.
|
|
||||||
//
|
|
||||||
// eslint-disable-next-line react/jsx-no-bind
|
|
||||||
onPress = { this._onButtonPress.bind(this, option) }
|
|
||||||
underlayColor = { BUTTON_UNDERLAY_COLOR } >
|
|
||||||
<View style = { styles.row } >
|
|
||||||
<Icon
|
|
||||||
name = { iconName }
|
|
||||||
style = { [ styles.rowIcon, selectedStyle ] } />
|
|
||||||
<View style = { styles.rowPadding } />
|
|
||||||
<Text style = { [ styles.rowText, selectedStyle ] } >
|
|
||||||
{ text }
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
</TouchableHighlight>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect()(SimpleBottomSheet);
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
export { default as BottomSheet } from './BottomSheet';
|
||||||
export { default as DialogContainer } from './DialogContainer';
|
export { default as DialogContainer } from './DialogContainer';
|
||||||
export { default as Dialog } from './Dialog';
|
export { default as Dialog } from './Dialog';
|
||||||
export { default as SimpleBottomSheet } from './SimpleBottomSheet';
|
|
||||||
export { default as StatelessDialog } from './StatelessDialog';
|
export { default as StatelessDialog } from './StatelessDialog';
|
||||||
|
|
|
@ -21,21 +21,36 @@ export const dialog = createStyleSheet({
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The React {@code Component} styles of {@code SimpleBottomSheet}. These have
|
* The React {@code Component} styles of {@code BottomSheet}. These have
|
||||||
* been implemented as per the Material Design guidelines:
|
* been implemented as per the Material Design guidelines:
|
||||||
* {@link https://material.io/guidelines/components/bottom-sheets.html}.
|
* {@link https://material.io/guidelines/components/bottom-sheets.html}.
|
||||||
*/
|
*/
|
||||||
export const simpleBottomSheet = createStyleSheet({
|
export const bottomSheetStyles = createStyleSheet({
|
||||||
|
/**
|
||||||
|
* Style for a backdrop which dims the view in the background. This view
|
||||||
|
* will also be clickable. The backgroundColor is applied to the overlay
|
||||||
|
* view instead, so the modal animation doesn't affect the backdrop.
|
||||||
|
*/
|
||||||
|
backdrop: {
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0,
|
||||||
|
top: 0
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Style for the container of the sheet.
|
* Style for the container of the sheet.
|
||||||
*/
|
*/
|
||||||
container: {
|
container: {
|
||||||
|
alignItems: 'flex-end',
|
||||||
flex: 1,
|
flex: 1,
|
||||||
flexDirection: 'row'
|
flexDirection: 'row',
|
||||||
|
justifyContent: 'center'
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Style for a backdrop overlay covering the screen while the
|
* Style for an overlay on top of which the sheet will be displayed.
|
||||||
*/
|
*/
|
||||||
overlay: {
|
overlay: {
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
backgroundColor: 'rgba(0, 0, 0, 0.8)',
|
||||||
|
@ -46,57 +61,13 @@ export const simpleBottomSheet = createStyleSheet({
|
||||||
top: 0
|
top: 0
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Base style for each row.
|
|
||||||
*/
|
|
||||||
row: {
|
|
||||||
alignItems: 'center',
|
|
||||||
flexDirection: 'row',
|
|
||||||
height: 48
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Style for the {@code Icon} element in a row.
|
|
||||||
*/
|
|
||||||
rowIcon: {
|
|
||||||
fontSize: 24
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper for adding some padding between the icon and text in a row.
|
|
||||||
*/
|
|
||||||
rowPadding: {
|
|
||||||
width: 32
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Style for a row which is marked as selected.
|
|
||||||
*/
|
|
||||||
rowSelectedText: {
|
|
||||||
color: ColorPalette.blue
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Style for the {@code Text} element in a row.
|
|
||||||
*/
|
|
||||||
rowText: {
|
|
||||||
fontSize: 16
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper for all rows, it adds a margin to the sheet container.
|
|
||||||
*/
|
|
||||||
rowsWrapper: {
|
|
||||||
marginHorizontal: 16,
|
|
||||||
marginVertical: 8
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bottom sheet's base style.
|
* Bottom sheet's base style.
|
||||||
*/
|
*/
|
||||||
sheet: {
|
sheet: {
|
||||||
alignSelf: 'flex-end',
|
flex: 1,
|
||||||
backgroundColor: ColorPalette.white,
|
backgroundColor: ColorPalette.white,
|
||||||
flex: 1
|
paddingHorizontal: 16,
|
||||||
|
paddingVertical: 8
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,15 +2,45 @@
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { NativeModules } from 'react-native';
|
import { NativeModules, Text, TouchableHighlight, View } from 'react-native';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
import { hideDialog, SimpleBottomSheet } from '../../../base/dialog';
|
import { hideDialog, BottomSheet } from '../../../base/dialog';
|
||||||
import { translate } from '../../../base/i18n';
|
import { translate } from '../../../base/i18n';
|
||||||
|
|
||||||
|
import { Icon } from '../../../base/font-icons';
|
||||||
|
|
||||||
|
import styles, { UNDERLAY_COLOR } from './styles';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code PasswordRequiredPrompt}'s React {@code Component} prop types.
|
* Type definition for a single entry in the device list.
|
||||||
|
*/
|
||||||
|
type Device = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the icon which will be rendered on the right.
|
||||||
|
*/
|
||||||
|
iconName: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the element is selected (will be highlighted in blue),
|
||||||
|
* false otherwise.
|
||||||
|
*/
|
||||||
|
selected: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text which will be rendered in the row.
|
||||||
|
*/
|
||||||
|
text: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Device type.
|
||||||
|
*/
|
||||||
|
type: string
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code AudioRoutePickerDialog}'s React {@code Component} prop types.
|
||||||
*/
|
*/
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
||||||
|
@ -25,12 +55,15 @@ type Props = {
|
||||||
t: Function
|
t: Function
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code AudioRoutePickerDialog}'s React {@code Component} state types.
|
||||||
|
*/
|
||||||
type State = {
|
type State = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of available devices.
|
* Array of available devices.
|
||||||
*/
|
*/
|
||||||
devices: Array<string>
|
devices: Array<Device>
|
||||||
};
|
};
|
||||||
|
|
||||||
const { AudioMode } = NativeModules;
|
const { AudioMode } = NativeModules;
|
||||||
|
@ -87,12 +120,11 @@ class AudioRoutePickerDialog extends Component<Props, State> {
|
||||||
* @param {Props} props - The read-only React {@code Component} props with
|
* @param {Props} props - The read-only React {@code Component} props with
|
||||||
* which the new instance is to be initialized.
|
* which the new instance is to be initialized.
|
||||||
*/
|
*/
|
||||||
constructor(props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
// Bind event handlers so they are only bound once per instance.
|
// Bind event handlers so they are only bound once per instance.
|
||||||
this._onCancel = this._onCancel.bind(this);
|
this._onCancel = this._onCancel.bind(this);
|
||||||
this._onSubmit = this._onSubmit.bind(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -146,19 +178,49 @@ class AudioRoutePickerDialog extends Component<Props, State> {
|
||||||
this._hide();
|
this._hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onSubmit: (?Object) => void;
|
_onSelectDeviceFn: (Device) => Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the selection of a device on the sheet. The selected device will
|
* Builds and returns a function which handles the selection of a device
|
||||||
* be used by {@code AudioMode}.
|
* on the sheet. The selected device will be used by {@code AudioMode}.
|
||||||
*
|
*
|
||||||
* @param {Object} device - Object representing the selected device.
|
* @param {Device} device - Object representing the selected device.
|
||||||
* @private
|
* @private
|
||||||
* @returns {void}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
_onSubmit(device) {
|
_onSelectDeviceFn(device: Device) {
|
||||||
this._hide();
|
return () => {
|
||||||
AudioMode.setAudioDevice(device.type);
|
this._hide();
|
||||||
|
AudioMode.setAudioDevice(device.type);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a single device.
|
||||||
|
*
|
||||||
|
* @param {Device} device - Object representing a single device.
|
||||||
|
* @private
|
||||||
|
* @returns {ReactElement}
|
||||||
|
*/
|
||||||
|
_renderDevice(device: Device) {
|
||||||
|
const { iconName, selected, text } = device;
|
||||||
|
const selectedStyle = selected ? styles.selectedText : {};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableHighlight
|
||||||
|
key = { device.type }
|
||||||
|
onPress = { this._onSelectDeviceFn(device) }
|
||||||
|
underlayColor = { UNDERLAY_COLOR } >
|
||||||
|
<View style = { styles.deviceRow } >
|
||||||
|
<Icon
|
||||||
|
name = { iconName }
|
||||||
|
style = { [ styles.deviceIcon, selectedStyle ] } />
|
||||||
|
<Text style = { [ styles.deviceText, selectedStyle ] } >
|
||||||
|
{ text }
|
||||||
|
</Text>
|
||||||
|
</View>
|
||||||
|
</TouchableHighlight>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -175,10 +237,9 @@ class AudioRoutePickerDialog extends Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SimpleBottomSheet
|
<BottomSheet onCancel = { this._onCancel }>
|
||||||
onCancel = { this._onCancel }
|
{ this.state.devices.map(this._renderDevice, this) }
|
||||||
onSubmit = { this._onSubmit }
|
</BottomSheet>
|
||||||
options = { devices } />
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
|
import { ColorPalette, createStyleSheet } from '../../../base/styles';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Underlay color for the buttons on the sheet.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const UNDERLAY_COLOR = '#eee';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The React {@code Component} styles of {@code AudioRoutePickerDialog}.
|
||||||
|
*
|
||||||
|
* It uses a {@code BottomSheet} and these have been implemented as per the
|
||||||
|
* Material Design guidelines:
|
||||||
|
* {@link https://material.io/guidelines/components/bottom-sheets.html}.
|
||||||
|
*/
|
||||||
|
export default createStyleSheet({
|
||||||
|
/**
|
||||||
|
* Base style for each row.
|
||||||
|
*/
|
||||||
|
deviceRow: {
|
||||||
|
alignItems: 'center',
|
||||||
|
flexDirection: 'row',
|
||||||
|
height: 48
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Style for the {@code Icon} element in a row.
|
||||||
|
*/
|
||||||
|
deviceIcon: {
|
||||||
|
fontSize: 24
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Style for the {@code Text} element in a row.
|
||||||
|
*/
|
||||||
|
deviceText: {
|
||||||
|
fontSize: 16,
|
||||||
|
marginLeft: 32
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Style for a row which is marked as selected.
|
||||||
|
*/
|
||||||
|
selectedText: {
|
||||||
|
color: ColorPalette.blue
|
||||||
|
}
|
||||||
|
});
|
Loading…
Reference in New Issue