@zzish/math-rich-input 0.1.56 → 0.1.57

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/dist/index.js CHANGED
@@ -169,6 +169,57 @@ function _arrayLikeToArray(arr, len) {
169
169
  function _nonIterableSpread() {
170
170
  throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
171
171
  }
172
+ function _createForOfIteratorHelper(o, allowArrayLike) {
173
+ var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
174
+ if (!it) {
175
+ if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
176
+ if (it) o = it;
177
+ var i = 0;
178
+ var F = function () {};
179
+ return {
180
+ s: F,
181
+ n: function () {
182
+ if (i >= o.length) return {
183
+ done: true
184
+ };
185
+ return {
186
+ done: false,
187
+ value: o[i++]
188
+ };
189
+ },
190
+ e: function (e) {
191
+ throw e;
192
+ },
193
+ f: F
194
+ };
195
+ }
196
+ throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
197
+ }
198
+ var normalCompletion = true,
199
+ didErr = false,
200
+ err;
201
+ return {
202
+ s: function () {
203
+ it = it.call(o);
204
+ },
205
+ n: function () {
206
+ var step = it.next();
207
+ normalCompletion = step.done;
208
+ return step;
209
+ },
210
+ e: function (e) {
211
+ didErr = true;
212
+ err = e;
213
+ },
214
+ f: function () {
215
+ try {
216
+ if (!normalCompletion && it.return != null) it.return();
217
+ } finally {
218
+ if (didErr) throw err;
219
+ }
220
+ }
221
+ };
222
+ }
172
223
 
173
224
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
174
225
 
