@entur-partner/rich-text-editor 6.2.4 → 6.2.6-6.2.6-alpha.1.0

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.
@@ -0,0 +1,907 @@
1
+ import { ExpandablePanel } from '@entur/expand';
2
+ import { TextField, FeedbackText } from '@entur/form';
3
+ import { Unbutton, Stack } from '@entur-partner/common';
4
+ import React, { Component, createRef, useState } from 'react';
5
+ import { Label } from '@entur/typography';
6
+ import cx from 'classnames';
7
+ import { EditorState, CompositeDecorator, Editor, RichUtils, getDefaultKeyBinding, Modifier, convertToRaw, convertFromRaw } from 'draft-js';
8
+ import PropTypes from 'prop-types';
9
+ import { useTranslation } from 'react-i18next';
10
+ import { SecondarySquareButton } from '@entur/button';
11
+ import { LinkIcon, CloseIcon, CheckIcon, UnlinkIcon, DownArrowIcon, BulletListIcon, NumberListIcon, BoldIcon, ItalicIcon, UnderlineIcon } from '@entur/icons';
12
+ import { Dropdown } from '@entur/dropdown';
13
+ import { OverflowMenuItem, OverflowMenu } from '@entur/menu';
14
+ import { Popover } from '@entur/tooltip';
15
+ import { draftToMarkdown, markdownToDraft } from 'markdown-draft-js';
16
+ import showdown from 'showdown';
17
+ import { convertFromHTML, convertToHTML } from 'draft-convert';
18
+
19
+ function _extends() {
20
+ return _extends = Object.assign ? Object.assign.bind() : function (n) {
21
+ for (var e = 1; e < arguments.length; e++) {
22
+ var t = arguments[e];
23
+ for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
24
+ }
25
+ return n;
26
+ }, _extends.apply(null, arguments);
27
+ }
28
+ function _inheritsLoose(t, o) {
29
+ t.prototype = Object.create(o.prototype), t.prototype.constructor = t, _setPrototypeOf(t, o);
30
+ }
31
+ function _objectWithoutPropertiesLoose(r, e) {
32
+ if (null == r) return {};
33
+ var t = {};
34
+ for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
35
+ if (-1 !== e.indexOf(n)) continue;
36
+ t[n] = r[n];
37
+ }
38
+ return t;
39
+ }
40
+ function _setPrototypeOf(t, e) {
41
+ return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
42
+ return t.__proto__ = e, t;
43
+ }, _setPrototypeOf(t, e);
44
+ }
45
+
46
+ var Key = /*#__PURE__*/Object.freeze({
47
+ ENTER: 13
48
+ });
49
+ function getKey(event) {
50
+ return event.keyCode || event.which;
51
+ }
52
+
53
+ function useI18N() {
54
+ var _useTranslation = useTranslation(),
55
+ t = _useTranslation.t,
56
+ language = _useTranslation.i18n.language;
57
+ if (language !== "nb" && language !== "en" && language !== "nb-NO" && language !== "en-GB") {
58
+ throw Error("Language must be either nb or en.");
59
+ }
60
+ return t;
61
+ }
62
+ function withI18n(Component) {
63
+ return function WrappedComponent(props) {
64
+ var t = useI18N();
65
+ return /*#__PURE__*/React.createElement(Component, _extends({}, props, {
66
+ i18n: t
67
+ }));
68
+ };
69
+ }
70
+
71
+ var StyleButton = /*#__PURE__*/function (_Component) {
72
+ function StyleButton() {
73
+ var _this;
74
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
75
+ args[_key] = arguments[_key];
76
+ }
77
+ _this = _Component.call.apply(_Component, [this].concat(args)) || this;
78
+ _this.onToggle = function (e) {
79
+ var _this$props = _this.props,
80
+ style = _this$props.style,
81
+ onToggle = _this$props.onToggle;
82
+ e.preventDefault();
83
+ onToggle(style);
84
+ };
85
+ _this.onToggleNoEvent = function () {
86
+ var _this$props2 = _this.props,
87
+ style = _this$props2.style,
88
+ onToggle = _this$props2.onToggle;
89
+ onToggle(style);
90
+ };
91
+ return _this;
92
+ }
93
+ _inheritsLoose(StyleButton, _Component);
94
+ var _proto = StyleButton.prototype;
95
+ _proto.render = function render() {
96
+ var _this2 = this;
97
+ var _this$props3 = this.props,
98
+ i18n = _this$props3.i18n,
99
+ active = _this$props3.active,
100
+ label = _this$props3.label,
101
+ title = _this$props3.title,
102
+ hotKey = _this$props3.hotKey;
103
+ var classNames = cx("editor-stylebutton", {
104
+ active: active
105
+ });
106
+ return (
107
+ /*#__PURE__*/
108
+ // biome-ignore lint/a11y/noStaticElementInteractions: Ignore for now.
109
+ React.createElement("div", {
110
+ className: classNames,
111
+ onMouseDown: this.onToggle,
112
+ title: i18n(title) + hotKey
113
+ // biome-ignore lint/a11y/noNoninteractiveTabindex: Ignore for now.
114
+ ,
115
+ tabIndex: 0,
116
+ onKeyPress: function onKeyPress(event) {
117
+ if (getKey(event) === Key.ENTER) {
118
+ _this2.onToggleNoEvent();
119
+ }
120
+ }
121
+ }, label)
122
+ );
123
+ };
124
+ return StyleButton;
125
+ }(Component);
126
+ var StyleButton$1 = /*#__PURE__*/withI18n(StyleButton);
127
+
128
+ var BlockTypeButtonControls = function BlockTypeButtonControls(props) {
129
+ var editorState = props.editorState,
130
+ blockTypes = props.blockTypes,
131
+ onToggle = props.onToggle;
132
+ var selection = editorState.getSelection();
133
+ var blockTypeStyle = editorState.getCurrentContent().getBlockForKey(selection.getStartKey()).getType();
134
+ return /*#__PURE__*/React.createElement("div", {
135
+ className: "controls-group block-editor-controls"
136
+ }, blockTypes.map(function (type) {
137
+ return /*#__PURE__*/React.createElement(StyleButton$1, {
138
+ key: type.style + type.label,
139
+ active: type.style === blockTypeStyle,
140
+ label: type.label,
141
+ onToggle: onToggle,
142
+ style: type.style,
143
+ title: type.tooltip
144
+ });
145
+ }));
146
+ };
147
+
148
+ var BlockTypeLinkControls = /*#__PURE__*/function (_Component) {
149
+ function BlockTypeLinkControls() {
150
+ var _this;
151
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
152
+ args[_key] = arguments[_key];
153
+ }
154
+ _this = _Component.call.apply(_Component, [this].concat(args)) || this;
155
+ _this.state = {
156
+ urlValue: "",
157
+ showUrlInput: false,
158
+ hasLink: false
159
+ };
160
+ _this.onUrlChange = function (e) {
161
+ _this.setState({
162
+ urlValue: e.target.value
163
+ });
164
+ };
165
+ _this.addLink = function (e) {
166
+ e.preventDefault();
167
+ var editorState = _this.props.editorState;
168
+ var selection = editorState.getSelection();
169
+ if (!selection.isCollapsed()) {
170
+ var currentContent = editorState.getCurrentContent();
171
+ var startKey = selection.getStartKey();
172
+ var startOffset = selection.getStartOffset();
173
+ var blockWithLinkAtBeginning = currentContent.getBlockForKey(startKey);
174
+ var linkKey = blockWithLinkAtBeginning.getEntityAt(startOffset);
175
+ var url = "";
176
+ if (linkKey) {
177
+ var linkInstance = currentContent.getEntity(linkKey);
178
+ url = linkInstance.getData().url;
179
+ }
180
+ _this.setState({
181
+ showUrlInput: true,
182
+ urlValue: url,
183
+ hasLink: !!url
184
+ });
185
+ }
186
+ };
187
+ _this.confirmLink = function (e) {
188
+ e.preventDefault();
189
+ var urlValue = _this.state.urlValue;
190
+ var _this$props = _this.props,
191
+ editorState = _this$props.editorState,
192
+ onToggle = _this$props.onToggle;
193
+ var contentState = editorState.getCurrentContent();
194
+ var contentStateWithEntity = contentState.createEntity("LINK", "MUTABLE", {
195
+ url: urlValue
196
+ });
197
+ var entityKey = contentStateWithEntity.getLastCreatedEntityKey();
198
+ var newEditorState = EditorState.set(editorState, {
199
+ currentContent: contentStateWithEntity
200
+ });
201
+ onToggle(newEditorState, entityKey);
202
+ _this.setState({
203
+ showUrlInput: false,
204
+ urlValue: ""
205
+ });
206
+ };
207
+ _this.cancelLink = function (e) {
208
+ e.preventDefault();
209
+ _this.setState({
210
+ showUrlInput: false,
211
+ urlValue: ""
212
+ });
213
+ };
214
+ _this.onLinkInputKeyDown = function (e) {
215
+ if (getKey(e) === Key.ENTER) {
216
+ _this.confirmLink(e);
217
+ }
218
+ };
219
+ _this.removeLink = function (e) {
220
+ e.preventDefault();
221
+ var _this$props2 = _this.props,
222
+ editorState = _this$props2.editorState,
223
+ onToggle = _this$props2.onToggle;
224
+ var hasLink = _this.state.hasLink;
225
+ var selection = editorState.getSelection();
226
+ if (!selection.isCollapsed() && hasLink) {
227
+ onToggle(editorState, null);
228
+ _this.setState({
229
+ showUrlInput: false
230
+ });
231
+ }
232
+ };
233
+ return _this;
234
+ }
235
+ _inheritsLoose(BlockTypeLinkControls, _Component);
236
+ var _proto = BlockTypeLinkControls.prototype;
237
+ _proto.render = function render() {
238
+ var i18n = this.props.i18n;
239
+ var _this$state = this.state,
240
+ showUrlInput = _this$state.showUrlInput,
241
+ hasLink = _this$state.hasLink;
242
+ return /*#__PURE__*/React.createElement("div", {
243
+ className: "controls-group block-editor-controls link-controls"
244
+ }, /*#__PURE__*/React.createElement("div", {
245
+ className: "editor-stylebutton",
246
+ title: i18n("styles.link"),
247
+ onClick: this.addLink,
248
+ tabIndex: 0
249
+ }, /*#__PURE__*/React.createElement(LinkIcon, null)), showUrlInput && /*#__PURE__*/React.createElement("div", {
250
+ className: "url-input-container"
251
+ }, /*#__PURE__*/React.createElement("span", {
252
+ className: "exit-button",
253
+ onMouseDown: this.cancelLink
254
+ }, /*#__PURE__*/React.createElement(CloseIcon, null)), /*#__PURE__*/React.createElement("div", {
255
+ className: "link-label"
256
+ }, i18n("common.from")), /*#__PURE__*/React.createElement("div", {
257
+ className: "url-input-form"
258
+ }, /*#__PURE__*/React.createElement(TextField, {
259
+ style: {
260
+ width: 250,
261
+ margin: 5
262
+ },
263
+ onChange: this.onUrlChange,
264
+ value: this.state.urlValue,
265
+ onKeyDown: this.onLinkInputKeyDown,
266
+ placeholder: "https://example.com"
267
+ }), /*#__PURE__*/React.createElement(SecondarySquareButton, {
268
+ onMouseDown: this.confirmLink
269
+ }, /*#__PURE__*/React.createElement(CheckIcon, {
270
+ width: 15,
271
+ height: 15
272
+ }))), hasLink && /*#__PURE__*/React.createElement("div", {
273
+ className: "remove-link"
274
+ }, /*#__PURE__*/React.createElement(Unbutton, {
275
+ onClick: this.removeLink,
276
+ title: i18n("styles.unlink")
277
+ }, /*#__PURE__*/React.createElement(UnlinkIcon, null), i18n("styles.unlink")))));
278
+ };
279
+ return BlockTypeLinkControls;
280
+ }(Component);
281
+ BlockTypeLinkControls.propTypes = {
282
+ editorState: PropTypes.object,
283
+ onToggle: PropTypes.func
284
+ };
285
+ var BlockTypeLinkControls$1 = /*#__PURE__*/withI18n(BlockTypeLinkControls);
286
+
287
+ var BlockTypeDropdown = /*#__PURE__*/function (_Component) {
288
+ function BlockTypeDropdown() {
289
+ var _this;
290
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
291
+ args[_key] = arguments[_key];
292
+ }
293
+ _this = _Component.call.apply(_Component, [this].concat(args)) || this;
294
+ _this.handleOnClick = function (selectedOption) {
295
+ var onChange = _this.props.onChange;
296
+ onChange(selectedOption);
297
+ };
298
+ return _this;
299
+ }
300
+ _inheritsLoose(BlockTypeDropdown, _Component);
301
+ var _proto = BlockTypeDropdown.prototype;
302
+ _proto.toItem = function toItem(option) {
303
+ return {
304
+ value: option.style,
305
+ label: this.renderFormattedLabel(option.label)
306
+ };
307
+ };
308
+ _proto.renderFormattedLabel = function renderFormattedLabel(label) {
309
+ var formattedLabelText = this.props.i18n(label);
310
+ switch (label) {
311
+ case "styles.p":
312
+ return /*#__PURE__*/React.createElement("div", {
313
+ className: "default-p"
314
+ }, formattedLabelText);
315
+ case "styles.h1":
316
+ return /*#__PURE__*/React.createElement("div", {
317
+ className: "default-h1"
318
+ }, formattedLabelText);
319
+ case "styles.h2":
320
+ return /*#__PURE__*/React.createElement("div", {
321
+ className: "default-h2"
322
+ }, formattedLabelText);
323
+ case "styles.h3":
324
+ return /*#__PURE__*/React.createElement("div", {
325
+ className: "default-h3"
326
+ }, formattedLabelText);
327
+ case "styles.h4":
328
+ return /*#__PURE__*/React.createElement("div", {
329
+ className: "default-h4"
330
+ }, formattedLabelText);
331
+ case "styles.h5":
332
+ return /*#__PURE__*/React.createElement("div", {
333
+ className: "default-h5"
334
+ }, formattedLabelText);
335
+ case "styles.h6":
336
+ return /*#__PURE__*/React.createElement("div", {
337
+ className: "default-h6"
338
+ }, formattedLabelText);
339
+ default:
340
+ return /*#__PURE__*/React.createElement("p", null, formattedLabelText);
341
+ }
342
+ };
343
+ _proto.render = function render() {
344
+ var _this2 = this;
345
+ var _this$props = this.props,
346
+ options = _this$props.options,
347
+ selected = _this$props.selected,
348
+ i18n = _this$props.i18n;
349
+ return /*#__PURE__*/React.createElement(Dropdown, {
350
+ className: "block-type-dropdown",
351
+ items: options.map(function (option) {
352
+ return _this2.toItem(option);
353
+ }),
354
+ selectedItem: this.toItem(selected),
355
+ label: i18n("styles.style"),
356
+ onChange: function onChange(selectedItem) {
357
+ return _this2.handleOnClick(selectedItem.value);
358
+ }
359
+ });
360
+ };
361
+ return BlockTypeDropdown;
362
+ }(Component);
363
+ var BlockTypeDropdown$1 = /*#__PURE__*/withI18n(BlockTypeDropdown);
364
+
365
+ var BlockTypeControls = function BlockTypeControls(_ref) {
366
+ var editorState = _ref.editorState,
367
+ blockTypes = _ref.blockTypes,
368
+ onToggle = _ref.onToggle;
369
+ var selection = editorState.getSelection();
370
+ var blockTypeStyle = editorState.getCurrentContent().getBlockForKey(selection.getStartKey()).getType();
371
+ var selectedOption = blockTypes.find(function (option) {
372
+ return option.style === blockTypeStyle;
373
+ }) || blockTypes[0];
374
+ return /*#__PURE__*/React.createElement(BlockTypeDropdown$1, {
375
+ options: blockTypes,
376
+ selected: selectedOption,
377
+ onChange: onToggle
378
+ });
379
+ };
380
+
381
+ var InlineStyleControls = function InlineStyleControls(props) {
382
+ var editorState = props.editorState,
383
+ inlineStyles = props.inlineStyles;
384
+ var currentStyle = editorState.getCurrentInlineStyle();
385
+ return /*#__PURE__*/React.createElement("div", {
386
+ className: "controls-group inline-editor-controls"
387
+ }, inlineStyles.map(function (type) {
388
+ return /*#__PURE__*/React.createElement(StyleButton$1, {
389
+ key: type.style + type.label,
390
+ active: currentStyle.has(type.style),
391
+ label: type.label,
392
+ onToggle: props.onToggle,
393
+ style: type.style,
394
+ title: type.tooltip,
395
+ hotKey: type.hotKey
396
+ });
397
+ }));
398
+ };
399
+
400
+ var TagControls = /*#__PURE__*/function (_Component) {
401
+ function TagControls() {
402
+ var _this;
403
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
404
+ args[_key] = arguments[_key];
405
+ }
406
+ _this = _Component.call.apply(_Component, [this].concat(args)) || this;
407
+ _this.tagControlRef = /*#__PURE__*/createRef();
408
+ _this.state = {
409
+ isOpen: false
410
+ };
411
+ _this.handleClickOutside = function (e) {
412
+ if (_this.tagControlRef.current && !_this.tagControlRef.current.contains(e.target)) {
413
+ _this.setState({
414
+ isOpen: false
415
+ });
416
+ }
417
+ };
418
+ _this.handleTagClick = function (tag, delimiter) {
419
+ var _this$props = _this.props,
420
+ editorState = _this$props.editorState,
421
+ onInsertTag = _this$props.onInsertTag;
422
+ var delimiterStart = delimiter[0];
423
+ var delimiterEnd = delimiter[1];
424
+ var fullTag = "" + delimiterStart + tag + delimiterEnd;
425
+ onInsertTag(editorState, fullTag);
426
+ };
427
+ return _this;
428
+ }
429
+ _inheritsLoose(TagControls, _Component);
430
+ var _proto = TagControls.prototype;
431
+ _proto.componentDidMount = function componentDidMount() {
432
+ document.addEventListener("mousedown", this.handleClickOutside);
433
+ };
434
+ _proto.componentWillUnmount = function componentWillUnmount() {
435
+ document.removeEventListener("mousedown", this.handleClickOutside);
436
+ };
437
+ _proto.render = function render() {
438
+ var _this2 = this;
439
+ var _this$props2 = this.props,
440
+ i18n = _this$props2.i18n,
441
+ tags = _this$props2.tags;
442
+ var isOpen = this.state.isOpen;
443
+ var menuItems = tags.map(function (tag) {
444
+ var delimiter = tag.delimiter || "{}";
445
+ return /*#__PURE__*/React.createElement(OverflowMenuItem, {
446
+ key: tag.tag,
447
+ className: "tag-control",
448
+ id: "tag-control-" + tag.tag,
449
+ onClick: function onClick() {
450
+ return _this2.handleTagClick(tag.tag, delimiter);
451
+ }
452
+ }, tag.icon, /*#__PURE__*/React.createElement("span", {
453
+ className: "tag-control-text"
454
+ }, tag.label));
455
+ });
456
+ return /*#__PURE__*/React.createElement("div", {
457
+ className: "tag-control-dropdown",
458
+ ref: this.tagControlRef
459
+ }, /*#__PURE__*/React.createElement("div", {
460
+ className: "tag-control-header",
461
+ onClick: function onClick() {
462
+ return _this2.setState(function (_ref) {
463
+ var isOpen = _ref.isOpen;
464
+ return {
465
+ isOpen: !isOpen
466
+ };
467
+ });
468
+ }
469
+ }, i18n("common.insert"), /*#__PURE__*/React.createElement(DownArrowIcon, {
470
+ className: "tag-control-chevron",
471
+ inline: true
472
+ })), /*#__PURE__*/React.createElement(Popover, {
473
+ open: isOpen,
474
+ className: "tag-control-content"
475
+ }, /*#__PURE__*/React.createElement(OverflowMenu, {
476
+ className: "action-menu"
477
+ }, menuItems)));
478
+ };
479
+ return TagControls;
480
+ }(Component);
481
+ TagControls.propTypes = {
482
+ editorState: PropTypes.object,
483
+ tags: PropTypes.arrayOf(PropTypes.object).isRequired,
484
+ onInsertTag: PropTypes.func.isRequired
485
+ };
486
+ var TagControls$1 = /*#__PURE__*/withI18n(TagControls);
487
+
488
+ var HtmlLink = function HtmlLink(_ref) {
489
+ var url = _ref.url,
490
+ children = _ref.children;
491
+ return /*#__PURE__*/React.createElement("a", {
492
+ href: url
493
+ }, children);
494
+ };
495
+ var Link = function Link(props) {
496
+ var _props$contentState$g = props.contentState.getEntity(props.entityKey).getData(),
497
+ url = _props$contentState$g.url;
498
+ return /*#__PURE__*/React.createElement(HtmlLink, {
499
+ url: url
500
+ }, props.children);
501
+ };
502
+ function findLinkEntities(contentBlock, callback, contentState) {
503
+ contentBlock.findEntityRanges(function (character) {
504
+ var entityKey = character.getEntity();
505
+ return entityKey !== null && contentState.getEntity(entityKey).getType() === "LINK";
506
+ }, callback);
507
+ }
508
+
509
+ var EditorConfigTypes = /*#__PURE__*/Object.freeze({
510
+ FONT_LIST: {
511
+ UNSTYLED: "unstyled",
512
+ HEADER_ONE: "header-one",
513
+ HEADER_TWO: "header-two",
514
+ HEADER_THREE: "header-three",
515
+ HEADER_FOUR: "header-four",
516
+ HEADER_FIVE: "header-five",
517
+ HEADER_SIX: "header-six"
518
+ },
519
+ BLOCK_TYPES: {
520
+ UNORDERED_LIST: "unordered-list",
521
+ ORDERED_LIST: "ordered-list"
522
+ },
523
+ INLINE_STYLES: {
524
+ BOLD: "bold",
525
+ ITALIC: "italic",
526
+ UNDERLINE: "underline"
527
+ }
528
+ });
529
+ var FontList = /*#__PURE__*/Object.freeze({
530
+ unstyled: {
531
+ label: "styles.p",
532
+ style: "unstyled"
533
+ },
534
+ "header-one": {
535
+ label: "styles.h1",
536
+ style: "header-one"
537
+ },
538
+ "header-two": {
539
+ label: "styles.h2",
540
+ style: "header-two"
541
+ },
542
+ "header-three": {
543
+ label: "styles.h3",
544
+ style: "header-three"
545
+ },
546
+ "header-four": {
547
+ label: "styles.h4",
548
+ style: "header-four"
549
+ },
550
+ "header-five": {
551
+ label: "styles.h5",
552
+ style: "header-five"
553
+ },
554
+ "header-six": {
555
+ label: "styles.h6",
556
+ style: "header-six"
557
+ }
558
+ });
559
+ var BlockTypeList = /*#__PURE__*/Object.freeze({
560
+ "unordered-list": {
561
+ label: /*#__PURE__*/React.createElement(BulletListIcon, null),
562
+ style: "unordered-list-item",
563
+ tooltip: "styles.unordered_list_item"
564
+ },
565
+ "ordered-list": {
566
+ label: /*#__PURE__*/React.createElement(NumberListIcon, null),
567
+ style: "ordered-list-item",
568
+ tooltip: "styles.ordered_list_item"
569
+ }
570
+ });
571
+ var InlineStylesList = /*#__PURE__*/Object.freeze({
572
+ bold: {
573
+ label: /*#__PURE__*/React.createElement(BoldIcon, null),
574
+ style: "BOLD",
575
+ tooltip: "styles.bold",
576
+ hotKey: "(Ctrl+B)"
577
+ },
578
+ italic: {
579
+ label: /*#__PURE__*/React.createElement(ItalicIcon, null),
580
+ style: "ITALIC",
581
+ tooltip: "styles.italic",
582
+ hotKey: "(Ctrl+I)"
583
+ },
584
+ underline: {
585
+ label: /*#__PURE__*/React.createElement(UnderlineIcon, null),
586
+ style: "UNDERLINE",
587
+ tooltip: "styles.underline",
588
+ hotKey: "(Ctrl+U)"
589
+ }
590
+ });
591
+ var MinifiedConfigTypes = /*#__PURE__*/Object.freeze({
592
+ fontList: [{
593
+ type: "unstyled",
594
+ label: "styles.p",
595
+ style: "unstyled"
596
+ }, {
597
+ type: "header-two",
598
+ label: "styles.h1",
599
+ style: "header-two"
600
+ }],
601
+ blockTypes: /*#__PURE__*/Object.values(EditorConfigTypes.BLOCK_TYPES),
602
+ inlineStyles: [EditorConfigTypes.INLINE_STYLES.BOLD, EditorConfigTypes.INLINE_STYLES.ITALIC]
603
+ });
604
+ var decorator = /*#__PURE__*/new CompositeDecorator([{
605
+ strategy: findLinkEntities,
606
+ component: Link
607
+ }]);
608
+
609
+ var RichTextEditor = /*#__PURE__*/function (_Component) {
610
+ function RichTextEditor() {
611
+ var _this;
612
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
613
+ args[_key] = arguments[_key];
614
+ }
615
+ _this = _Component.call.apply(_Component, [this].concat(args)) || this;
616
+ _this.wrapperRef = /*#__PURE__*/createRef();
617
+ _this.editor = /*#__PURE__*/createRef();
618
+ _this.handleKeyCommand = function (command, editorState) {
619
+ var newState = RichUtils.handleKeyCommand(editorState, command);
620
+ if (newState) {
621
+ _this.props.onChange(newState);
622
+ return true;
623
+ }
624
+ return false;
625
+ };
626
+ _this.keyBindingFn = function (evt) {
627
+ switch (evt.keyCode) {
628
+ case 9:
629
+ return _this.onTab(evt);
630
+ default:
631
+ return getDefaultKeyBinding(evt);
632
+ }
633
+ };
634
+ _this.onTab = function (evt) {
635
+ evt.stopPropagation();
636
+ var _this$props = _this.props,
637
+ maxTabDepth = _this$props.maxTabDepth,
638
+ editorState = _this$props.editorState,
639
+ onChange = _this$props.onChange;
640
+ onChange(RichUtils.onTab(evt, editorState, maxTabDepth));
641
+ };
642
+ _this.toggleButtonBlockType = function (blockType) {
643
+ var _this$props2 = _this.props,
644
+ editorState = _this$props2.editorState,
645
+ onChange = _this$props2.onChange;
646
+ onChange(RichUtils.toggleBlockType(editorState, blockType));
647
+ };
648
+ _this.toggleSelectBlockType = function (blockType) {
649
+ var _this$props3 = _this.props,
650
+ editorState = _this$props3.editorState,
651
+ onChange = _this$props3.onChange;
652
+ onChange(RichUtils.toggleBlockType(editorState, blockType));
653
+ };
654
+ _this.toggleInlineStyle = function (inlineStyle) {
655
+ var _this$props4 = _this.props,
656
+ editorState = _this$props4.editorState,
657
+ onChange = _this$props4.onChange;
658
+ onChange(RichUtils.toggleInlineStyle(editorState, inlineStyle));
659
+ };
660
+ _this.toggleLink = function (newEditorState, entityKey) {
661
+ _this.props.onChange(RichUtils.toggleLink(newEditorState, newEditorState.getSelection(), entityKey));
662
+ };
663
+ _this.insertText = function (editorState, text) {
664
+ var newContent = Modifier.insertText(editorState.getCurrentContent(), editorState.getSelection(), text);
665
+ _this.props.onChange(EditorState.push(editorState, newContent, "insert-characters"), function () {
666
+ return _this.focusEditor();
667
+ });
668
+ };
669
+ _this.getFontListConfigForPanelType = function (panelType) {
670
+ var controlConfig = _this.getControlConfigBySet(_this.props.controlConfigSet);
671
+ return controlConfig[panelType];
672
+ };
673
+ _this.getControlConfigBySet = function (config) {
674
+ var fontList = ((config == null ? void 0 : config.fontList) || Object.keys(FontList)).filter(function (f) {
675
+ return typeof f === "object" ? FontList[f.type] : FontList[f];
676
+ }).map(function (f) {
677
+ return f.label && f.style ? f : FontList[f];
678
+ });
679
+ var blockTypes = ((config == null ? void 0 : config.blockTypes) || Object.keys(BlockTypeList)).filter(function (f) {
680
+ return typeof f === "object" ? BlockTypeList[f.type] : BlockTypeList[f];
681
+ }).map(function (f) {
682
+ return f.label && f.style ? f : BlockTypeList[f];
683
+ });
684
+ var inlineStyles = ((config == null ? void 0 : config.inlineStyles) || Object.keys(InlineStylesList)).filter(function (f) {
685
+ return typeof f === "object" ? InlineStylesList[f.type] : InlineStylesList[f];
686
+ }).map(function (f) {
687
+ return f.label && f.style ? f : InlineStylesList[f];
688
+ });
689
+ return {
690
+ fontList: fontList,
691
+ blockTypes: blockTypes,
692
+ inlineStyles: inlineStyles
693
+ };
694
+ };
695
+ return _this;
696
+ }
697
+ _inheritsLoose(RichTextEditor, _Component);
698
+ var _proto = RichTextEditor.prototype;
699
+ _proto.focusEditor = function focusEditor() {
700
+ var _this$editor$current;
701
+ (_this$editor$current = this.editor.current) == null || _this$editor$current.focus();
702
+ };
703
+ _proto.render = function render() {
704
+ var _this$props5 = this.props,
705
+ className = _this$props5.className,
706
+ showFontMenu = _this$props5.showFontMenu,
707
+ showInlineStyleMenu = _this$props5.showInlineStyleMenu,
708
+ showTextFormatMenu = _this$props5.showTextFormatMenu,
709
+ showLinkMenu = _this$props5.showLinkMenu,
710
+ label = _this$props5.label,
711
+ tags = _this$props5.tags,
712
+ editorState = _this$props5.editorState,
713
+ onChange = _this$props5.onChange,
714
+ handleBeforeInput = _this$props5.handleBeforeInput;
715
+ var classNames = cx("editor-root", className);
716
+ return /*#__PURE__*/React.createElement("div", {
717
+ ref: this.wrapperRef
718
+ }, label && /*#__PURE__*/React.createElement(Label, null, label), /*#__PURE__*/React.createElement("div", {
719
+ className: classNames
720
+ }, /*#__PURE__*/React.createElement("div", {
721
+ className: "controls-wrapper"
722
+ }, showFontMenu && /*#__PURE__*/React.createElement(BlockTypeControls, {
723
+ editorState: editorState,
724
+ onToggle: this.toggleSelectBlockType,
725
+ blockTypes: this.getFontListConfigForPanelType("fontList")
726
+ }), showInlineStyleMenu && /*#__PURE__*/React.createElement(InlineStyleControls, {
727
+ editorState: editorState,
728
+ onToggle: this.toggleInlineStyle,
729
+ inlineStyles: this.getFontListConfigForPanelType("inlineStyles")
730
+ }), showTextFormatMenu && /*#__PURE__*/React.createElement(BlockTypeButtonControls, {
731
+ editorState: editorState,
732
+ onToggle: this.toggleButtonBlockType,
733
+ blockTypes: this.getFontListConfigForPanelType("blockTypes")
734
+ }), showLinkMenu && /*#__PURE__*/React.createElement(BlockTypeLinkControls$1, {
735
+ editorState: editorState,
736
+ onToggle: this.toggleLink
737
+ }), tags && tags.length > 0 && /*#__PURE__*/React.createElement(TagControls$1, {
738
+ editorState: editorState,
739
+ tags: tags,
740
+ onInsertTag: this.insertText
741
+ })), /*#__PURE__*/React.createElement("div", {
742
+ className: "editor-wrapper"
743
+ }, /*#__PURE__*/React.createElement(Editor, {
744
+ ref: this.editor,
745
+ editorState: editorState,
746
+ handleKeyCommand: this.handleKeyCommand,
747
+ onChange: onChange,
748
+ handleBeforeInput: handleBeforeInput,
749
+ keyBindingFn: this.keyBindingFn,
750
+ spellCheck: true
751
+ }))));
752
+ };
753
+ return RichTextEditor;
754
+ }(Component);
755
+ RichTextEditor.decorator = decorator;
756
+ var styleShape = function styleShape(configList) {
757
+ return PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOf([].concat(Object.values(configList)))), PropTypes.arrayOf(PropTypes.shape({
758
+ type: PropTypes.oneOf([].concat(Object.values(configList))),
759
+ label: PropTypes.string,
760
+ style: PropTypes.string,
761
+ tooltip: PropTypes.string,
762
+ hotKey: PropTypes.string
763
+ }))]);
764
+ };
765
+ RichTextEditor.propTypes = {
766
+ editorState: PropTypes.object.isRequired,
767
+ onChange: PropTypes.func.isRequired,
768
+ maxTabDepth: PropTypes.number,
769
+ showFontMenu: PropTypes.bool,
770
+ showInlineStyleMenu: PropTypes.bool,
771
+ showTextFormatMenu: PropTypes.bool,
772
+ showLinkMenu: PropTypes.bool,
773
+ label: PropTypes.string,
774
+ tags: /*#__PURE__*/PropTypes.arrayOf(PropTypes.object),
775
+ controlConfigSet: /*#__PURE__*/PropTypes.shape({
776
+ fontList: /*#__PURE__*/styleShape(EditorConfigTypes.FONT_LIST),
777
+ blockTypes: /*#__PURE__*/styleShape(EditorConfigTypes.BLOCK_TYPES),
778
+ inlineStyles: /*#__PURE__*/styleShape(EditorConfigTypes.INLINE_STYLES)
779
+ })
780
+ };
781
+ RichTextEditor.defaultProps = {
782
+ maxTabDepth: 4,
783
+ showFontMenu: true,
784
+ showInlineStyleMenu: true,
785
+ showTextFormatMenu: true,
786
+ showLinkMenu: true,
787
+ label: ""
788
+ };
789
+
790
+ var editorStateToMarkdown = function editorStateToMarkdown(editorState) {
791
+ var rawState = convertToRaw(editorState.getCurrentContent());
792
+ return draftToMarkdown(rawState, {
793
+ preserveNewlines: true
794
+ });
795
+ };
796
+ var markdownToEditorState = function markdownToEditorState(markdown) {
797
+ if (!markdown) {
798
+ return EditorState.createEmpty(decorator);
799
+ }
800
+ var rawState = markdownToDraft(markdown, {
801
+ preserveNewlines: true
802
+ });
803
+ var contentState = convertFromRaw(rawState);
804
+ return EditorState.createWithContent(contentState, decorator);
805
+ };
806
+ var converter = /*#__PURE__*/new showdown.Converter({
807
+ underline: true
808
+ });
809
+ var markdownToHtml = function markdownToHtml(markdown) {
810
+ return converter.makeHtml(markdown);
811
+ };
812
+
813
+ var _excluded = ["name", "title", "languages"];
814
+ var RichTextEditorForLanguage = function RichTextEditorForLanguage(_ref) {
815
+ var _ref$language = _ref.language,
816
+ langKey = _ref$language.value,
817
+ label = _ref$language.label,
818
+ required = _ref$language.required,
819
+ values = _ref.values,
820
+ onChange = _ref.onChange,
821
+ variant = _ref.variant,
822
+ feedback = _ref.feedback,
823
+ tags = _ref.tags;
824
+ var _useState = useState(markdownToEditorState(values[langKey])),
825
+ editorState = _useState[0],
826
+ setEditorState = _useState[1];
827
+ var handleOnChange = function handleOnChange(changedState) {
828
+ var newValues = _extends({}, values);
829
+ var content = editorStateToMarkdown(changedState);
830
+ if (values[langKey] && content === "\n") {
831
+ delete newValues[langKey];
832
+ } else {
833
+ newValues[langKey] = content;
834
+ }
835
+ setEditorState(changedState);
836
+ onChange(newValues);
837
+ };
838
+ var feedbackText = feedback == null ? void 0 : feedback(langKey);
839
+ return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(RichTextEditor, {
840
+ label: required ? label + "*" : label,
841
+ editorState: editorState,
842
+ onChange: function onChange(changedState) {
843
+ return handleOnChange(changedState);
844
+ },
845
+ controlConfigSet: MinifiedConfigTypes,
846
+ tags: tags
847
+ }), variant && feedbackText && feedbackText.length > 0 && (/*#__PURE__*/React.createElement(FeedbackText, {
848
+ variant: variant(langKey)
849
+ }, feedbackText)));
850
+ };
851
+ var ExpandableMultiLanguageRichTextEditor = function ExpandableMultiLanguageRichTextEditor(_ref2) {
852
+ var name = _ref2.name,
853
+ title = _ref2.title,
854
+ languages = _ref2.languages,
855
+ rest = _objectWithoutPropertiesLoose(_ref2, _excluded);
856
+ return /*#__PURE__*/React.createElement(ExpandablePanel, {
857
+ title: title,
858
+ defaultOpen: true,
859
+ contentStyle: {
860
+ padding: "4px 4px 4px 4px",
861
+ marginTop: "16px",
862
+ marginBottom: "16px"
863
+ }
864
+ }, /*#__PURE__*/React.createElement(Stack, {
865
+ space: "medium"
866
+ }, languages.map(function (lang) {
867
+ return /*#__PURE__*/React.createElement("div", {
868
+ key: name + lang.value,
869
+ "data-testid": "multi-lang-rich-text-" + name + "-" + lang.value
870
+ }, /*#__PURE__*/React.createElement(RichTextEditorForLanguage, _extends({
871
+ language: lang
872
+ }, rest)));
873
+ })));
874
+ };
875
+
876
+ var entityToHtml = {
877
+ entityToHTML: function entityToHTML(entity, originalText) {
878
+ if (entity.type === "LINK") {
879
+ return /*#__PURE__*/React.createElement(HtmlLink, {
880
+ url: entity.data.url
881
+ }, originalText);
882
+ }
883
+ return originalText;
884
+ }
885
+ };
886
+ var htmlToEntity = {
887
+ htmlToEntity: function htmlToEntity(nodeName, node, createEntity) {
888
+ if (nodeName === "a") {
889
+ return createEntity("LINK", "MUTABLE", {
890
+ url: node.href
891
+ });
892
+ }
893
+ }
894
+ };
895
+ var htmlToEditorState = function htmlToEditorState(html) {
896
+ if (!html) {
897
+ return EditorState.createEmpty(decorator);
898
+ }
899
+ var rawState = convertFromHTML(htmlToEntity)(html);
900
+ return EditorState.createWithContent(rawState, decorator);
901
+ };
902
+ var editorStateToHtml = function editorStateToHtml(editorState) {
903
+ return convertToHTML(entityToHtml)(editorState.getCurrentContent());
904
+ };
905
+
906
+ export { EditorConfigTypes, ExpandableMultiLanguageRichTextEditor, MinifiedConfigTypes, RichTextEditor, editorStateToHtml, editorStateToMarkdown, htmlToEditorState, markdownToEditorState, markdownToHtml };
907
+ //# sourceMappingURL=rich-text-editor.esm.js.map