@drghaliasri/butex 5.5.0 → 5.5.1

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/react.d.mts CHANGED
@@ -1071,6 +1071,7 @@ type EditorRuntimeApi = {
1071
1071
  getSession: () => EditorSession;
1072
1072
  setSession: (next: EditorSession) => void;
1073
1073
  setUiLocale: (locale: ButexUiLocale) => void;
1074
+ focusInput: () => void;
1074
1075
  performUndo: () => void;
1075
1076
  performRedo: () => void;
1076
1077
  performCopy: () => Promise<void>;
package/dist/react.d.ts CHANGED
@@ -1071,6 +1071,7 @@ type EditorRuntimeApi = {
1071
1071
  getSession: () => EditorSession;
1072
1072
  setSession: (next: EditorSession) => void;
1073
1073
  setUiLocale: (locale: ButexUiLocale) => void;
1074
+ focusInput: () => void;
1074
1075
  performUndo: () => void;
1075
1076
  performRedo: () => void;
1076
1077
  performCopy: () => Promise<void>;
package/dist/react.js CHANGED
@@ -4940,7 +4940,8 @@ ${BUTEX_FONT_FACE_CSS}
4940
4940
  transition: box-shadow 0.15s ease, border-color 0.15s ease;
4941
4941
  }
4942
4942
 
4943
- .surface:focus {
4943
+ .surface:focus,
4944
+ .surface.surface--typing-focus {
4944
4945
  border-color: var(--butex-focus-border, rgba(13, 148, 136, 0.45));
4945
4946
  box-shadow: 0 0 0 3px var(--butex-focus-shadow, rgba(13, 148, 136, 0.12));
4946
4947
  }
@@ -5142,7 +5143,7 @@ function injectBuTeXEditorStyles(doc) {
5142
5143
 
5143
5144
  // src/editor/runtime.ts
5144
5145
  function createEditorRuntime(options) {
5145
- const { surfaceEl } = options;
5146
+ const { surfaceEl, inputEl } = options;
5146
5147
  const buttonElements = options.buttonElements ?? {};
5147
5148
  const outsidePointerIgnoreSelectors = options.outsidePointerIgnoreSelectors ?? [];
5148
5149
  let session = options.initialSession ?? createStarterSession();
@@ -5156,6 +5157,23 @@ function createEditorRuntime(options) {
5156
5157
  let dragSelecting = false;
5157
5158
  let dragChainId = null;
5158
5159
  let dragChanged = false;
5160
+ let composingInput = false;
5161
+ let pendingCompositionText = null;
5162
+ function resetInputElement() {
5163
+ if (!inputEl) {
5164
+ return;
5165
+ }
5166
+ inputEl.value = "";
5167
+ }
5168
+ function focusInput() {
5169
+ if (!inputEl) {
5170
+ surfaceEl.focus();
5171
+ return;
5172
+ }
5173
+ inputEl.focus({ preventScroll: true });
5174
+ const end = inputEl.value.length;
5175
+ inputEl.setSelectionRange(end, end);
5176
+ }
5159
5177
  function notifySessionChange() {
5160
5178
  options.onSessionChange?.(session);
5161
5179
  }
@@ -5420,7 +5438,7 @@ function createEditorRuntime(options) {
5420
5438
  event.preventDefault();
5421
5439
  event.stopPropagation();
5422
5440
  startDragSelection(chainId, index);
5423
- surfaceEl.focus();
5441
+ focusInput();
5424
5442
  });
5425
5443
  slot.addEventListener("click", (event) => {
5426
5444
  if (dragChanged) {
@@ -5430,7 +5448,7 @@ function createEditorRuntime(options) {
5430
5448
  return;
5431
5449
  }
5432
5450
  applyTransient((prev) => setCaret(prev, chainId, index));
5433
- surfaceEl.focus();
5451
+ focusInput();
5434
5452
  });
5435
5453
  if (session.caret.chainId === chainId && session.caret.index === index) {
5436
5454
  const caret = document.createElement("span");
@@ -5462,7 +5480,7 @@ function createEditorRuntime(options) {
5462
5480
  event.preventDefault();
5463
5481
  event.stopPropagation();
5464
5482
  startDragSelection(chainId, indexInChain);
5465
- surfaceEl.focus();
5483
+ focusInput();
5466
5484
  });
5467
5485
  nodeEl.addEventListener("click", (event) => {
5468
5486
  if (dragChanged) {
@@ -5473,7 +5491,7 @@ function createEditorRuntime(options) {
5473
5491
  }
5474
5492
  event.stopPropagation();
5475
5493
  applyTransient((prev) => selectNode(prev, node.id));
5476
- surfaceEl.focus();
5494
+ focusInput();
5477
5495
  });
5478
5496
  const body = document.createElement("span");
5479
5497
  body.className = "node-body";
@@ -5508,7 +5526,7 @@ function createEditorRuntime(options) {
5508
5526
  const activeTree = session[activeTreeKey(session.activeSide)];
5509
5527
  surfaceEl.appendChild(buildChain(activeTree));
5510
5528
  if (initialKeyboardFocusPending) {
5511
- requestAnimationFrame(() => surfaceEl.focus());
5529
+ requestAnimationFrame(focusInput);
5512
5530
  initialKeyboardFocusPending = false;
5513
5531
  }
5514
5532
  notifySessionChange();
@@ -5546,7 +5564,7 @@ function createEditorRuntime(options) {
5546
5564
  }
5547
5565
  session = restored;
5548
5566
  render();
5549
- surfaceEl.focus();
5567
+ focusInput();
5550
5568
  }
5551
5569
  function performRedo() {
5552
5570
  const restored = restoreRedo(undoRedo, session);
@@ -5555,9 +5573,12 @@ function createEditorRuntime(options) {
5555
5573
  }
5556
5574
  session = restored;
5557
5575
  render();
5558
- surfaceEl.focus();
5576
+ focusInput();
5559
5577
  }
5560
5578
  function onKeyDown(event) {
5579
+ if (event.isComposing || event.key === "Process" || event.keyCode === 229) {
5580
+ return;
5581
+ }
5561
5582
  const shortcutMod = event.ctrlKey || event.metaKey;
5562
5583
  const keyLower = typeof event.key === "string" ? event.key.toLowerCase() : "";
5563
5584
  if (shortcutMod && !event.altKey && keyLower === "z") {
@@ -5656,6 +5677,70 @@ function createEditorRuntime(options) {
5656
5677
  applyStructural((prev) => insertChar(prev, char));
5657
5678
  }
5658
5679
  }
5680
+ function onBeforeInput(event) {
5681
+ if (composingInput || event.isComposing) {
5682
+ return;
5683
+ }
5684
+ if (event.inputType === "deleteContentBackward") {
5685
+ event.preventDefault();
5686
+ applyStructural((prev) => deleteBackward(prev));
5687
+ resetInputElement();
5688
+ return;
5689
+ }
5690
+ if (event.inputType === "deleteContentForward") {
5691
+ event.preventDefault();
5692
+ applyStructural((prev) => deleteForward(prev));
5693
+ resetInputElement();
5694
+ }
5695
+ }
5696
+ function onInput(event) {
5697
+ if (!inputEl || composingInput) {
5698
+ return;
5699
+ }
5700
+ const inputEvent = event;
5701
+ const text = inputEvent.data ?? inputEl.value;
5702
+ resetInputElement();
5703
+ if (pendingCompositionText !== null && (inputEvent.inputType === "insertFromComposition" || text === pendingCompositionText)) {
5704
+ pendingCompositionText = null;
5705
+ return;
5706
+ }
5707
+ pendingCompositionText = null;
5708
+ if (inputEvent.inputType === "deleteContentBackward") {
5709
+ applyStructural((prev) => deleteBackward(prev));
5710
+ return;
5711
+ }
5712
+ if (inputEvent.inputType === "deleteContentForward") {
5713
+ applyStructural((prev) => deleteForward(prev));
5714
+ return;
5715
+ }
5716
+ if (text) {
5717
+ applyStructural((prev) => pasteText(prev, text));
5718
+ }
5719
+ }
5720
+ function onCompositionStart() {
5721
+ composingInput = true;
5722
+ }
5723
+ function onCompositionEnd(event) {
5724
+ if (!inputEl) {
5725
+ return;
5726
+ }
5727
+ composingInput = false;
5728
+ const text = event.data || inputEl.value;
5729
+ resetInputElement();
5730
+ if (text) {
5731
+ applyStructural((prev) => pasteText(prev, text));
5732
+ }
5733
+ pendingCompositionText = text || null;
5734
+ window.setTimeout(() => {
5735
+ pendingCompositionText = null;
5736
+ }, 0);
5737
+ }
5738
+ function onInputFocus() {
5739
+ surfaceEl.classList.add("surface--typing-focus");
5740
+ }
5741
+ function onInputBlur() {
5742
+ surfaceEl.classList.remove("surface--typing-focus");
5743
+ }
5659
5744
  function isShortcutOnlyEvent(event) {
5660
5745
  if (!(event.ctrlKey || event.metaKey) || event.altKey) {
5661
5746
  return false;
@@ -5705,7 +5790,7 @@ function createEditorRuntime(options) {
5705
5790
  }
5706
5791
  event.preventDefault();
5707
5792
  startDragSelection(resolved.chainId, resolved.slotIndex);
5708
- surfaceEl.focus();
5793
+ focusInput();
5709
5794
  }
5710
5795
  function onSurfaceClick(event) {
5711
5796
  if (dragChanged) {
@@ -5722,7 +5807,7 @@ function createEditorRuntime(options) {
5722
5807
  } else {
5723
5808
  clearSelectionAndNodeHighlights();
5724
5809
  }
5725
- surfaceEl.focus();
5810
+ focusInput();
5726
5811
  }
5727
5812
  function onDocumentPointerDown(event) {
5728
5813
  const target = event.target;
@@ -5738,6 +5823,13 @@ function createEditorRuntime(options) {
5738
5823
  clearSelectionAndNodeHighlights();
5739
5824
  }
5740
5825
  surfaceEl.addEventListener("keydown", onKeyDown);
5826
+ inputEl?.addEventListener("keydown", onKeyDown);
5827
+ inputEl?.addEventListener("beforeinput", onBeforeInput);
5828
+ inputEl?.addEventListener("input", onInput);
5829
+ inputEl?.addEventListener("compositionstart", onCompositionStart);
5830
+ inputEl?.addEventListener("compositionend", onCompositionEnd);
5831
+ inputEl?.addEventListener("focus", onInputFocus);
5832
+ inputEl?.addEventListener("blur", onInputBlur);
5741
5833
  document.addEventListener("keydown", onDocumentKeyDown);
5742
5834
  document.addEventListener("mouseup", endDragSelection);
5743
5835
  document.addEventListener("mouseleave", endDragSelection);
@@ -5749,6 +5841,13 @@ function createEditorRuntime(options) {
5749
5841
  render,
5750
5842
  destroy: () => {
5751
5843
  surfaceEl.removeEventListener("keydown", onKeyDown);
5844
+ inputEl?.removeEventListener("keydown", onKeyDown);
5845
+ inputEl?.removeEventListener("beforeinput", onBeforeInput);
5846
+ inputEl?.removeEventListener("input", onInput);
5847
+ inputEl?.removeEventListener("compositionstart", onCompositionStart);
5848
+ inputEl?.removeEventListener("compositionend", onCompositionEnd);
5849
+ inputEl?.removeEventListener("focus", onInputFocus);
5850
+ inputEl?.removeEventListener("blur", onInputBlur);
5752
5851
  document.removeEventListener("keydown", onDocumentKeyDown);
5753
5852
  document.removeEventListener("mouseup", endDragSelection);
5754
5853
  document.removeEventListener("mouseleave", endDragSelection);
@@ -5769,6 +5868,7 @@ function createEditorRuntime(options) {
5769
5868
  uiLocale = locale;
5770
5869
  render();
5771
5870
  },
5871
+ focusInput,
5772
5872
  performUndo,
5773
5873
  performRedo,
5774
5874
  performCopy,
@@ -5776,27 +5876,27 @@ function createEditorRuntime(options) {
5776
5876
  performPaste,
5777
5877
  toggleSide: () => {
5778
5878
  applyTransient((prev) => switchSide(prev));
5779
- surfaceEl.focus();
5879
+ focusInput();
5780
5880
  },
5781
5881
  toggleSplitLeafTyping: () => {
5782
5882
  applyStructural((prev) => setSplitLeafTyping(prev, !prev.splitLeafTyping));
5783
- surfaceEl.focus();
5883
+ focusInput();
5784
5884
  },
5785
5885
  toggleArabicReverseNumberTyping: () => {
5786
5886
  applyStructural((prev) => setArabicReverseNumberTyping(prev, !prev.arabicReverseNumberTyping));
5787
- surfaceEl.focus();
5887
+ focusInput();
5788
5888
  },
5789
5889
  toggleTakweenCharacterFont: () => {
5790
5890
  applyTransient((prev) => toggleTakweenCharacterFont(prev));
5791
- surfaceEl.focus();
5891
+ focusInput();
5792
5892
  },
5793
5893
  setCurrentCharacterFont: (fontId) => {
5794
5894
  applyTransient((prev) => setCurrentCharacterFont(prev, fontId));
5795
- surfaceEl.focus();
5895
+ focusInput();
5796
5896
  },
5797
5897
  setCurrentDigitForm: (digitForm) => {
5798
5898
  applyStructural((prev) => setCurrentDigitForm(prev, digitForm));
5799
- surfaceEl.focus();
5899
+ focusInput();
5800
5900
  },
5801
5901
  insertDelimiterByKind: (kind) => {
5802
5902
  if (kind === "paren") {
@@ -5806,79 +5906,79 @@ function createEditorRuntime(options) {
5806
5906
  } else {
5807
5907
  applyStructural((prev) => insertDelimiterPair(prev, "\\left\\{", "\\right\\}"));
5808
5908
  }
5809
- surfaceEl.focus();
5909
+ focusInput();
5810
5910
  },
5811
5911
  insertFraction: () => {
5812
5912
  applyStructural((prev) => insertFraction(prev));
5813
- surfaceEl.focus();
5913
+ focusInput();
5814
5914
  },
5815
5915
  insertFirstDerivative: () => {
5816
5916
  applyStructural((prev) => insertFirstDerivative(prev));
5817
- surfaceEl.focus();
5917
+ focusInput();
5818
5918
  },
5819
5919
  insertSecondDerivative: () => {
5820
5920
  applyStructural((prev) => insertSecondDerivative(prev));
5821
- surfaceEl.focus();
5921
+ focusInput();
5822
5922
  },
5823
5923
  insertMatrixEnv: (style, rows, columns) => {
5824
5924
  applyStructural((prev) => insertMatrixEnv(prev, style, rows, columns));
5825
- surfaceEl.focus();
5925
+ focusInput();
5826
5926
  },
5827
5927
  insertArrayEnv: (rows, columns) => {
5828
5928
  applyStructural((prev) => insertArrayEnv(prev, rows, columns));
5829
- surfaceEl.focus();
5929
+ focusInput();
5830
5930
  },
5831
5931
  insertAlignedEnv: (rows, columns) => {
5832
5932
  applyStructural((prev) => insertAlignedEnv(prev, rows, columns));
5833
- surfaceEl.focus();
5933
+ focusInput();
5834
5934
  },
5835
5935
  insertSqrt: () => {
5836
5936
  applyStructural((prev) => insertSqrt(prev));
5837
- surfaceEl.focus();
5937
+ focusInput();
5838
5938
  },
5839
5939
  insertOverset: () => {
5840
5940
  applyStructural((prev) => insertOverset(prev));
5841
- surfaceEl.focus();
5941
+ focusInput();
5842
5942
  },
5843
5943
  insertUnderset: () => {
5844
5944
  applyStructural((prev) => insertUnderset(prev));
5845
- surfaceEl.focus();
5945
+ focusInput();
5846
5946
  },
5847
5947
  insertLimitsSeriesTemplate: (commandId) => {
5848
5948
  applyStructural((prev) => insertLimitsSeriesTemplate(prev, commandId));
5849
- surfaceEl.focus();
5949
+ focusInput();
5850
5950
  },
5851
5951
  insertAccentPair: () => {
5852
5952
  applyStructural((prev) => insertAccentPair(prev));
5853
- surfaceEl.focus();
5953
+ focusInput();
5854
5954
  },
5855
5955
  insertAccent: (accentId) => {
5856
5956
  applyStructural((prev) => insertAccent(prev, accentId));
5857
- surfaceEl.focus();
5957
+ focusInput();
5858
5958
  },
5859
5959
  insertAtomicCommand: (commandId) => {
5860
5960
  applyStructural((prev) => insertAtomicCommand(prev, commandId));
5861
- surfaceEl.focus();
5961
+ focusInput();
5862
5962
  },
5863
5963
  insertAtomicOperatorCommand: (commandId) => {
5864
5964
  applyStructural((prev) => insertAtomicOperatorCommand(prev, commandId));
5865
- surfaceEl.focus();
5965
+ focusInput();
5866
5966
  },
5867
5967
  addSup: () => {
5868
5968
  applyStructural((prev) => addSup(prev));
5869
- surfaceEl.focus();
5969
+ focusInput();
5870
5970
  },
5871
5971
  addSub: () => {
5872
5972
  applyStructural((prev) => addSub(prev));
5873
- surfaceEl.focus();
5973
+ focusInput();
5874
5974
  },
5875
5975
  removeSup: () => {
5876
5976
  applyStructural((prev) => removeSup(prev));
5877
- surfaceEl.focus();
5977
+ focusInput();
5878
5978
  },
5879
5979
  removeSub: () => {
5880
5980
  applyStructural((prev) => removeSub(prev));
5881
- surfaceEl.focus();
5981
+ focusInput();
5882
5982
  },
5883
5983
  setMatrixEnvStyle: (style) => {
5884
5984
  applyStructural((prev) => setMatrixEnvStyle(prev, style));
@@ -5900,7 +6000,7 @@ function createEditorRuntime(options) {
5900
6000
  },
5901
6001
  deleteStructure: () => {
5902
6002
  applyStructural((prev) => deleteStructure(prev));
5903
- surfaceEl.focus();
6003
+ focusInput();
5904
6004
  }
5905
6005
  };
5906
6006
  render();
@@ -6367,6 +6467,22 @@ var WIDGET_CHROME_CSS = `
6367
6467
  padding: 10px 12px;
6368
6468
  }
6369
6469
 
6470
+ .butex-widget .butex-editor-input-bridge {
6471
+ border: 0;
6472
+ font-size: 16px;
6473
+ height: 1px;
6474
+ margin: 0;
6475
+ max-height: 1px;
6476
+ min-height: 1px;
6477
+ opacity: 0;
6478
+ overflow: hidden;
6479
+ padding: 0;
6480
+ pointer-events: none;
6481
+ position: absolute;
6482
+ resize: none;
6483
+ width: 1px;
6484
+ }
6485
+
6370
6486
  .butex-widget .toolbar {
6371
6487
  display: flex;
6372
6488
  flex-wrap: wrap;
@@ -7373,6 +7489,7 @@ var ButexEditor = (0, import_react.forwardRef)(
7373
7489
  const messages = equationEditorMessages(uiLocale);
7374
7490
  const wrapperRef = (0, import_react.useRef)(null);
7375
7491
  const surfaceRef = (0, import_react.useRef)(null);
7492
+ const inputRef = (0, import_react.useRef)(null);
7376
7493
  const mathOutputRef = (0, import_react.useRef)(null);
7377
7494
  const renderErrorRef = (0, import_react.useRef)(null);
7378
7495
  const latexLinesRef = (0, import_react.useRef)(null);
@@ -7484,6 +7601,7 @@ ${arabic || currentMessages.empty}`;
7484
7601
  }
7485
7602
  const runtime = createEditorRuntime({
7486
7603
  surfaceEl,
7604
+ inputEl: inputRef.current,
7487
7605
  initialSession,
7488
7606
  defaultSide,
7489
7607
  uiLocale,
@@ -7525,7 +7643,7 @@ ${arabic || currentMessages.empty}`;
7525
7643
  } else {
7526
7644
  runtime.render();
7527
7645
  }
7528
- surfaceEl.focus();
7646
+ runtime.focusInput();
7529
7647
  return () => {
7530
7648
  runtime.destroy();
7531
7649
  runtimeRef.current = null;
@@ -7539,7 +7657,7 @@ ${arabic || currentMessages.empty}`;
7539
7657
  }
7540
7658
  }, [uiLocale]);
7541
7659
  function focusSurface() {
7542
- surfaceRef.current?.focus();
7660
+ runtimeRef.current?.focusInput();
7543
7661
  }
7544
7662
  function insertSelectedEnvironment(rows, columns) {
7545
7663
  if (envPaletteMode === "array") {
@@ -8617,6 +8735,20 @@ ${arabic || currentMessages.empty}`;
8617
8735
  "aria-label": messages.equationEditor
8618
8736
  }
8619
8737
  ),
8738
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
8739
+ "textarea",
8740
+ {
8741
+ ref: inputRef,
8742
+ className: "butex-editor-input-bridge",
8743
+ "aria-label": messages.equationEditor,
8744
+ autoCapitalize: "none",
8745
+ autoComplete: "off",
8746
+ autoCorrect: "off",
8747
+ inputMode: "text",
8748
+ spellCheck: false,
8749
+ tabIndex: -1
8750
+ }
8751
+ ),
8620
8752
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: renderErrorRef, className: "error", hidden: true })
8621
8753
  ] }),
8622
8754
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("section", { className: "panel panel-preview", "aria-label": messages.renderPreview, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: mathOutputRef, className: "preview-box" }) }),