You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RichTextToolbar.js 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import React, { Component } from 'react';
  2. import PropTypes from 'prop-types';
  3. import {FlatList, View, TouchableOpacity, Image, StyleSheet} from 'react-native';
  4. import {actions} from './const';
  5. const defaultActions = [
  6. actions.insertImage,
  7. actions.setBold,
  8. actions.setItalic,
  9. actions.insertBulletsList,
  10. actions.insertOrderedList,
  11. actions.insertLink
  12. ];
  13. function getDefaultIcon() {
  14. const texts = {};
  15. texts[actions.insertImage] = require('../img/icon_format_media.png');
  16. texts[actions.setBold] = require('../img/icon_format_bold.png');
  17. texts[actions.setItalic] = require('../img/icon_format_italic.png');
  18. texts[actions.insertBulletsList] = require('../img/icon_format_ul.png');
  19. texts[actions.insertOrderedList] = require('../img/icon_format_ol.png');
  20. texts[actions.insertLink] = require('../img/icon_format_link.png');
  21. return texts;
  22. }
  23. export default class RichTextToolbar extends Component {
  24. static propTypes = {
  25. getEditor: PropTypes.func.isRequired,
  26. actions: PropTypes.array,
  27. onPressAddLink: PropTypes.func,
  28. onPressAddImage: PropTypes.func,
  29. selectedButtonStyle: PropTypes.object,
  30. iconTint: PropTypes.any,
  31. selectedIconTint: PropTypes.any,
  32. unselectedButtonStyle: PropTypes.object,
  33. renderAction: PropTypes.func,
  34. iconMap: PropTypes.object,
  35. };
  36. constructor(props) {
  37. super(props);
  38. const actions = this.props.actions ? this.props.actions : defaultActions;
  39. this.state = {
  40. editor: undefined,
  41. selectedItems: [],
  42. actions,
  43. dataSet: this.getRows(actions, [])
  44. };
  45. }
  46. getRows(actions, selectedItems) {
  47. return actions.map((action) => {return {action, selected: selectedItems.includes(action)};});
  48. }
  49. componentDidMount() {
  50. const editor = this.props.getEditor();
  51. if (!editor) {
  52. throw new Error('Toolbar has no editor!');
  53. } else {
  54. editor.registerToolbar((selectedItems) => this.setSelectedItems(selectedItems));
  55. this.setState({editor});
  56. }
  57. }
  58. setSelectedItems(selectedItems) {
  59. if (selectedItems !== this.state.selectedItems) {
  60. this.setState({
  61. selectedItems,
  62. dataSet: this.getRows(this.state.actions, selectedItems)
  63. });
  64. }
  65. }
  66. _getButtonSelectedStyle() {
  67. return this.props.selectedButtonStyle ? this.props.selectedButtonStyle : styles.defaultSelectedButton;
  68. }
  69. _getButtonUnselectedStyle() {
  70. return this.props.unselectedButtonStyle ? this.props.unselectedButtonStyle : styles.defaultUnselectedButton;
  71. }
  72. _getButtonIcon(action) {
  73. if (this.props.iconMap && this.props.iconMap[action]) {
  74. return this.props.iconMap[action];
  75. } else if (getDefaultIcon()[action]){
  76. return getDefaultIcon()[action];
  77. } else {
  78. return undefined;
  79. }
  80. }
  81. _defaultRenderAction(action, selected) {
  82. const icon = this._getButtonIcon(action);
  83. return (
  84. <TouchableOpacity
  85. key={action}
  86. style={[
  87. {height: 50, width: 50, justifyContent: 'center'},
  88. selected ? this._getButtonSelectedStyle() : this._getButtonUnselectedStyle()
  89. ]}
  90. onPress={() => this._onPress(action)}
  91. >
  92. {icon ? <Image source={icon} style={{tintColor: selected ? this.props.selectedIconTint : this.props.iconTint}}/> : null}
  93. </TouchableOpacity>
  94. );
  95. }
  96. _renderAction(action, selected) {
  97. return this.props.renderAction ?
  98. this.props.renderAction(action, selected) :
  99. this._defaultRenderAction(action, selected);
  100. }
  101. render() {
  102. return (
  103. <View
  104. style={[{height: 50, backgroundColor: '#D3D3D3', alignItems: 'center'}, this.props.style]}
  105. >
  106. <FlatList
  107. data={this.state.dataSet}
  108. numColumns={this.state.actions.length}
  109. renderItem={(item) => this._renderAction(item.item.action, item.item.selected)}
  110. />
  111. </View>
  112. );
  113. }
  114. _onPress(action) {
  115. switch(action) {
  116. case actions.setBold:
  117. case actions.setItalic:
  118. case actions.insertBulletsList:
  119. case actions.insertOrderedList:
  120. case actions.setUnderline:
  121. case actions.heading1:
  122. case actions.heading2:
  123. case actions.heading3:
  124. case actions.heading4:
  125. case actions.heading5:
  126. case actions.heading6:
  127. case actions.setParagraph:
  128. case actions.removeFormat:
  129. case actions.alignLeft:
  130. case actions.alignCenter:
  131. case actions.alignRight:
  132. case actions.alignFull:
  133. case actions.setSubscript:
  134. case actions.setSuperscript:
  135. case actions.setStrikethrough:
  136. case actions.setHR:
  137. case actions.setIndent:
  138. case actions.setOutdent:
  139. this.state.editor._sendAction(action);
  140. break;
  141. case actions.insertLink:
  142. this.state.editor.prepareInsert();
  143. if(this.props.onPressAddLink) {
  144. this.props.onPressAddLink();
  145. } else {
  146. this.state.editor.getSelectedText().then(selectedText => {
  147. this.state.editor.showLinkDialog(selectedText);
  148. });
  149. }
  150. break;
  151. case actions.insertImage:
  152. this.state.editor.prepareInsert();
  153. if(this.props.onPressAddImage) {
  154. this.props.onPressAddImage();
  155. }
  156. break;
  157. break;
  158. }
  159. }
  160. }
  161. const styles = StyleSheet.create({
  162. defaultSelectedButton: {
  163. backgroundColor: 'red'
  164. },
  165. defaultUnselectedButton: {}
  166. });