redhotmagma-graphics-editor 1.35.8 → 1.36.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.
- package/Components/SelectionToolbox/TextTools.js +4 -2
- package/Components/TextEditor/TextEditor.js +17 -4
- package/Utils/DOM.js +63 -38
- package/package.json +1 -1
- package/src/Components/SelectionToolbox/TextTools.js +2 -0
- package/src/Components/TextEditor/TextEditor.js +12 -1
- package/src/Utils/DOM.ts +39 -17
|
@@ -242,7 +242,8 @@ var TextTools = /*#__PURE__*/function (_React$Component) {
|
|
|
242
242
|
fullTextCommandList = renderObj.fullTextCommandList,
|
|
243
243
|
autoFocusWhenMounted = renderObj.autoFocusWhenMounted,
|
|
244
244
|
canvas = renderObj.canvas,
|
|
245
|
-
textEditorElementProps = renderObj.textEditorElementProps
|
|
245
|
+
textEditorElementProps = renderObj.textEditorElementProps,
|
|
246
|
+
disableLinebreaks = renderObj.disableLinebreaks;
|
|
246
247
|
var selectedCanvasObject = canvas.selectedObject;
|
|
247
248
|
var explicitStyleParams = selectedCanvasObject ? selectedCanvasObject.getExplicitStyleParams() : {};
|
|
248
249
|
var renderTextEditor = _this.props.renderTextEditor;
|
|
@@ -266,7 +267,8 @@ var TextTools = /*#__PURE__*/function (_React$Component) {
|
|
|
266
267
|
fullTextCommandList: fullTextCommandList,
|
|
267
268
|
autoFocusWhenMounted: autoFocusWhenMounted,
|
|
268
269
|
explicitStyleParams: explicitStyleParams,
|
|
269
|
-
elementProps: textEditorElementProps
|
|
270
|
+
elementProps: textEditorElementProps,
|
|
271
|
+
disableLinebreaks: disableLinebreaks
|
|
270
272
|
});
|
|
271
273
|
});
|
|
272
274
|
|
|
@@ -176,8 +176,14 @@ var TextEditor = /*#__PURE__*/function (_React$Component) {
|
|
|
176
176
|
});
|
|
177
177
|
|
|
178
178
|
_defineProperty(_assertThisInitialized(_this), "onKeyDown", function (evt) {
|
|
179
|
-
|
|
179
|
+
var disableLinebreaks = _this.props.disableLinebreaks;
|
|
180
|
+
|
|
181
|
+
if (disableLinebreaks && evt.keyCode === 13) {
|
|
182
|
+
evt.preventDefault();
|
|
183
|
+
} // prevent direct line-breaks
|
|
180
184
|
// it inserts a <br> tag which can lead to wrong structure
|
|
185
|
+
|
|
186
|
+
|
|
181
187
|
if (evt.keyCode === 13 && evt.shiftKey) {
|
|
182
188
|
evt.preventDefault();
|
|
183
189
|
} else if (evt.keyCode === 66 && evt.ctrlKey) {
|
|
@@ -202,7 +208,8 @@ var TextEditor = /*#__PURE__*/function (_React$Component) {
|
|
|
202
208
|
setTimeout(function () {
|
|
203
209
|
var container = _this.contentRef.current;
|
|
204
210
|
var defaultStyle = (0, _get["default"])(_this.props, 'textEditorState.defaultStyle', {});
|
|
205
|
-
|
|
211
|
+
var disableLinebreaks = _this.props.disableLinebreaks;
|
|
212
|
+
(0, _DOM.updatePastedTextNode)(container, disableLinebreaks);
|
|
206
213
|
|
|
207
214
|
var divs = _toConsumableArray(container.childNodes);
|
|
208
215
|
|
|
@@ -452,7 +459,8 @@ var TextEditor = /*#__PURE__*/function (_React$Component) {
|
|
|
452
459
|
value: function componentDidUpdate(prevProps) {
|
|
453
460
|
var _this$props4 = this.props,
|
|
454
461
|
content = _this$props4.content,
|
|
455
|
-
defaultStyle = _this$props4.textEditorState.defaultStyle
|
|
462
|
+
defaultStyle = _this$props4.textEditorState.defaultStyle,
|
|
463
|
+
disableLinebreaks = _this$props4.disableLinebreaks;
|
|
456
464
|
|
|
457
465
|
if (content && content !== prevProps.content) {
|
|
458
466
|
this.setState({
|
|
@@ -465,6 +473,10 @@ var TextEditor = /*#__PURE__*/function (_React$Component) {
|
|
|
465
473
|
if (defaultStyle !== prevProps.textEditorState.defaultStyle) {
|
|
466
474
|
this.updateContent();
|
|
467
475
|
}
|
|
476
|
+
|
|
477
|
+
if (disableLinebreaks && disableLinebreaks !== prevProps.disableLinebreaks) {
|
|
478
|
+
(0, _DOM.removeLinebreaks)(this.contentRef.current);
|
|
479
|
+
}
|
|
468
480
|
}
|
|
469
481
|
}, {
|
|
470
482
|
key: "wrapSingleTextNodeWithStyle",
|
|
@@ -584,7 +596,8 @@ var TextEditor = /*#__PURE__*/function (_React$Component) {
|
|
|
584
596
|
exports.TextEditor = TextEditor;
|
|
585
597
|
|
|
586
598
|
_defineProperty(TextEditor, "defaultProps", {
|
|
587
|
-
autoFocusWhenMounted: true
|
|
599
|
+
autoFocusWhenMounted: true,
|
|
600
|
+
disableLinebreaks: false
|
|
588
601
|
});
|
|
589
602
|
|
|
590
603
|
var _default = (0, _TextEditorStateProvider.withTextEditorState)(TextEditor);
|
package/Utils/DOM.js
CHANGED
|
@@ -10,7 +10,7 @@ exports.getFirstEndNode = getFirstEndNode;
|
|
|
10
10
|
exports.getLastEndNode = getLastEndNode;
|
|
11
11
|
exports.getNextNode = getNextNode;
|
|
12
12
|
exports.fixContentEditableDOM = fixContentEditableDOM;
|
|
13
|
-
exports.traverse = exports.updateTextWrapper = exports.updatePastedTextNode = exports.placeCaretAtEnd = exports.getClosestAttribute = void 0;
|
|
13
|
+
exports.traverse = exports.updateTextWrapper = exports.removeLinebreaks = exports.updatePastedTextNode = exports.placeCaretAtEnd = exports.getClosestAttribute = void 0;
|
|
14
14
|
|
|
15
15
|
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
|
|
16
16
|
|
|
@@ -120,55 +120,80 @@ var placeCaretAtEnd = function placeCaretAtEnd(el) {
|
|
|
120
120
|
|
|
121
121
|
exports.placeCaretAtEnd = placeCaretAtEnd;
|
|
122
122
|
|
|
123
|
-
var updatePastedTextNode = function updatePastedTextNode(rootNode) {
|
|
123
|
+
var updatePastedTextNode = function updatePastedTextNode(rootNode, disableLinebreaks) {
|
|
124
124
|
var divs = rootNode.childNodes;
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
126
|
+
if (disableLinebreaks) {
|
|
127
|
+
removeLinebreaks(rootNode);
|
|
128
|
+
} else {
|
|
129
|
+
var _iterator = _createForOfIteratorHelper(divs),
|
|
130
|
+
_step;
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
134
|
+
var child = _step.value;
|
|
135
|
+
// get the text nodes and wrap it in Div and span in order to apply styles
|
|
136
|
+
var text = child.textContent || '';
|
|
137
|
+
|
|
138
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
139
|
+
if ((text.match(/\n/g) || []).length) {
|
|
140
|
+
// To support multi line
|
|
141
|
+
var textElements = text.split('\n');
|
|
142
|
+
|
|
143
|
+
var _iterator2 = _createForOfIteratorHelper(textElements),
|
|
144
|
+
_step2;
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
148
|
+
var element = _step2.value;
|
|
149
|
+
var textWrapper = document.createElement('span');
|
|
150
|
+
var wrapperDiv = document.createElement('div');
|
|
151
|
+
textWrapper.innerText = element.trim();
|
|
152
|
+
wrapperDiv.appendChild(textWrapper);
|
|
153
|
+
child.parentNode && child.parentNode.insertBefore(wrapperDiv, child);
|
|
154
|
+
placeCaretAtEnd(textWrapper);
|
|
155
|
+
}
|
|
156
|
+
} catch (err) {
|
|
157
|
+
_iterator2.e(err);
|
|
158
|
+
} finally {
|
|
159
|
+
_iterator2.f();
|
|
152
160
|
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
} finally {
|
|
156
|
-
_iterator2.f();
|
|
161
|
+
} else {
|
|
162
|
+
updateTextWrapper(child);
|
|
157
163
|
}
|
|
158
|
-
} else {
|
|
159
|
-
updateTextWrapper(child);
|
|
160
164
|
}
|
|
161
165
|
}
|
|
166
|
+
} catch (err) {
|
|
167
|
+
_iterator.e(err);
|
|
168
|
+
} finally {
|
|
169
|
+
_iterator.f();
|
|
162
170
|
}
|
|
163
|
-
} catch (err) {
|
|
164
|
-
_iterator.e(err);
|
|
165
|
-
} finally {
|
|
166
|
-
_iterator.f();
|
|
167
171
|
}
|
|
168
172
|
};
|
|
169
173
|
|
|
170
174
|
exports.updatePastedTextNode = updatePastedTextNode;
|
|
171
175
|
|
|
176
|
+
var removeLinebreaks = function removeLinebreaks(rootNode) {
|
|
177
|
+
var divs = rootNode.childNodes;
|
|
178
|
+
divs.forEach(function (child, key) {
|
|
179
|
+
if (key !== 0) {
|
|
180
|
+
if (rootNode.firstChild) {
|
|
181
|
+
var parentText = rootNode.firstChild.textContent || '';
|
|
182
|
+
var childText = child.textContent || '';
|
|
183
|
+
rootNode.firstChild.textContent = "".concat(parentText, " ").concat(childText);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
rootNode.removeChild(child);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
if (rootNode && rootNode.textContent) {
|
|
191
|
+
rootNode.textContent = rootNode.textContent.split('\n').join(' ');
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
exports.removeLinebreaks = removeLinebreaks;
|
|
196
|
+
|
|
172
197
|
var updateTextWrapper = function updateTextWrapper(child) {
|
|
173
198
|
var textWrapper = document.createElement('span');
|
|
174
199
|
var wrapperDiv = document.createElement('div');
|
package/package.json
CHANGED
|
@@ -289,6 +289,7 @@ export class TextTools extends React.Component {
|
|
|
289
289
|
autoFocusWhenMounted,
|
|
290
290
|
canvas,
|
|
291
291
|
textEditorElementProps,
|
|
292
|
+
disableLinebreaks,
|
|
292
293
|
} = renderObj;
|
|
293
294
|
const { selectedObject: selectedCanvasObject } = canvas;
|
|
294
295
|
const explicitStyleParams = selectedCanvasObject ? selectedCanvasObject.getExplicitStyleParams() : {};
|
|
@@ -314,6 +315,7 @@ export class TextTools extends React.Component {
|
|
|
314
315
|
autoFocusWhenMounted={autoFocusWhenMounted}
|
|
315
316
|
explicitStyleParams={explicitStyleParams}
|
|
316
317
|
elementProps={textEditorElementProps}
|
|
318
|
+
disableLinebreaks={disableLinebreaks}
|
|
317
319
|
/>
|
|
318
320
|
);
|
|
319
321
|
};
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
getFirstEndNode,
|
|
7
7
|
updatePastedTextNode,
|
|
8
8
|
placeCaretAtEnd,
|
|
9
|
+
removeLinebreaks,
|
|
9
10
|
} from '../../Utils/DOM';
|
|
10
11
|
import { getNodesInRange, selectAll } from '../../Utils/Range';
|
|
11
12
|
import { withTextEditorState } from './TextEditorStateProvider';
|
|
@@ -13,6 +14,7 @@ import { withTextEditorState } from './TextEditorStateProvider';
|
|
|
13
14
|
export class TextEditor extends React.Component {
|
|
14
15
|
static defaultProps = {
|
|
15
16
|
autoFocusWhenMounted: true,
|
|
17
|
+
disableLinebreaks: false,
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
state = {
|
|
@@ -69,6 +71,7 @@ export class TextEditor extends React.Component {
|
|
|
69
71
|
const {
|
|
70
72
|
content,
|
|
71
73
|
textEditorState: { defaultStyle },
|
|
74
|
+
disableLinebreaks,
|
|
72
75
|
} = this.props;
|
|
73
76
|
if (content && content !== prevProps.content) {
|
|
74
77
|
this.setState({
|
|
@@ -80,6 +83,9 @@ export class TextEditor extends React.Component {
|
|
|
80
83
|
if (defaultStyle !== prevProps.textEditorState.defaultStyle) {
|
|
81
84
|
this.updateContent();
|
|
82
85
|
}
|
|
86
|
+
if (disableLinebreaks && disableLinebreaks !== prevProps.disableLinebreaks) {
|
|
87
|
+
removeLinebreaks(this.contentRef.current);
|
|
88
|
+
}
|
|
83
89
|
}
|
|
84
90
|
|
|
85
91
|
selectionChangeListener = () => {
|
|
@@ -243,6 +249,10 @@ export class TextEditor extends React.Component {
|
|
|
243
249
|
};
|
|
244
250
|
|
|
245
251
|
onKeyDown = evt => {
|
|
252
|
+
const { disableLinebreaks } = this.props;
|
|
253
|
+
if (disableLinebreaks && evt.keyCode === 13) {
|
|
254
|
+
evt.preventDefault();
|
|
255
|
+
}
|
|
246
256
|
// prevent direct line-breaks
|
|
247
257
|
// it inserts a <br> tag which can lead to wrong structure
|
|
248
258
|
if (evt.keyCode === 13 && evt.shiftKey) {
|
|
@@ -267,7 +277,8 @@ export class TextEditor extends React.Component {
|
|
|
267
277
|
setTimeout(() => {
|
|
268
278
|
const container = this.contentRef.current;
|
|
269
279
|
const defaultStyle = get(this.props, 'textEditorState.defaultStyle', {});
|
|
270
|
-
|
|
280
|
+
const { disableLinebreaks } = this.props;
|
|
281
|
+
updatePastedTextNode(container, disableLinebreaks);
|
|
271
282
|
const divs = [...container.childNodes];
|
|
272
283
|
divs.forEach(div => {
|
|
273
284
|
div.dataset && this.setNodeData(div, 'color', defaultStyle.color.identifier);
|
package/src/Utils/DOM.ts
CHANGED
|
@@ -88,30 +88,52 @@ export const placeCaretAtEnd = (el: HTMLElement) => {
|
|
|
88
88
|
}
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
-
export const updatePastedTextNode = (rootNode: HTMLElement) => {
|
|
91
|
+
export const updatePastedTextNode = (rootNode: HTMLElement, disableLinebreaks: boolean) => {
|
|
92
92
|
const divs = rootNode.childNodes;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
93
|
+
if (disableLinebreaks) {
|
|
94
|
+
removeLinebreaks(rootNode);
|
|
95
|
+
} else {
|
|
96
|
+
for (const child of divs) {
|
|
97
|
+
// get the text nodes and wrap it in Div and span in order to apply styles
|
|
98
|
+
const text = child.textContent || '';
|
|
99
|
+
if (child.nodeType === Node.TEXT_NODE) {
|
|
100
|
+
if ((text.match(/\n/g) || []).length) {
|
|
101
|
+
// To support multi line
|
|
102
|
+
const textElements = text.split('\n');
|
|
103
|
+
for (const element of textElements) {
|
|
104
|
+
const textWrapper = document.createElement('span');
|
|
105
|
+
const wrapperDiv = document.createElement('div');
|
|
106
|
+
textWrapper.innerText = element.trim();
|
|
107
|
+
wrapperDiv.appendChild(textWrapper);
|
|
108
|
+
child.parentNode && child.parentNode.insertBefore(wrapperDiv, child);
|
|
109
|
+
placeCaretAtEnd(textWrapper);
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
updateTextWrapper(child);
|
|
107
113
|
}
|
|
108
|
-
} else {
|
|
109
|
-
updateTextWrapper(child);
|
|
110
114
|
}
|
|
111
115
|
}
|
|
112
116
|
}
|
|
113
117
|
};
|
|
114
118
|
|
|
119
|
+
export const removeLinebreaks = (rootNode: HTMLElement) => {
|
|
120
|
+
const divs = rootNode.childNodes;
|
|
121
|
+
divs.forEach((child, key) => {
|
|
122
|
+
if (key !== 0) {
|
|
123
|
+
if (rootNode.firstChild) {
|
|
124
|
+
const parentText = rootNode.firstChild.textContent || '';
|
|
125
|
+
const childText = child.textContent || '';
|
|
126
|
+
rootNode.firstChild.textContent = `${parentText} ${childText}`;
|
|
127
|
+
}
|
|
128
|
+
rootNode.removeChild(child);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
if (rootNode && rootNode.textContent) {
|
|
133
|
+
rootNode.textContent = rootNode.textContent.split('\n').join(' ');
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
115
137
|
export const updateTextWrapper = (child: ChildNode) => {
|
|
116
138
|
const textWrapper = document.createElement('span');
|
|
117
139
|
const wrapperDiv = document.createElement('div');
|