@@ -21972,6 +22023,229 @@ function plainTextOffsetToGlobalOffset(editableDiv, plainTextOffset) {
21972
22023
  */
21973
22024
  var SELECTION_MARK = MARK$1;
21974
22025
 
22026
+ /**
22027
+ * Capture browser editing intent in the logical text coordinates used by MathRichInput.
22028
+ *
22029
+ * The component deliberately reports a measured replacement range instead of asking a host to diff the
22030
+ * old and new strings. A host can therefore retain two equal names independently and reject a stale
22031
+ * event before it changes protected content.
22032
+ */
22033
+
22034
+ var ZERO_WIDTH_SPACE = "\u200B";
22035
+ var BLOCK_TAGS = new Set(["p", "div", "section", "article", "blockquote", "pre", "li", "ul", "ol", "h1", "h2", "h3", "h4", "h5", "h6", "table", "thead", "tbody", "tfoot", "tr", "td", "th", "hr"]);
22036
+ var INERT_TAGS = new Set(["script", "style", "template", "head", "title"]);
22037
+
22038
+ /** Return whether a node is the rendered KaTeX island that cannot be edited character by character. */
22039
+ function isMathNode(node) {
22040
+ var _node$classList, _node$classList2;
22041
+ return node && node.nodeType === 1 && (((_node$classList = node.classList) === null || _node$classList === void 0 ? void 0 : _node$classList.contains("katex")) || ((_node$classList2 = node.classList) === null || _node$classList2 === void 0 ? void 0 : _node$classList2.contains("katex-error")));
22042
+ }
22043
+
22044
+ /** Return whether a tag contributes a logical line boundary to the source text. */
22045
+ function isBlock(node) {
22046
+ if (!node || node.nodeType !== 1) return false;
22047
+ return BLOCK_TAGS.has(node.tagName.toLowerCase());
22048
+ }
22049
+ function isInert(node) {
22050
+ if (!node || node.nodeType !== 1) return false;
22051
+ return INERT_TAGS.has(node.tagName.toLowerCase());
22052
+ }
22053
+ function trimZeroWidth(value) {
22054
+ return value.split(ZERO_WIDTH_SPACE).join("");
22055
+ }
22056
+
22057
+ /** Build the text coordinate string without reading attributes or rendered math markup. */
22058
+ function editableText(root) {
22059
+ if (!root) return "";
22060
+ var pieces = [];
22061
+ var pendingBoundary = false;
22062
+ var walk = function walk(node) {
22063
+ if (isInert(node)) return;
22064
+ if (isMathNode(node)) {
22065
+ var _node$querySelector;
22066
+ if (pendingBoundary && pieces.length && pieces[pieces.length - 1] !== "\n") pieces.push("\n");
22067
+ var latex = ((_node$querySelector = node.querySelector) === null || _node$querySelector === void 0 || (_node$querySelector = _node$querySelector.call(node, 'annotation[encoding="application/x-tex"]')) === null || _node$querySelector === void 0 ? void 0 : _node$querySelector.textContent) || "";
22068
+ pieces.push(latex);
22069
+ pendingBoundary = false;
22070
+ return;
22071
+ }
22072
+ if (node.nodeType === 3) {
22073
+ var text = trimZeroWidth(node.nodeValue || "");
22074
+ if (text && pendingBoundary && pieces.length && pieces[pieces.length - 1] !== "\n") pieces.push("\n");
22075
+ if (text) pieces.push(text);
22076
+ if (text) pendingBoundary = false;
22077
+ return;
22078
+ }
22079
+ if (node.nodeType !== 1 && node.nodeType !== 11) return;
22080
+ if (node.nodeType === 1 && node.tagName.toLowerCase() === "br") {
22081
+ pieces.push("\n");
22082
+ pendingBoundary = false;
22083
+ return;
22084
+ }
22085
+ var block = isBlock(node);
22086
+ if (block && pieces.length) pendingBoundary = true;
22087
+ var _iterator = _createForOfIteratorHelper(node.childNodes || []),
22088
+ _step;
22089
+ try {
22090
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
22091
+ var child = _step.value;
22092
+ walk(child);
22093
+ }
22094
+ } catch (err) {
22095
+ _iterator.e(err);
22096
+ } finally {
22097
+ _iterator.f();
22098
+ }
22099
+ if (block) pendingBoundary = true;
22100
+ };
22101
+ var _iterator2 = _createForOfIteratorHelper(root.childNodes || []),
22102
+ _step2;
22103
+ try {
22104
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
22105
+ var child = _step2.value;
22106
+ walk(child);
22107
+ }
22108
+ } catch (err) {
22109
+ _iterator2.e(err);
22110
+ } finally {
22111
+ _iterator2.f();
22112
+ }
22113
+ return pieces.join("");
22114
+ }
22115
+ function textBeforeEndpoint(root, container, offset) {
22116
+ if (!root || !container || !root.contains(container)) return null;
22117
+ var range = document.createRange();
22118
+ range.selectNodeContents(root);
22119
+ try {
22120
+ range.setEnd(container, offset);
22121
+ } catch (_error) {
22122
+ return null;
22123
+ }
22124
+ var clone = document.createElement("span");
22125
+ clone.appendChild(range.cloneContents());
22126
+ return editableText(clone).length;
22127
+ }
22128
+
22129
+ /** Read a collapsed or selected DOM range in logical UTF-16 offsets. */
22130
+ function selectionOffsets(root) {
22131
+ var _window$getSelection, _window;
22132
+ var selection = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : (_window$getSelection = (_window = window).getSelection) === null || _window$getSelection === void 0 ? void 0 : _window$getSelection.call(_window);
22133
+ if (!root || !selection || selection.rangeCount === 0) return null;
22134
+ var range = selection.getRangeAt(0);
22135
+ var from = textBeforeEndpoint(root, range.startContainer, range.startOffset);
22136
+ var to = textBeforeEndpoint(root, range.endContainer, range.endOffset);
22137
+ if (from === null || to === null) return null;
22138
+ return from <= to ? {
22139
+ from: from,
22140
+ to: to
22141
+ } : {
22142
+ from: to,
22143
+ to: from
22144
+ };
22145
+ }
22146
+ function expandSurrogateBoundary(text, from, to) {
22147
+ var before = text.charCodeAt(from - 1);
22148
+ var after = text.charCodeAt(from);
22149
+ if (before >= 0xd800 && before <= 0xdbff && after >= 0xdc00 && after <= 0xdfff) {
22150
+ return {
22151
+ from: from - 1,
22152
+ to: Math.max(to, from + 1)
22153
+ };
22154
+ }
22155
+ var at = text.charCodeAt(to - 1);
22156
+ var next = text.charCodeAt(to);
22157
+ if (at >= 0xd800 && at <= 0xdbff && next >= 0xdc00 && next <= 0xdfff) {
22158
+ return {
22159
+ from: Math.min(from, to - 1),
22160
+ to: to + 1
22161
+ };
22162
+ }
22163
+ return {
22164
+ from: from,
22165
+ to: to
22166
+ };
22167
+ }
22168
+ function textFromTransfer(dataTransfer) {
22169
+ var _dataTransfer$getData, _dataTransfer$getData2;
22170
+ if (!dataTransfer) return "";
22171
+ var plain = ((_dataTransfer$getData = dataTransfer.getData) === null || _dataTransfer$getData === void 0 ? void 0 : _dataTransfer$getData.call(dataTransfer, "text/plain")) || "";
22172
+ if (plain) return plain;
22173
+ var html = ((_dataTransfer$getData2 = dataTransfer.getData) === null || _dataTransfer$getData2 === void 0 ? void 0 : _dataTransfer$getData2.call(dataTransfer, "text/html")) || "";
22174
+ if (!html || typeof document === "undefined") return "";
22175
+ var probe = document.createElement("div");
22176
+ probe.innerHTML = html;
22177
+ return editableText(probe);
22178
+ }
22179
+
22180
+ /**
22181
+ * Convert a browser `beforeinput` event into an explicit replacement.
22182
+ *
22183
+ * A null return means the browser supplied no safe range or the operation is outside the supported text
22184
+ * edits. The caller still emits the intent, without an edit, so a protected host can refuse it loudly.
22185
+ */
22186
+ function transactionFromBeforeInput(root, event) {
22187
+ var _event$data;
22188
+ var compositionStart = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
22189
+ var before = editableText(root);
22190
+ var selection = selectionOffsets(root);
22191
+ if (!selection) return {
22192
+ before: before,
22193
+ intent: intentForInputType(event === null || event === void 0 ? void 0 : event.inputType),
22194
+ edit: null
22195
+ };
22196
+ var inputType = (event === null || event === void 0 ? void 0 : event.inputType) || "insertText";
22197
+ var intent = intentForInputType(inputType);
22198
+ var from = selection.from,
22199
+ to = selection.to;
22200
+ var insert = (_event$data = event === null || event === void 0 ? void 0 : event.data) !== null && _event$data !== void 0 ? _event$data : "";
22201
+ if (inputType === "insertFromPaste" || inputType === "insertFromDrop") {
22202
+ insert = textFromTransfer(event === null || event === void 0 ? void 0 : event.dataTransfer);
22203
+ } else if (inputType === "insertLineBreak" || inputType === "insertParagraph") {
22204
+ insert = "\n";
22205
+ } else if (inputType === "deleteContentBackward" && from === to) {
22206
+ var _expandSurrogateBound = expandSurrogateBoundary(before, Math.max(0, from - 1), from);
22207
+ from = _expandSurrogateBound.from;
22208
+ to = _expandSurrogateBound.to;
22209
+ } else if (inputType === "deleteContentForward" && from === to) {
22210
+ var _expandSurrogateBound2 = expandSurrogateBoundary(before, from, Math.min(before.length, to + 1));
22211
+ from = _expandSurrogateBound2.from;
22212
+ to = _expandSurrogateBound2.to;
22213
+ } else if (inputType.startsWith("delete") && from === to) {
22214
+ return {
22215
+ before: before,
22216
+ intent: intent,
22217
+ edit: null
22218
+ };
22219
+ }
22220
+ var base = compositionStart && intent === "composition" ? compositionStart : {
22221
+ before: before,
22222
+ from: from,
22223
+ to: to
22224
+ };
22225
+ return {
22226
+ before: base.before,
22227
+ intent: intent,
22228
+ edit: {
22229
+ before: base.before,
22230
+ from: base.from,
22231
+ to: base.to,
22232
+ insert: insert
22233
+ }
22234
+ };
22235
+ }
22236
+
22237
+ /** Give hosts a stable vocabulary while preserving the browser's native inputType for diagnostics. */
22238
+ function intentForInputType(inputType) {
22239
+ if (!inputType) return "input";
22240
+ if (inputType.includes("Composition")) return "composition";
22241
+ if (inputType.includes("Paste")) return "paste";
22242
+ if (inputType.includes("Drop")) return "drop";
22243
+ if (inputType.includes("Cut")) return "cut";
22244
+ if (inputType === "historyUndo") return "undo";
22245
+ if (inputType === "historyRedo") return "redo";
22246
+ return "input";
22247
+ }
22248
+
21975
22249
  var MIME_TYPE_PLAIN_TEXT = "text/plain";
