react-bootstrap-front 3.8.0 → 3.9.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-bootstrap-front",
3
- "version": "3.8.0",
3
+ "version": "3.9.4",
4
4
  "description": "React Bootstrap Components",
5
5
  "keywords": [
6
6
  "Bootstrap 4",
@@ -34,6 +34,7 @@
34
34
  "react-router-dom": "^5.0.1"
35
35
  },
36
36
  "dependencies": {
37
+ "@draft-js-plugins/image": "^4.1.2",
37
38
  "@ericblade/quagga2": "^1.4.1",
38
39
  "@popperjs/core": "^2.5.4",
39
40
  "autosize": "^4.0.2",
@@ -6,22 +6,32 @@ import { Dropdown } from '../basic';
6
6
  export default class DropdownWrapper extends Component {
7
7
  static propTypes = {
8
8
  align: PropTypes.string,
9
- children: PropTypes.element.isRequired,
9
+ autoClose: PropTypes.bool,
10
10
  className: PropTypes.string,
11
11
  myRef: PropTypes.object,
12
+ open: PropTypes.bool,
12
13
  tooltip: PropTypes.string,
13
14
  trigger: PropTypes.element.isRequired,
14
15
  };
15
16
  static defaultProps = {
16
17
  align: 'bottom-left',
18
+ autoClose: true,
17
19
  className: '',
18
20
  myRef: null,
21
+ open: false,
19
22
  tooltip: '',
20
23
  };
21
24
 
25
+ static getDerivedStateFromProps(state, props) {
26
+ if (state.origOpen !== props.open && state.open !== props.open) {
27
+ return { open: props.open, origOpen: props.open };
28
+ }
29
+ return null;
30
+ }
31
+
22
32
  constructor(props) {
23
33
  super(props);
24
- this.state = { open: false, ref: props.myRef || React.createRef() };
34
+ this.state = { origOpen: this.props.open, open: this.props.open || false, ref: props.myRef || React.createRef() };
25
35
  this.onClose = this.onClose.bind(this);
26
36
  this.onClick = this.onClick.bind(this);
27
37
  }
@@ -41,14 +51,17 @@ export default class DropdownWrapper extends Component {
41
51
  render() {
42
52
  const clonedTrigger = React.cloneElement(
43
53
  this.props.trigger,
44
- {ref: this.state.ref, onClick: this.onClick, title: this.props.tooltip}
54
+ { ref: this.state.ref, onClick: this.onClick, title: this.props.tooltip }
45
55
  )
56
+ const { onClose } = this;
46
57
  return (
47
58
  <>
48
59
  {clonedTrigger}
49
60
  {this.state.open && (
50
- <Dropdown align={this.props.align} myRef={this.state.ref} onClose={this.onClose}>
51
- <div onClick={this.onClose}>{this.props.children}</div>
61
+ <Dropdown align={this.props.align} myRef={this.state.ref} onClose={onClose}>
62
+ <div onClick={this.props.autoClose && this.onClose}>
63
+ {typeof this.props.children === 'function' ? this.props.children({ onClose }) : this.props.children}
64
+ </div>
52
65
  </Dropdown>
53
66
  )}
54
67
  </>
@@ -298,7 +298,7 @@ export default class ResponsiveModalInner extends Component {
298
298
  </div>
299
299
  }
300
300
  </div>
301
- {this.props.buttons && (
301
+ {(this.props.buttons || this.props.help || this.props.saving) && (
302
302
  <div className={classnames('modal-footer', this.props.modalClassName)}>
303
303
  {(this.props.help || this.props.saving ) &&
304
304
  <div className="modal-left-buttons">
@@ -53,8 +53,8 @@ export default class Dropdown extends Component {
53
53
 
54
54
  handleClickOutside(event) {
55
55
  const domNode = ReactDOM.findDOMNode(this);
56
- if (!domNode || !domNode.contains(event.target)) {
57
- if (this.props.myRef && this.props.myRef.current &&this.props.myRef.current.contains(event.target)) {
56
+ if (!domNode || !domNode.contains(event.target)) {
57
+ if (this.props.myRef && this.props.myRef.current && this.props.myRef.current.contains(event.target)) {
58
58
  event.preventDefault();
59
59
  event.stopPropagation();
60
60
  }
@@ -8,7 +8,6 @@ import { getFieldId } from '../helpers';
8
8
  export const InputJson = props => {
9
9
  let myId = getFieldId(props.name, props.id);
10
10
  const data = JSON.parse(props.value) || {};
11
- console.log(data, props.value);
12
11
  return (
13
12
  <InputGroup {...props} id={myId}>
14
13
  {props.prepend && props.prepend !== '' && (
@@ -35,12 +35,12 @@ export default class ColorPicker extends Component {
35
35
  type="button"
36
36
  className={classnames(this.props.className, 'btn btn-light')}
37
37
  >
38
- Color
38
+ {this.props.config.icon ? this.props.config.icon : 'Color' }
39
39
  </button>
40
40
  );
41
41
  const { color } = this.props.currentState;
42
42
  return (
43
- <DropdownWrapper trigger={trigger} className="rbf-inline-wrapper btn-group pl-2" align="bottom-right" myRef={this.state.myRef}>
43
+ <DropdownWrapper autoClose={false} trigger={trigger} className="ui-inline-wrapper btn-group pl-2" align="bottom-right" myRef={this.state.myRef}>
44
44
  <DropdownMenu>
45
45
  <ChromePicker color={color} onChangeComplete={this.onChange} />
46
46
  </DropdownMenu>
@@ -0,0 +1,70 @@
1
+ import React, { Component } from 'react';
2
+ import classnames from 'classnames';
3
+ import PropTypes from 'prop-types';
4
+ import { DropdownWrapper } from '../advanced'
5
+ import { DropdownMenu, DropdownMenuOption } from '../basic';
6
+
7
+ export default class FontFamily extends Component {
8
+ static propTypes = {
9
+ expanded: PropTypes.bool,
10
+ onExpandEvent: PropTypes.func,
11
+ onChange: PropTypes.func,
12
+ currentState: PropTypes.object,
13
+ };
14
+
15
+ constructor(props) {
16
+ super(props);
17
+ this.state = {
18
+ myRef: React.createRef()
19
+ }
20
+ }
21
+
22
+ stopPropagation = (event) => {
23
+ event.stopPropagation();
24
+ };
25
+
26
+ onChange = (family) => {
27
+ const { onChange } = this.props;
28
+ onChange('family', family.hex);
29
+ }
30
+
31
+ render() {
32
+ const trigger = (
33
+ <button
34
+ type="button"
35
+ className={classnames(this.props.className, 'btn btn-light')}
36
+ >
37
+ {this.props.icon ? this.props.icon : 'Font' }
38
+ </button>
39
+ );
40
+ const {
41
+ config: { icon, className, dropdownClassName, options, title },
42
+ onChange,
43
+ expanded,
44
+ doCollapse,
45
+ onExpandEvent,
46
+ doExpand,
47
+ translations,
48
+ } = this.props;
49
+ let { currentState: { fontFamily: currentFontFamily } } = this.props;
50
+ let { defaultFontFamily } = this.state;
51
+ currentFontFamily = currentFontFamily ||
52
+ (options && options.indexOf(defaultFontFamily) >= 0 && defaultFontFamily);
53
+ return (
54
+ <DropdownWrapper trigger={trigger} className="ui-inline-wrapper btn-group pl-2" align="bottom-right" myRef={this.state.myRef}>
55
+ <DropdownMenu>
56
+ {options.map((family, index) =>
57
+ (<DropdownMenuOption
58
+ className="rdw-fontfamily-option"
59
+ active={currentFontFamily === family}
60
+ onClick={() => onChange(family)}
61
+ key={index}
62
+ >
63
+ {family}
64
+ </DropdownMenuOption>),
65
+ )}
66
+ </DropdownMenu>
67
+ </DropdownWrapper>
68
+ );
69
+ }
70
+ }
File without changes
@@ -23,9 +23,13 @@ export default class FontSize extends Component {
23
23
  event.stopPropagation();
24
24
  };
25
25
 
26
- onChange = (color) => {
26
+ onChange = (size) => {
27
27
  const { onChange } = this.props;
28
- onChange('color', color.hex);
28
+ let mySize = size.hex;
29
+ if (!isNaN(mySize)) {
30
+ mySize += 'px';
31
+ }
32
+ onChange('size', mySize);
29
33
  }
30
34
 
31
35
  render() {
@@ -34,7 +38,7 @@ export default class FontSize extends Component {
34
38
  type="button"
35
39
  className={classnames(this.props.className, 'btn btn-light')}
36
40
  >
37
- Size
41
+ {this.props.config.icon ? this.props.config.icon : 'Size' }
38
42
  </button>
39
43
  );
40
44
  const {
@@ -52,7 +56,7 @@ export default class FontSize extends Component {
52
56
  currentFontSize = currentFontSize ||
53
57
  (options && options.indexOf(defaultFontSize) >= 0 && defaultFontSize);
54
58
  return (
55
- <DropdownWrapper trigger={trigger} className="rbf-inline-wrapper btn-group pl-2" align="bottom-right" myRef={this.state.myRef}>
59
+ <DropdownWrapper trigger={trigger} className="ui-inline-wrapper btn-group pl-2" align="bottom-right" myRef={this.state.myRef}>
56
60
  <DropdownMenu>
57
61
  {options.map((size, index) =>
58
62
  (<DropdownMenuOption
@@ -0,0 +1,64 @@
1
+ import React, { Component } from 'react';
2
+ import classnames from 'classnames';
3
+ import PropTypes from 'prop-types';
4
+ import { DropdownWrapper } from '../advanced'
5
+ import { DropdownMenu, InputText } from '../basic';
6
+
7
+ export default class Image extends Component {
8
+ static propTypes = {
9
+ expanded: PropTypes.bool,
10
+ onExpandEvent: PropTypes.func,
11
+ onChange: PropTypes.func,
12
+ currentState: PropTypes.object,
13
+ };
14
+
15
+ constructor(props) {
16
+ super(props);
17
+ this.state = {
18
+ url: '',
19
+ myRef: React.createRef()
20
+ }
21
+ this.onChange = this.onChange.bind(this);
22
+ this.onAdd = this.onAdd.bind(this);
23
+ }
24
+
25
+ onChange(ev) {
26
+ if (ev) {
27
+ ev.preventDefault();
28
+ ev.stopPropagation();
29
+ const value = ev.target.value;
30
+ const name = ev.target.name;
31
+ this.setState({ [name]: value });
32
+ }
33
+ }
34
+
35
+ onAdd(ev) {
36
+ const url = this.state.url;
37
+ this.setState({ url: '' });
38
+ this.props.onChange(url);
39
+ }
40
+
41
+ render() {
42
+ const trigger = (
43
+ <button
44
+ type="button"
45
+ className={classnames(this.props.className, 'btn btn-light')}
46
+ >
47
+ {this.props.config.icon ? this.props.config.icon : 'Image'}
48
+ </button>
49
+ );
50
+ //console.log(this.props.currentState, this.props.config);
51
+ return (
52
+ <DropdownWrapper autoClose={false} trigger={trigger} className="ui-inline-wrapper btn-group pl-2" align="bottom-right" myRef={this.state.myRef}>
53
+ {({ onClose }) =>
54
+ <DropdownMenu>
55
+ <>
56
+ <InputText labelTop={true} label="Url" name="url" value={this.state.url} onChange={this.onChange} />
57
+ <button type="button" class="btn btn-xs btn-success" onClick={(ev) => { onClose(); this.onAdd(ev); }}>Ok</button>
58
+ </>
59
+ </DropdownMenu>
60
+ }
61
+ </DropdownWrapper>
62
+ );
63
+ }
64
+ }
@@ -0,0 +1,3 @@
1
+ .btn-image {
2
+ margin-left: 5px;
3
+ }
@@ -18,15 +18,16 @@ export default class Inline extends Component {
18
18
  }
19
19
  render() {
20
20
  const { config, currentState, onChange, translations } = this.props;
21
+ const textalign = currentState.textAlignment || '';
21
22
  return (
22
- <div className={classnames('rbf-inline-wrapper btn-group pl-2', config.className)} aria-label="rdw-inline-control">
23
+ <div className={classnames('ui-inline-wrapper btn-group', config.className)} aria-label="rdw-inline-control">
23
24
  {
24
25
  config.options
25
26
  .map((style, index) =>
26
27
  (<button
27
28
  key={index}
28
29
  onClick={() => onChange(style)}
29
- className={classnames("btn btn-light", config[style].className, (currentState[style] === true ||
30
+ className={classnames("btn btn-light", config[style].className, (textalign === true ||
30
31
  (style === 'MONOSPACE' && currentState.CODE)) && "active")}
31
32
  title={config[style].title || translations[`components.controls.inline.${style}`]}
32
33
  >
@@ -1,11 +1,12 @@
1
1
  import React, { Component } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import classnames from 'classnames';
4
- import { EditorState, Modifier } from 'draft-js';
4
+ import { camelCase } from 'lodash';
5
+ import { EditorState, Modifier, CompositeDecorator } from 'draft-js';
5
6
  import { Editor } from 'react-draft-wysiwyg';
6
7
  import { convertToHTML, convertFromHTML } from 'draft-convert';
7
8
  import { htmlToString } from '../helpers';
8
- import { ColorPicker, Inline, FontSize } from './';
9
+ import { ColorPicker, Inline, FontSize, FontFamily, Image, MailMerge as MailMergeOption } from './';
9
10
  import '../../../node_modules/react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
10
11
 
11
12
  const myStyle = {
@@ -37,20 +38,62 @@ const toHtml = {
37
38
  case 'color':
38
39
  return <span style={{ color: parts[1] }} />;
39
40
  case 'fontsize':
40
- return <span style={{ fontSize: parts[1] }} />;
41
+ return <span style={{ fontSize: parts[1] + 'px' }} />;
42
+ case 'text':
43
+ if (parts[1] === 'align') {
44
+ return <span style={{ textAlign: parts[2] }} />;
45
+ }
46
+ return '';
41
47
  default:
42
48
  // nothing
43
49
  break;
44
50
  }
45
51
  },
46
52
  blockToHTML: block => {
53
+ let styles = {};
54
+ if (block.data && Object.keys(block.data).length > 0) {
55
+ Object.keys(block.data).forEach(key => {
56
+ styles[camelCase(key)] = block.data[key];
57
+ });
58
+ }
47
59
  if (block.type === 'PARAGRAPH') {
48
- return <p />;
60
+ return <p style={styles} />;
61
+ }
62
+ if (block.type === 'atomic') {
63
+ return {
64
+ start: "",
65
+ end: "",
66
+ }
67
+ }
68
+ if (block.type === 'unstyled' && block.text.trim() === '') {
69
+ return <br />;
49
70
  }
71
+ if (Object.keys(styles).length > 0) {
72
+ return <p style={styles} />;
73
+ }
74
+ return null;
50
75
  },
51
76
  entityToHTML: (entity, originalText) => {
52
- if (entity.type === 'LINK') {
53
- return <a href={entity.data.url}>{originalText}</a>;
77
+ switch (entity.type) {
78
+ case 'LINK':
79
+ return <a href={entity.data.url}>{originalText}</a>;
80
+ case 'MAILMERGE':
81
+ return <span data-mailmerge="{originalText}">{originalText}</span>;
82
+ case 'IMAGE':
83
+ let otherDatas = {};
84
+ let alt = '';
85
+ if (entity.data.height) {
86
+ otherDatas['height'] = entity.data.height;
87
+ }
88
+ if (entity.data.width) {
89
+ otherDatas['width'] = entity.data.width;
90
+ }
91
+ if (entity.data.alt) {
92
+ alt = entity.data.alt;
93
+ }
94
+ return <img src={entity.data.src} {...otherDatas} alt={alt} />;
95
+ default:
96
+ break;
54
97
  }
55
98
  return originalText;
56
99
  },
@@ -96,40 +139,99 @@ const fromHtml = {
96
139
  if (fontSize && fontSize !== '') {
97
140
  style.add(`fontsize-${fontSize.replace(/px$/g, '')}`);
98
141
  }
142
+ const textAlign = node.style.textAlign;
143
+ if (textAlign && textAlign !== '') {
144
+ style.add(`textalign-${textAlign}`);
145
+ }
99
146
  }
100
147
  })
101
148
  .toOrderedSet();
102
149
  return currentStyle;
103
150
  },
104
151
  htmlToEntity: (nodeName, node, createEntity) => {
152
+ let entity = null;
105
153
  if (nodeName === 'a') {
106
- return createEntity('LINK', 'MUTABLE', { url: node.href });
154
+ entity = createEntity('LINK', 'MUTABLE', { url: node.href });
155
+ }
156
+ if (nodeName === 'span' && node.dataset && node.dataset.mailmerge) {
157
+ entity = createEntity('MAILMERGE', 'IMMUTABLE', { mailmerge: node.dataset.mailmerge });
107
158
  }
159
+ if (nodeName === 'img') {
160
+ entity = createEntity('IMAGE', 'MUTABLE', { src: node.src });
161
+ }
162
+ return entity;
108
163
  },
109
164
  textToEntity: (text, createEntity) => {
110
165
  const result = [];
111
- text.replace(/\@(\w+)/g, (match, name, offset) => {
112
- const entityKey = createEntity('AT-MENTION', 'IMMUTABLE', { name });
113
- result.push({
114
- entity: entityKey,
115
- offset,
116
- length: match.length,
117
- result: match,
118
- });
119
- });
120
166
  return result;
121
167
  },
122
168
  htmlToBlock: (nodeName, node) => {
169
+ if (nodeName === "hr" || nodeName === "img") {
170
+ return "atomic";
171
+ }
123
172
  if (nodeName === 'blockquote') {
124
173
  return {
125
174
  type: 'blockquote',
126
175
  data: {},
127
176
  };
128
177
  }
178
+ if (nodeName === 'br') {
179
+ return {
180
+ type: 'PARAGRAPH',
181
+ data: {},
182
+ };
183
+ }
184
+ if (nodeName === 'p' && node instanceof HTMLElement) {
185
+ let styles = {};
186
+ if (node.style.textAlign) {
187
+ styles['text-align'] = node.style.textAlign;
188
+ }
189
+ if (Object.keys(styles).length > 0) {
190
+ return {
191
+ type: 'PARAGRAPH',
192
+ data: styles,
193
+ };
194
+ }
195
+ }
196
+ return null;
129
197
  },
130
198
  };
131
199
 
132
- export default class InputTextarea extends Component {
200
+ function findMailmergeEntities(contentBlock, callback, contentState) {
201
+ contentBlock.findEntityRanges(
202
+ (character) => {
203
+ const entityKey = character.getEntity();
204
+ const found = entityKey !== null && contentState.getEntity(entityKey).getType() === 'MAILMERGE';
205
+ return found;
206
+ },
207
+ callback
208
+ );
209
+ }
210
+
211
+ const Mailmerge = (props) => {
212
+ const {mailmerge} = props.contentState.getEntity(props.entityKey).getData();
213
+ return (
214
+ <a href={mailmerge}>
215
+ {props.children}
216
+ </a>
217
+ );
218
+ };
219
+
220
+ const MailmergeOptions = (props) => {
221
+ if (props.presetTexts && Array.isArray(props.presetTexts) && props.presetTexts.length > 0) {
222
+ return (
223
+ [<MailMergeOption
224
+ icon={props.presetTextIcon}
225
+ options={props.presetTexts}
226
+ onChangeText={(text) => this.onAddPresetText(text)}
227
+ />]
228
+ );
229
+ }
230
+ return [];
231
+ }
232
+
233
+
234
+ export default class InputHtml extends Component {
133
235
  static propTypes = {
134
236
  id: PropTypes.string,
135
237
  name: PropTypes.string.isRequired,
@@ -142,8 +244,14 @@ export default class InputTextarea extends Component {
142
244
  disabled: PropTypes.bool,
143
245
  clearIcon: PropTypes.element,
144
246
  toolbarIcon: PropTypes.element,
247
+ sizeIcon: PropTypes.element,
248
+ fontIcon: PropTypes.element,
249
+ colorIcon: PropTypes.element,
250
+ imageIcon: PropTypes.element,
145
251
  presetTextIcon: PropTypes.element,
252
+ presetTexts: PropTypes.array,
146
253
  onPresetText: PropTypes.func,
254
+ t: PropTypes.func,
147
255
  };
148
256
 
149
257
  static defaultProps = {
@@ -157,8 +265,14 @@ export default class InputTextarea extends Component {
157
265
  required: false,
158
266
  clearIcon: null,
159
267
  toolbarIcon: null,
268
+ sizeIcon: null,
269
+ fontIcon: null,
270
+ colorIcon: null,
271
+ imageIcon: null,
160
272
  presetTextIcon: null,
273
+ presetTexts: [],
161
274
  onPresetText: null,
275
+ t: () => {},
162
276
  };
163
277
 
164
278
  constructor(props) {
@@ -169,18 +283,22 @@ export default class InputTextarea extends Component {
169
283
  } else {
170
284
  content = '<p/>';
171
285
  }
286
+ const decorator = new CompositeDecorator([
287
+ {
288
+ strategy: findMailmergeEntities,
289
+ component: Mailmerge,
290
+ },
291
+ ]);
172
292
  const value = convertFromHTML(fromHtml)(content);
173
293
  this.state = {
174
- editorState: EditorState.createWithContent(value),
294
+ editorState: EditorState.createWithContent(value, decorator),
175
295
  toolbar: false,
176
296
  };
177
297
  this.onEditorStateChange = this.onEditorStateChange.bind(this);
178
298
  this.onChange = this.onChange.bind(this);
179
299
  this.onToolbar = this.onToolbar.bind(this);
180
300
  this.onClear = this.onClear.bind(this);
181
- this.onPresetText = this.onPresetText.bind(this);
182
301
  this.onAddPresetText = this.onAddPresetText.bind(this);
183
- this.onPresetTextClose = this.onPresetTextClose.bind(this);
184
302
  }
185
303
 
186
304
  onEditorStateChange(editorState) {
@@ -216,11 +334,6 @@ export default class InputTextarea extends Component {
216
334
  this.props.onChange(event);
217
335
  }
218
336
 
219
- onPresetText() {
220
- this.props.onPresetText();
221
- this.setState({ presetText: true });
222
- }
223
-
224
337
  onAddPresetText(contentMore) {
225
338
  const editorState = this.state.editorState;
226
339
  let content = editorState.getCurrentContent();
@@ -238,27 +351,54 @@ export default class InputTextarea extends Component {
238
351
  this.props.onChange(event);
239
352
  }
240
353
 
241
- onPresetTextClose() {
242
- this.setState({ presetText: false });
243
- }
244
-
245
354
  render() {
246
355
  //<div className={classnames('input-group', (props.error || props.warning) && 'is-invalid')}>
247
356
  const { editorState, toolbar } = this.state;
357
+ const { t } = this.props;
248
358
  const editorToolbar = {
249
- options: ['inline','fontSize','colorPicker'],
359
+ options: ['inline','fontSize', 'fontFamily', 'list', 'textAlign', 'colorPicker', 'image'],
250
360
  inline: {
251
361
  inDropdown: false,
252
362
  component: Inline,
253
- options: ['bold', 'italic', 'underline', 'superscript', 'subscript'],
363
+ options: ['bold', 'italic', 'underline', 'strikethrough', 'monospace', 'superscript', 'subscript'],
364
+ bold: { title: t({ id: 'ui.textarea.draft.toolbar.bold', defaultMessage: 'Bold' }) },
365
+ italic: { title: t({ id: 'ui.textarea.draft.toolbar.italic', defaultMessage: 'Italic' }) },
366
+ underline: { title: t({ id: 'ui.textarea.draft.toolbar.underline', defaultMessage: 'Underline' }) },
367
+ strikethrough: { title: t({ id: 'ui.textarea.draft.toolbar.strikethrough', defaultMessage: 'Underline' }) },
368
+ monospace: { title: t({ id: 'ui.textarea.draft.toolbar.monospace', defaultMessage: 'monospace' }) },
369
+ superscript: { title: t({ id: 'ui.textarea.draft.toolbar.superscript', defaultMessage: 'Superscript' }) },
370
+ subscript: { title: t({ id: 'ui.textarea.draft.toolbar.subscript', defaultMessage: 'Subscript' }) },
254
371
  },
255
372
  fontSize: {
256
373
  component: FontSize,
257
374
  options: [7, 8, 9, 10, 11, 12, 14, 16, 18, 24, 30, 36, 48, 60, 72, 96],
375
+ icon: this.props.sizeIcon,
376
+ },
377
+ fontFamily: {
378
+ component: FontFamily,
379
+ options: ['Arial', 'Georgia', 'Impact', 'Tahoma', 'Times New Roman', 'Verdana'],
380
+ },
381
+ list: {
382
+ inDropdown: false,
383
+ component: Inline,
384
+ options: ['unordered', 'ordered'],
385
+ },
386
+ textAlign: {
387
+ inDropdown: false,
388
+ component: Inline,
389
+ options: ['left', 'center', 'right'],
258
390
  },
259
391
  colorPicker: {
260
- component: ColorPicker
261
- }
392
+ component: ColorPicker,
393
+ icon: this.props.colorIcon,
394
+ },
395
+ image: {
396
+ component: Image,
397
+ inputAccept: 'image/gif,image/jpeg,image/jpg,image/png,image/svg',
398
+ alt: { present: false, mandatory: false },
399
+ previewImage: true,
400
+ icon: this.props.imageIcon,
401
+ },
262
402
  };
263
403
  return (
264
404
  <div className={classnames('form-group', !this.props.labelTop && 'row')}>
@@ -276,8 +416,9 @@ export default class InputTextarea extends Component {
276
416
  <Editor
277
417
  toolbarHidden={!toolbar}
278
418
  toolbar={editorToolbar}
419
+ toolbarCustomButtons={MailmergeOptions(this.props)}
279
420
  editorState={editorState}
280
- wrapperClassName="form-control border-rbf h-auto"
421
+ wrapperClassName="form-control border-ui h-auto"
281
422
  onEditorStateChange={this.onEditorStateChange}
282
423
  onBlur={this.onChange}
283
424
  />
@@ -285,7 +426,7 @@ export default class InputTextarea extends Component {
285
426
  <button
286
427
  type="button"
287
428
  className={classnames(
288
- 'btn btn-input btn-outline-rbf bg-light',
429
+ 'btn btn-input btn-outline-ui bg-light',
289
430
  this.props.size === 'sm' && `btn-${this.props.size}`
290
431
  )}
291
432
  onClick={this.onToolbar}
@@ -295,7 +436,7 @@ export default class InputTextarea extends Component {
295
436
  <button
296
437
  type="button"
297
438
  className={classnames(
298
- 'btn btn-input btn-outline-rbf bg-light',
439
+ 'btn btn-input btn-outline-ui bg-light',
299
440
  this.props.size === 'sm' && `btn-${this.props.size}`
300
441
  )}
301
442
  onClick={this.onClear}