21976
22250
  var MIME_TYPE_HTML = "text/html";
21977
22251
  var MIME_TYPE_TEX = "application/x-tex";
@@ -22178,23 +22452,34 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22178
22452
  var options = _this2.props.options || DEFAULT_OPTIONS;
22179
22453
  if (isExpertMode === null) isExpertMode = options.isExpertMode;
22180
22454
  if (selectedTab === null) selectedTab = options.selectedTab;
22181
-
22182
- // Add this to the history
22183
- _this2.undoHistory.push({
22455
+ var transaction = applyOptions.transaction || null;
22456
+ var historyState = {
22184
22457
  value: value,
22185
22458
  mimeType: mimeType,
22186
- rangeParams: rangeParams
22187
- });
22188
- if (_this2.undoHistory.length > MAX_HISTORY_LENGTH) _this2.undoHistory.shift();
22459
+ rangeParams: rangeParams,
22460
+ transaction: transaction
22461
+ };
22462
+ if (applyOptions.recordHistory !== false) {
22463
+ // Add this to the history. The transaction is retained beside the rendered value so a host can
22464
+ // restore annotation snapshots on undo/redo instead of interpreting an inverse spelling anew.
22465
+ _this2.undoHistory.push(historyState);
22466
+ if (_this2.undoHistory.length > MAX_HISTORY_LENGTH) _this2.undoHistory.shift();
22467
+ }
22189
22468
 
22190
22469
  // Debug what's being passed to parent
22191
22470
  // console.log("APPLY CHANGES:", { value, mimeType });
22192
22471
 
22193
22472
  // Call the parent handler to apply the changes
22194
- _this2.onChangeCallback({
22473
+ _this2.onChangeCallback(_objectSpread2(_objectSpread2(_objectSpread2({
22195
22474
  value: value,
22196
22475
  mimeType: mimeType
22197
- }, {
22476
+ }, transaction !== null && transaction !== void 0 && transaction.edit ? {
22477
+ edit: transaction.edit
22478
+ } : {}), transaction !== null && transaction !== void 0 && transaction.intent ? {
22479
+ intent: transaction.intent
22480
+ } : {}), transaction !== null && transaction !== void 0 && transaction.history ? {
22481
+ history: transaction.history
22482
+ } : {}), {
22198
22483
  isExpertMode: isExpertMode,
22199
22484
  selectedTab: selectedTab
22200
22485
  });
@@ -22219,7 +22504,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22219
22504
  if (_this2.initialHistoryState == null) _this2.initialHistoryState = {
22220
22505
  value: _this2.props.value,
22221
22506
  mimeType: _this2.props.mimeType,
22222
- rangeParams: _this2._getRangeParams()
22507
+ rangeParams: _this2._getRangeParams(),
22508
+ transaction: null
22223
22509
  };
22224
22510
  });
22225
22511
  _defineProperty(_this2, "resetHistoryRedo", function () {
@@ -22238,23 +22524,60 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22238
22524
  return true;
22239
22525
  });
22240
22526
  _defineProperty(_this2, "undo", function () {
22241
- var currentState = _this2.undoHistory.pop();
22242
- var previousState = _this2.undoHistory.pop();
22243
- if (previousState === null || previousState === undefined) {
22244
- previousState = _this2.initialHistoryState;
22245
- }
22246
- if (_this2.redoHistory.length > 0) {
22247
- var redoLast = _this2.redoHistory[_this2.redoHistory.length - 1];
22248
- if (!_this2.deepEqual(redoLast, currentState)) _this2.redoHistory.push(currentState);
22249
- } else _this2.redoHistory.push(currentState);
22250
- _this2.applyChangesToComponent(previousState.value, previousState.mimeType, previousState.rangeParams);
22527
+ var currentState = _this2.undoHistory[_this2.undoHistory.length - 1];
22528
+ if (!currentState) return;
22529
+ _this2.undoHistory.pop();
22530
+ var previousState = _this2.undoHistory[_this2.undoHistory.length - 1] || _this2.initialHistoryState;
22531
+ if (!previousState) return;
22532
+ _this2.redoHistory.push(currentState);
22533
+ var transaction = _this2.historyTransaction(currentState, "undo");
22534
+ _this2.applyChangesToComponent(previousState.value, previousState.mimeType, previousState.rangeParams, null, null, {
22535
+ transaction: transaction,
22536
+ recordHistory: false
22537
+ });
22251
22538
  });
22252
22539
  _defineProperty(_this2, "redo", function () {
22253
22540
  var redoState = _this2.redoHistory.pop();
22254
- if (redoState !== null & redoState !== undefined) {
22255
- _this2.applyChangesToComponent(redoState.value, redoState.mimeType, redoState.rangeParams);
22541
+ if (redoState !== null && redoState !== undefined) {
22542
+ _this2.applyChangesToComponent(redoState.value, redoState.mimeType, redoState.rangeParams, null, null, {
22543
+ transaction: _this2.historyTransaction(redoState, "redo"),
22544
+ recordHistory: false
22545
+ });
22546
+ _this2.undoHistory.push(redoState);
22256
22547
  }
22257
22548
  });
22549
+ /** Build an explicit forward/inverse transaction for one history entry. */
22550
+ _defineProperty(_this2, "historyTransaction", function (state, direction) {
22551
+ var _original$history;
22552
+ var original = state === null || state === void 0 ? void 0 : state.transaction;
22553
+ if (!(original !== null && original !== void 0 && (_original$history = original.history) !== null && _original$history !== void 0 && _original$history.id) || !original.edit) {
22554
+ return {
22555
+ intent: direction,
22556
+ history: original !== null && original !== void 0 && original.history ? {
22557
+ id: original.history.id,
22558
+ direction: direction
22559
+ } : undefined
22560
+ };
22561
+ }
22562
+ var edit = original.edit;
22563
+ var after = edit.before.slice(0, edit.from) + edit.insert + edit.before.slice(edit.to);
22564
+ var inverse = _objectSpread2({
22565
+ before: after,
22566
+ from: edit.from,
22567
+ to: edit.from + edit.insert.length,
22568
+ insert: edit.before.slice(edit.from, edit.to)
22569
+ }, edit.boundary ? {
22570
+ boundary: edit.boundary
22571
+ } : {});
22572
+ return {
22573
+ intent: direction,
22574
+ history: {
22575
+ id: original.history.id,
22576
+ direction: direction
22577
+ },
22578
+ edit: direction === "undo" ? inverse : edit
22579
+ };
22580
+ });
22258
22581
  _defineProperty(_this2, "_setRangeParams", function (params) {
22259
22582
  try {
22260
22583
  debugMathRichInput("MathRichInput:_setRangeParams:start", {
@@ -22295,6 +22618,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22295
22618
  restore(50);
22296
22619
  });
22297
22620
  _defineProperty(_this2, "handleKeyDownBackspace", function (e) {
22621
+ var beforeText = editableText(_this2.editableDiv);
22298
22622
  var rangeParams = _this2._getRangeParams();
22299
22623
  var start_node_index = rangeParams.startNodeIndex;
22300
22624
  var end_node_index = rangeParams.endNodeIndex;
@@ -22331,7 +22655,21 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
22331
22655
  startGlobalOffset: 0,
22332
22656
  endGlobalOffset: 0
22333
22657
  };
22334
- _this2.applyChangesToComponent("", _this2.getMimeType(false, false), _new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
22658
+ _this2.applyChangesToComponent("", _this2.getMimeType(false, false), _new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab, {
22659
+ transaction: {
22660
+ edit: {
22661
+ before: beforeText,
22662
+ from: 0,
22663
+ to: beforeText.length,
22664
+ insert: ""
22665
+ },
22666
+ intent: "cut",
22667
+ history: {
22668
+ id: "mri-".concat(++_this2.historySequence),
22669
+ direction: "forward"
22670
+ }
22671
+ }
22672
+ });
22335
22673
  e.preventDefault();
22336
22674
  return;
22337
22675
  }
@@ -23188,6 +23526,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
23188
23526
  try {
23189
23527
  // console.log("handleInput")
23190
23528
  if (_this2.isComposing) return;
23529
+ var transaction = _this2.pendingTransaction;
23530
+ _this2.pendingTransaction = null;
23191
23531
  debugMathRichInput("handleInput:start", {
23192
23532
  inputType: event && event.nativeEvent ? event.nativeEvent.inputType : null,
23193
23533
  data: event && event.nativeEvent ? event.nativeEvent.data : null,
@@ -23224,7 +23564,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
23224
23564
  _raw_text = removeEncodingIfPlainText(_raw_text, _mimeType, _this2.enableHtml());
23225
23565
  _raw_text = _this2.stripEmptyInlineFormattingTags(_raw_text);
23226
23566
  _this2.applyChangesToComponent(_raw_text, _mimeType, defaultParams, _this2.props.useExpertMode, _this2.props.selectedTab, {
23227
- skipControlledRender: true
23567
+ skipControlledRender: true,
23568
+ transaction: transaction
23228
23569
  });
23229
23570
  return;
23230
23571
  } else if (params.startNodeIndex === null || params.startNodeIndex === undefined) {
@@ -23259,7 +23600,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
23259
23600
  };
23260
23601
  _this2.setOldRangeParams(validParams);
23261
23602
  _this2.applyChangesToComponent(raw_text, mimeType, validParams, _this2.props.useExpertMode, _this2.props.selectedTab, {
23262
- skipControlledRender: true
23603
+ skipControlledRender: true,
23604
+ transaction: transaction
23263
23605
  });
23264
23606
  debugMathRichInput("handleInput:after-apply", {
23265
23607
  raw_text: raw_text,
@@ -23356,6 +23698,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
23356
23698
  });
23357
23699
  _defineProperty(_this2, "handlePaste", function (event) {
23358
23700
  try {
23701
+ _this2.pendingTransaction = null;
23359
23702
  var clipboardData = event.clipboardData || window.clipboardData;
23360
23703
  if (!clipboardData) {
23361
23704
  return;
@@ -23380,6 +23723,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
23380
23723
  console.warn("Could not get range params for paste");
23381
23724
  return;
23382
23725
  }
23726
+ var beforePaste = editableText(_this2.editableDiv);
23727
+ var pasteSelection = _this2.captureSelectionOffsets();
23383
23728
 
23384
23729
  // Store old range params for cursor positioning (like equation editor)
23385
23730
  _this2.setOldRangeParams(rangeParams);
@@ -23605,7 +23950,34 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
23605
23950
  var cleanedRawText = removeEncodingIfPlainText(newRawText, actualMimeType, _this2.enableHtml());
23606
23951
 
23607
23952
  // Apply the change using the component's standard flow
23608
- _this2.applyChangesToComponent(cleanedRawText, actualMimeType, newRangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
23953
+ var insertionText = function () {
23954
+ if (!/<[^>]+>/.test(finalText)) return finalText;
23955
+ var probe = document.createElement("div");
23956
+ probe.innerHTML = finalText;
23957
+ return editableText(probe).replace(/\ufffc/g, "");
23958
+ }();
23959
+ var transaction = pasteSelection ? {
23960
+ edit: {
23961
+ before: beforePaste,
23962
+ from: pasteSelection.from,
23963
+ to: pasteSelection.to,
23964
+ insert: insertionText
23965
+ },
23966
+ intent: "paste",
23967
+ history: {
23968
+ id: "mri-".concat(++_this2.historySequence),
23969
+ direction: "forward"
23970
+ }
23971
+ } : {
23972
+ intent: "paste",
23973
+ history: {
23974
+ id: "mri-".concat(++_this2.historySequence),
23975
+ direction: "forward"
23976
+ }
23977
+ };
23978
+ _this2.applyChangesToComponent(cleanedRawText, actualMimeType, newRangeParams, _this2.props.useExpertMode, _this2.props.selectedTab, {
23979
+ transaction: transaction
23980
+ });
23609
23981
 
23610
23982
  // A paste cannot rely on being re-rendered. It removed the selected content from the DOM itself,
23611
23983
  // and if the host already holds the value being applied — the same words pasted back into the
@@ -23966,10 +24338,22 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
23966
24338
  }
23967
24339
  }
23968
24340
  var rangeParams = _this2._getRangeParams();
23969
- var removedEmptyTags = !insertedTypingStylePlaceholder && _this2.cleanupEmptyInlineFormattingElements();
23970
- if (removedEmptyTags && rangeParams !== null && rangeParams !== undefined) {
24341
+ if (!insertedTypingStylePlaceholder) _this2.cleanupEmptyInlineFormattingElements();
24342
+ if (rangeParams !== null && rangeParams !== undefined) {
23971
24343
  _this2._setRangeParams(rangeParams);
23972
- _this2.applyCurrentEditableDomToComponent(rangeParams);
24344
+ _this2.applyCurrentEditableDomToComponent(rangeParams, {
24345
+ edit: {
24346
+ before: editableText(_this2.editableDiv),
24347
+ from: 0,
24348
+ to: 0,
24349
+ insert: ""
24350
+ },
24351
+ intent: "format",
24352
+ history: {
24353
+ id: "mri-".concat(++_this2.historySequence),
24354
+ direction: "forward"
24355
+ }
24356
+ });
23973
24357
  }
23974
24358
  _this2.setActiveButtonsIfChanged(_this2.getActiveButtonsFromSelection(rangeParams));
23975
24359
  return success;
@@ -24014,6 +24398,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
24014
24398
  _defineProperty(_this2, "insertRawText", function (new_text) {
24015
24399
  var selectInsertedText = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
24016
24400
  try {
24401
+ var beforeText = editableText(_this2.editableDiv);
24017
24402
  var rangeParams = _this2._getRangeParams();
24018
24403
  var node = _this2._findNodeWithIndex(rangeParams.endNodeIndex);
24019
24404
  var offset = rangeParams.endOffset;
@@ -24045,7 +24430,21 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
24045
24430
  // console.log(new_rangeParams)
24046
24431
 
24047
24432
  new_raw_text = removeEncodingIfPlainText(new_raw_text, _this2.props.mimeType, _this2.enableHtml());
24048
- _this2.applyChangesToComponent(new_raw_text, _this2.props.mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
24433
+ _this2.applyChangesToComponent(new_raw_text, _this2.props.mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab, {
24434
+ transaction: {
24435
+ edit: {
24436
+ before: beforeText,
24437
+ from: rangeParams.startGlobalOffset,
24438
+ to: rangeParams.endGlobalOffset,
24439
+ insert: new_text
24440
+ },
24441
+ intent: "input",
24442
+ history: {
24443
+ id: "mri-".concat(++_this2.historySequence),
24444
+ direction: "forward"
24445
+ }
24446
+ }
24447
+ });
24049
24448
  } catch (error) {
24050
24449
  console.error(error);
24051
24450
  }
@@ -24173,6 +24572,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
24173
24572
  });
24174
24573
  _defineProperty(_this2, "removeNewLine", function () {
24175
24574
  try {
24575
+ var beforeText = editableText(_this2.editableDiv);
24176
24576
  var rangeParams = _this2._getRangeParams();
24177
24577
  var node = _this2._findNodeWithIndex(rangeParams.endNodeIndex);
24178
24578
  var prevNode = _this2._findNodeWithIndex(rangeParams.endNodeIndex - 1);
@@ -24189,13 +24589,28 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
24189
24589
  new_rangeParams.srartGlobalOffset--;
24190
24590
  new_rangeParams.endGlobalOffset--;
24191
24591
  new_raw_text = removeEncodingIfPlainText(new_raw_text, _this2.props.mimeType, _this2.enableHtml());
24192
- _this2.applyChangesToComponent(new_raw_text, _this2.props.mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
24592
+ _this2.applyChangesToComponent(new_raw_text, _this2.props.mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab, {
24593
+ transaction: {
24594
+ edit: {
24595
+ before: beforeText,
24596
+ from: Math.max(0, rangeParams.endGlobalOffset - 1),
24597
+ to: rangeParams.endGlobalOffset,
24598
+ insert: ""
24599
+ },
24600
+ intent: "input",
24601
+ history: {
24602
+ id: "mri-".concat(++_this2.historySequence),
24603
+ direction: "forward"
24604
+ }
24605
+ }
24606
+ });
24193
24607
  } catch (error) {
24194
24608
  console.error(error);
24195
24609
  }
24196
24610
  });
24197
24611
  _defineProperty(_this2, "insertNewLine", function () {
24198
24612
  try {
24613
+ var beforeText = editableText(_this2.editableDiv);
24199
24614
  var rangeParams = _this2._getRangeParams();
24200
24615
  var node = _this2._findNodeWithIndex(rangeParams.endNodeIndex);
24201
24616
  var offset = rangeParams.endOffset;
@@ -24231,13 +24646,28 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
24231
24646
  // console.log("New range params after line insert")
24232
24647
  // console.log(new_rangeParams)
24233
24648
 
24234
- _this2.applyChangesToComponent(new_raw_text, _this2.props.mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
24649
+ _this2.applyChangesToComponent(new_raw_text, _this2.props.mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab, {
24650
+ transaction: {
24651
+ edit: {
24652
+ before: beforeText,
24653
+ from: rangeParams.startGlobalOffset,
24654
+ to: rangeParams.endGlobalOffset,
24655
+ insert: "\n"
24656
+ },
24657
+ intent: "input",
24658
+ history: {
24659
+ id: "mri-".concat(++_this2.historySequence),
24660
+ direction: "forward"
24661
+ }
24662
+ }
24663
+ });
24235
24664
  } catch (error) {
24236
24665
  console.error(error);
24237
24666
  }
24238
24667
  });
24239
24668
  _defineProperty(_this2, "insertAccentLetter", function (event, old_char, new_char) {
24240
24669
  try {
24670
+ var beforeText = editableText(_this2.editableDiv);
24241
24671
  var rangeParams = _this2._getRangeParams();
24242
24672
  var node = _this2._findNodeWithIndex(rangeParams.startNodeIndex);
24243
24673
  var offset = rangeParams.startOffset;
@@ -24261,7 +24691,21 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
24261
24691
  new_rangeParams = _objectSpread2({}, rangeParams);
24262
24692
  }
24263
24693
  new_raw_text = removeEncodingIfPlainText(new_raw_text, _this2.props.mimeType, _this2.enableHtml());
24264
- _this2.applyChangesToComponent(new_raw_text, _this2.props.mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab);
24694
+ _this2.applyChangesToComponent(new_raw_text, _this2.props.mimeType, new_rangeParams, _this2.props.useExpertMode, _this2.props.selectedTab, {
24695
+ transaction: {
24696
+ edit: {
24697
+ before: beforeText,
24698
+ from: old_char === null ? rangeParams.startGlobalOffset : Math.max(0, rangeParams.startGlobalOffset - 1),
24699
+ to: old_char === null ? rangeParams.startGlobalOffset : rangeParams.startGlobalOffset,
24700
+ insert: new_char
24701
+ },
24702
+ intent: "input",
24703
+ history: {
24704
+ id: "mri-".concat(++_this2.historySequence),
24705
+ direction: "forward"
24706
+ }
24707
+ }
24708
+ });
24265
24709
  } catch (error) {
24266
24710
  console.error(error);
24267
24711
  }
@@ -24369,10 +24813,66 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
24369
24813
  }
24370
24814
  });
24371
24815
  _defineProperty(_this2, "handleCompositionStart", function (event) {
24816
+ var _offsets$from, _offsets$to;
24817
+ var offsets = _this2.captureSelectionOffsets();
24818
+ _this2.compositionStart = {
24819
+ before: editableText(_this2.editableDiv),
24820
+ from: (_offsets$from = offsets === null || offsets === void 0 ? void 0 : offsets.from) !== null && _offsets$from !== void 0 ? _offsets$from : 0,
24821
+ to: (_offsets$to = offsets === null || offsets === void 0 ? void 0 : offsets.to) !== null && _offsets$to !== void 0 ? _offsets$to : 0
24822
+ };
24372
24823
  _this2.isComposing = true;
24373
24824
  });
24374
24825
  _defineProperty(_this2, "handleCompositionEnd", function (event) {
24375
24826
  _this2.isComposing = false;
24827
+ _this2.compositionStart = null;
24828
+ });
24829
+ _defineProperty(_this2, "captureSelectionOffsets", function () {
24830
+ try {
24831
+ var selection = window.getSelection();
24832
+ if (!selection || selection.rangeCount === 0) return null;
24833
+ var range = selection.getRangeAt(0);
24834
+ var before = editableText(_this2.editableDiv);
24835
+ var endpoint = function endpoint(container, offset) {
24836
+ var probe = document.createRange();
24837
+ probe.selectNodeContents(_this2.editableDiv);
24838
+ probe.setEnd(container, offset);
24839
+ var wrapper = document.createElement("span");
24840
+ wrapper.appendChild(probe.cloneContents());
24841
+ return editableText(wrapper).length;
24842
+ };
24843
+ var from = endpoint(range.startContainer, range.startOffset);
24844
+ var to = endpoint(range.endContainer, range.endOffset);
24845
+ return {
24846
+ before: before,
24847
+ from: Math.min(from, to),
24848
+ to: Math.max(from, to)
24849
+ };
24850
+ } catch (_error) {
24851
+ return null;
24852
+ }
24853
+ });
24854
+ /** Capture an input intent before the browser mutates the contenteditable DOM. */
24855
+ _defineProperty(_this2, "handleBeforeInput", function (event) {
24856
+ try {
24857
+ var captured = transactionFromBeforeInput(_this2.editableDiv, event, _this2.compositionStart ? {
24858
+ before: _this2.compositionStart.before,
24859
+ from: _this2.compositionStart.from,
24860
+ to: _this2.compositionStart.to
24861
+ } : null);
24862
+ var id = "mri-".concat(++_this2.historySequence);
24863
+ _this2.pendingTransaction = {
24864
+ edit: captured.edit || undefined,
24865
+ intent: captured.intent,
24866
+ history: {
24867
+ id: id,
24868
+ direction: "forward"
24869
+ }
24870
+ };
24871
+ } catch (_error) {
24872
+ _this2.pendingTransaction = {
24873
+ intent: "programmatic"
24874
+ };
24875
+ }
24376
24876
  });
24377
24877
  // Comprehensive LaTeX pattern detection and auto-wrapping in math tags
24378
24878
  // Comprehensive LaTeX pattern detection for paste auto-wrapping
@@ -24518,6 +25018,9 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
24518
25018
  _this2.initialHistoryState = null;
24519
25019
  _this2.undoHistory = [];
24520
25020
  _this2.redoHistory = [];
25021
+ _this2.historySequence = 0;
25022
+ _this2.pendingTransaction = null;
25023
+ _this2.compositionStart = null;
24521
25024
  _this2.accent = "";
24522
25025
 
24523
25026
  // keeps track of whether user is composing in an IME - see https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
@@ -24954,7 +25457,19 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
24954
25457
  var rangeParams = this._getRangeParams();
24955
25458
  if (rangeParams) {
24956
25459
  this.setOldRangeParams(rangeParams);
24957
- this.applyCurrentEditableDomToComponent(rangeParams);
25460
+ this.applyCurrentEditableDomToComponent(rangeParams, {
25461
+ edit: {
25462
+ before: editableText(this.editableDiv),
25463
+ from: 0,
25464
+ to: 0,
25465
+ insert: ""
25466
+ },
25467
+ intent: "format",
25468
+ history: {
25469
+ id: "mri-".concat(++this.historySequence),
25470
+ direction: "forward"
25471
+ }
25472
+ });
24958
25473
  }
24959
25474
  debugMathRichInput("moveTrailingWhitespaceOutsideInlineStyle:after", {
24960
25475
  style: style,
@@ -24970,6 +25485,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
24970
25485
  key: "applyCurrentEditableDomToComponent",
24971
25486
  value: function applyCurrentEditableDomToComponent() {
24972
25487
  var rangeParams = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
25488
+ var transaction = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
24973
25489
  if (!this.editableDiv) return;
24974
25490
  if (rangeParams === null || rangeParams === undefined) {
24975
25491
  rangeParams = this._getRangeParams();
@@ -24984,7 +25500,8 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
24984
25500
  rawText = removeEncodingIfPlainText(rawText, mimeType, this.enableHtml());
24985
25501
  rawText = this.stripEmptyInlineFormattingTags(rawText);
24986
25502
  this.applyChangesToComponent(rawText, mimeType, rangeParams, this.props.useExpertMode, this.props.selectedTab, {
24987
- skipControlledRender: true
25503
+ skipControlledRender: true,
25504
+ transaction: transaction
24988
25505
  });
24989
25506
  }
24990
25507
  }, {
@@ -25035,6 +25552,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
25035
25552
  });
25036
25553
  this.editableDiv.addEventListener("keydown", this.handleKeyDown);
25037
25554
  this.editableDiv.addEventListener("keyup", this.handleKeyUp);
25555
+ this.editableDiv.addEventListener("beforeinput", this.handleBeforeInput);
25038
25556
  this.editableDiv.addEventListener("paste", this.handlePaste);
25039
25557
  this.editableDiv.addEventListener("copy", this.handleCopy);
25040
25558
  if (this.props.autofocus === true) this.editableDiv.focus();
@@ -25048,6 +25566,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
25048
25566
  try {
25049
25567
  this.editableDiv.removeEventListener("keydown", this.handleKeyDown);
25050
25568
  this.editableDiv.removeEventListener("keyup", this.handleKeyUp);
25569
+ this.editableDiv.removeEventListener("beforeinput", this.handleBeforeInput);
25051
25570
  this.editableDiv.removeEventListener("paste", this.handlePaste);
25052
25571
  this.editableDiv.removeEventListener("copy", this.handleCopy);
25053
25572
  } catch (error) {
@@ -25227,6 +25746,7 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
25227
25746
  try {
25228
25747
  if (rangeParams === null || rangeParams === undefined) rangeParams = this._getRangeParams();
25229
25748
  if (rangeParams.startOffset !== 0) console.warn("Unexpected startOffset " + rangeParams.startOffset + " in insertAfterSmallSpace");
25749
+ var beforeText = editableText(this.editableDiv);
25230
25750
  var node = this._findNodeWithIndex(rangeParams.startNodeIndex);
25231
25751
  if (node === null || node === undefined || node.nodeValue === null) {
25232
25752
  console.warn("Could not find small-space text node");
@@ -25251,7 +25771,20 @@ var MathRichInput = /*#__PURE__*/function (_React$Component) {
25251
25771
  var new_raw_text = elementToMarkedRawText(this.editableDiv, null, 0, this.enableHtml());
25252
25772
  new_raw_text = removeEncodingIfPlainText(new_raw_text, this.props.mimeType, this.enableHtml());
25253
25773
  this.applyChangesToComponent(new_raw_text, this.props.mimeType, new_rangeParams, this.props.useExpertMode, this.props.selectedTab, {
25254
- skipControlledRender: true
25774
+ skipControlledRender: true,
25775
+ transaction: {
25776
+ edit: {
25777
+ before: beforeText,
25778
+ from: rangeParams.startGlobalOffset,
25779
+ to: rangeParams.startGlobalOffset,
25780
+ insert: new_char
25781
+ },
25782
+ intent: "input",
25783
+ history: {
25784
+ id: "mri-".concat(++this.historySequence),
25785
+ direction: "forward"
25786
+ }
25787
+ }
25255
25788
  });
25256
25789
  } catch (error) {
25257
25790
  console.error(error);