@drghaliasri/butex 5.6.0 → 5.6.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.
@@ -10380,7 +10380,7 @@ function focusArticleMetaPanel(panel) {
10380
10380
  }
10381
10381
 
10382
10382
  // src/react-document2/ButexDocumentEditor2.tsx
10383
- import { useCallback as useCallback2, useEffect as useEffect9, useMemo as useMemo2, useRef as useRef8, useState as useState12 } from "react";
10383
+ import { forwardRef as forwardRef2, useCallback as useCallback2, useEffect as useEffect9, useImperativeHandle as useImperativeHandle2, useMemo as useMemo2, useRef as useRef8, useState as useState12 } from "react";
10384
10384
 
10385
10385
  // src/debugJson.ts
10386
10386
  function lineColumnForPosition(text, position) {
@@ -17600,951 +17600,977 @@ function resolveInitialDocument2(initialDocument, uiLocale = "ar", documentMeta)
17600
17600
  };
17601
17601
  }
17602
17602
  }
17603
- function ButexDocumentEditor2({
17604
- initialDocument,
17605
- documentMeta,
17606
- className,
17607
- debug = false,
17608
- documentDirection = "rtl",
17609
- equationSide = "arabic",
17610
- editableEquations = true,
17611
- previewOnly = false,
17612
- uiLocale = "ar",
17613
- mathOutput = "svg",
17614
- digitForm: digitFormProp,
17615
- onDigitFormChange,
17616
- resolveImageUrl,
17617
- onDocumentChange,
17618
- onDocumentJsonChange,
17619
- onLatexChange
17620
- }) {
17621
- const messages = document2Messages(uiLocale);
17622
- const initialState = useMemo2(
17623
- () => resolveInitialDocument2(initialDocument, uiLocale, documentMeta),
17624
- [initialDocument, documentMeta, uiLocale]
17625
- );
17626
- const [documentNode, setDocumentNode] = useState12(initialState.document);
17627
- const [error, setError] = useState12(initialState.error);
17628
- const [editorOpen, setEditorOpen] = useState12(true);
17629
- const [previewOpen, setPreviewOpen] = useState12(true);
17630
- const [selectedMath, setSelectedMath] = useState12(null);
17631
- const [citePicker, setCitePicker] = useState12(null);
17632
- const [referencesOpen, setReferencesOpen] = useState12(false);
17633
- const [labelsOpen, setLabelsOpen] = useState12(false);
17634
- const [refPicker, setRefPicker] = useState12(null);
17635
- const [digitFormState, setDigitFormState] = useState12(null);
17636
- const [debugImportOpen, setDebugImportOpen] = useState12(false);
17637
- const [debugImportText, setDebugImportText] = useState12("");
17638
- const [debugImportError, setDebugImportError] = useState12("");
17639
- const [editorFocus, setEditorFocus] = useState12(createEmptyDocument2EditorFocus());
17640
- const [collapsedBlockIds, setCollapsedBlockIds] = useState12(() => /* @__PURE__ */ new Set());
17641
- const [blockSelectionState, setBlockSelectionState] = useState12(emptyBlockSelection);
17642
- const [historyTick, setHistoryTick] = useState12(0);
17643
- const digitForm = digitFormProp ?? digitFormState ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
17644
- function equationSessionWithDocumentDigits(session) {
17645
- return setCurrentDigitForm(session, digitForm);
17646
- }
17647
- const historyRef = useRef8(createDocument2History());
17648
- const documentRef = useRef8(documentNode);
17649
- const textSnapshotArmedRef = useRef8(false);
17650
- const textDebounceRef = useRef8(null);
17651
- const widgetRef = useRef8(null);
17652
- const articleMetaPanelRef = useRef8(null);
17653
- const pendingFocusRef = useRef8(null);
17654
- documentRef.current = documentNode;
17655
- const latex = document2Latex(documentNode, { digitForm });
17656
- const documentJson = useMemo2(() => toDocumentJson2(documentNode), [documentNode]);
17657
- const documentLabels = useMemo2(() => collectDocument2Labels(documentNode), [documentNode]);
17658
- const preview = useMemo2(
17659
- () => document2Preview(documentNode, mathOutput, equationSide, {
17660
- documentDirection,
17661
- digitForm,
17662
- uiLocale
17663
- }),
17664
- [documentNode, documentDirection, digitForm, equationSide, mathOutput, uiLocale]
17665
- );
17666
- const debugEnabled = useMemo2(() => {
17667
- if (debug) {
17668
- return true;
17669
- }
17670
- if (typeof window === "undefined") {
17671
- return false;
17672
- }
17673
- return new URLSearchParams(window.location.search).get("debug") === "1";
17674
- }, [debug]);
17675
- const canUndo = useMemo2(() => document2HistoryCanUndo(historyRef.current), [historyTick, documentNode]);
17676
- const canRedo = useMemo2(() => document2HistoryCanRedo(historyRef.current), [historyTick, documentNode]);
17677
- const blockSelection = normalizeBlockSelection(blockSelectionState.selection, documentNode.blocks.length);
17678
- const selectionCount = blockSelection ? blockSelection.to - blockSelection.from + 1 : 0;
17679
- const canMoveSelectionUp = Boolean(blockSelection && blockSelection.from > 0);
17680
- const canMoveSelectionDown = Boolean(blockSelection && blockSelection.to < documentNode.blocks.length - 1);
17681
- const formatTextToken = useMemo2(() => findFormatTextToken(documentNode, editorFocus), [documentNode, editorFocus]);
17682
- const canFormatText = formatTextToken !== null;
17683
- const activeTextStyles = formatTextToken?.style ?? {};
17684
- function clearBlockSelection() {
17685
- setBlockSelectionState(emptyBlockSelection());
17686
- }
17687
- function toggleSelectBlock(blockId, shiftKey) {
17688
- const index = documentRef.current.blocks.findIndex((block) => block.id === blockId);
17689
- if (index < 0) {
17690
- return;
17691
- }
17692
- const blockCount = documentRef.current.blocks.length;
17693
- setBlockSelectionState(
17694
- (current) => shiftKey ? extendBlockSelectionFromAnchor(current, index, blockCount) : toggleBlockInSelection(current, index, blockCount)
17603
+ var ButexDocumentEditor2 = forwardRef2(
17604
+ function ButexDocumentEditor22({
17605
+ initialDocument,
17606
+ documentMeta,
17607
+ className,
17608
+ debug = false,
17609
+ documentDirection = "rtl",
17610
+ equationSide = "arabic",
17611
+ editableEquations = true,
17612
+ previewOnly = false,
17613
+ uiLocale = "ar",
17614
+ mathOutput = "svg",
17615
+ digitForm: digitFormProp,
17616
+ onDigitFormChange,
17617
+ resolveImageUrl,
17618
+ onDocumentChange,
17619
+ onDocumentJsonChange,
17620
+ onLatexChange
17621
+ }, ref) {
17622
+ const messages = document2Messages(uiLocale);
17623
+ const initialState = useMemo2(
17624
+ () => resolveInitialDocument2(initialDocument, uiLocale, documentMeta),
17625
+ [initialDocument, documentMeta, uiLocale]
17695
17626
  );
17696
- }
17697
- function moveSelectedBlocks(direction) {
17698
- const selection = normalizeBlockSelection(blockSelectionState.selection, documentRef.current.blocks.length);
17699
- if (!selection) {
17700
- return;
17701
- }
17702
- const next = moveDocument2BlockRange(documentRef.current, selection.from, selection.to, direction);
17703
- if (next === documentRef.current) {
17704
- return;
17705
- }
17706
- applyDocument(next, "immediate");
17707
- const remapped = remapSelectionAfterRangeMove(selection, direction);
17708
- setBlockSelectionState({
17709
- selection: normalizeBlockSelection(remapped, next.blocks.length),
17710
- anchor: blockSelectionState.anchor === null ? null : blockSelectionState.anchor + direction
17711
- });
17712
- }
17713
- function deleteSelectedBlocks() {
17714
- const selection = normalizeBlockSelection(blockSelectionState.selection, documentRef.current.blocks.length);
17715
- if (!selection) {
17716
- return;
17717
- }
17718
- applyDocument(removeDocument2BlockRange(documentRef.current, selection.from, selection.to), "immediate");
17719
- clearBlockSelection();
17720
- }
17721
- useEffect9(() => {
17722
- injectBuTeXDocument2Styles();
17723
- }, []);
17724
- useEffect9(() => {
17725
- if (!editableEquations || previewOnly) {
17726
- setSelectedMath(null);
17727
- }
17728
- }, [editableEquations, previewOnly]);
17729
- useEffect9(() => {
17730
- const next = resolveInitialDocument2(initialDocument, uiLocale, documentMeta);
17731
- setDocumentNode(next.document);
17732
- setError(next.error);
17733
- setSelectedMath(null);
17734
- setCollapsedBlockIds(/* @__PURE__ */ new Set());
17735
- historyRef.current = createDocument2History();
17736
- setHistoryTick((tick) => tick + 1);
17737
- }, [initialDocument, documentMeta, uiLocale]);
17738
- useEffect9(() => {
17739
- onDocumentChange?.(documentNode);
17740
- }, [documentNode, onDocumentChange]);
17741
- useEffect9(() => {
17742
- onDocumentJsonChange?.(documentJson);
17743
- }, [documentJson, onDocumentJsonChange]);
17744
- useEffect9(() => {
17745
- onLatexChange?.(latex);
17746
- }, [latex, onLatexChange]);
17747
- useEffect9(() => {
17748
- const pending = pendingFocusRef.current;
17749
- const root = widgetRef.current;
17750
- if (!pending || !root) {
17751
- return;
17627
+ const [documentNode, setDocumentNode] = useState12(initialState.document);
17628
+ const [error, setError] = useState12(initialState.error);
17629
+ const [editorOpen, setEditorOpen] = useState12(true);
17630
+ const [previewOpen, setPreviewOpen] = useState12(true);
17631
+ const [selectedMath, setSelectedMath] = useState12(null);
17632
+ const [citePicker, setCitePicker] = useState12(null);
17633
+ const [referencesOpen, setReferencesOpen] = useState12(false);
17634
+ const [labelsOpen, setLabelsOpen] = useState12(false);
17635
+ const [refPicker, setRefPicker] = useState12(null);
17636
+ const [digitFormState, setDigitFormState] = useState12(null);
17637
+ const [debugImportOpen, setDebugImportOpen] = useState12(false);
17638
+ const [debugImportText, setDebugImportText] = useState12("");
17639
+ const [debugImportError, setDebugImportError] = useState12("");
17640
+ const [editorFocus, setEditorFocus] = useState12(createEmptyDocument2EditorFocus());
17641
+ const [collapsedBlockIds, setCollapsedBlockIds] = useState12(() => /* @__PURE__ */ new Set());
17642
+ const [blockSelectionState, setBlockSelectionState] = useState12(emptyBlockSelection);
17643
+ const [historyTick, setHistoryTick] = useState12(0);
17644
+ const digitForm = digitFormProp ?? digitFormState ?? (documentDirection === "rtl" ? "arabicIndic" : "western");
17645
+ function equationSessionWithDocumentDigits(session) {
17646
+ return setCurrentDigitForm(session, digitForm);
17647
+ }
17648
+ const historyRef = useRef8(createDocument2History());
17649
+ const documentRef = useRef8(documentNode);
17650
+ const editorFocusRef = useRef8(editorFocus);
17651
+ const textSnapshotArmedRef = useRef8(false);
17652
+ const textDebounceRef = useRef8(null);
17653
+ const widgetRef = useRef8(null);
17654
+ const articleMetaPanelRef = useRef8(null);
17655
+ const pendingFocusRef = useRef8(null);
17656
+ documentRef.current = documentNode;
17657
+ editorFocusRef.current = editorFocus;
17658
+ const latex = document2Latex(documentNode, { digitForm });
17659
+ const documentJson = useMemo2(() => toDocumentJson2(documentNode), [documentNode]);
17660
+ const documentLabels = useMemo2(() => collectDocument2Labels(documentNode), [documentNode]);
17661
+ const preview = useMemo2(
17662
+ () => document2Preview(documentNode, mathOutput, equationSide, {
17663
+ documentDirection,
17664
+ digitForm,
17665
+ uiLocale
17666
+ }),
17667
+ [documentNode, documentDirection, digitForm, equationSide, mathOutput, uiLocale]
17668
+ );
17669
+ const debugEnabled = useMemo2(() => {
17670
+ if (debug) {
17671
+ return true;
17672
+ }
17673
+ if (typeof window === "undefined") {
17674
+ return false;
17675
+ }
17676
+ return new URLSearchParams(window.location.search).get("debug") === "1";
17677
+ }, [debug]);
17678
+ const canUndo = useMemo2(() => document2HistoryCanUndo(historyRef.current), [historyTick, documentNode]);
17679
+ const canRedo = useMemo2(() => document2HistoryCanRedo(historyRef.current), [historyTick, documentNode]);
17680
+ const blockSelection = normalizeBlockSelection(blockSelectionState.selection, documentNode.blocks.length);
17681
+ const selectionCount = blockSelection ? blockSelection.to - blockSelection.from + 1 : 0;
17682
+ const canMoveSelectionUp = Boolean(blockSelection && blockSelection.from > 0);
17683
+ const canMoveSelectionDown = Boolean(blockSelection && blockSelection.to < documentNode.blocks.length - 1);
17684
+ const formatTextToken = useMemo2(() => findFormatTextToken(documentNode, editorFocus), [documentNode, editorFocus]);
17685
+ const canFormatText = formatTextToken !== null;
17686
+ const activeTextStyles = formatTextToken?.style ?? {};
17687
+ function clearBlockSelection() {
17688
+ setBlockSelectionState(emptyBlockSelection());
17689
+ }
17690
+ function toggleSelectBlock(blockId, shiftKey) {
17691
+ const index = documentRef.current.blocks.findIndex((block) => block.id === blockId);
17692
+ if (index < 0) {
17693
+ return;
17694
+ }
17695
+ const blockCount = documentRef.current.blocks.length;
17696
+ setBlockSelectionState(
17697
+ (current) => shiftKey ? extendBlockSelectionFromAnchor(current, index, blockCount) : toggleBlockInSelection(current, index, blockCount)
17698
+ );
17752
17699
  }
17753
- pendingFocusRef.current = null;
17754
- requestAnimationFrame(() => {
17755
- if (pending.kind === "math") {
17756
- const mathButton = Array.from(root.querySelectorAll("[data-math-token-id]")).find(
17757
- (button) => button.dataset.mathTokenId === pending.tokenId
17758
- );
17759
- mathButton?.focus();
17700
+ function moveSelectedBlocks(direction) {
17701
+ const selection = normalizeBlockSelection(blockSelectionState.selection, documentRef.current.blocks.length);
17702
+ if (!selection) {
17760
17703
  return;
17761
17704
  }
17762
- if (pending.kind === "cite") {
17763
- const citeButton = Array.from(root.querySelectorAll("[data-cite-token-id]")).find(
17764
- (button) => button.dataset.citeTokenId === pending.tokenId
17765
- );
17766
- citeButton?.focus();
17705
+ const next = moveDocument2BlockRange(documentRef.current, selection.from, selection.to, direction);
17706
+ if (next === documentRef.current) {
17767
17707
  return;
17768
17708
  }
17769
- if (pending.kind === "ref") {
17770
- const refButton = Array.from(root.querySelectorAll("[data-ref-token-id]")).find(
17771
- (button) => button.dataset.refTokenId === pending.tokenId
17772
- );
17773
- refButton?.focus();
17709
+ applyDocument(next, "immediate");
17710
+ const remapped = remapSelectionAfterRangeMove(selection, direction);
17711
+ setBlockSelectionState({
17712
+ selection: normalizeBlockSelection(remapped, next.blocks.length),
17713
+ anchor: blockSelectionState.anchor === null ? null : blockSelectionState.anchor + direction
17714
+ });
17715
+ }
17716
+ function deleteSelectedBlocks() {
17717
+ const selection = normalizeBlockSelection(blockSelectionState.selection, documentRef.current.blocks.length);
17718
+ if (!selection) {
17774
17719
  return;
17775
17720
  }
17776
- const textarea = Array.from(root.querySelectorAll("textarea[data-field-id][data-text-token-id]")).find(
17777
- (element) => element.dataset.fieldId === pending.fieldId && element.dataset.textTokenId === pending.textTokenId
17778
- );
17779
- if (!textarea) {
17721
+ applyDocument(removeDocument2BlockRange(documentRef.current, selection.from, selection.to), "immediate");
17722
+ clearBlockSelection();
17723
+ }
17724
+ useEffect9(() => {
17725
+ injectBuTeXDocument2Styles();
17726
+ }, []);
17727
+ useEffect9(() => {
17728
+ if (!editableEquations || previewOnly) {
17729
+ setSelectedMath(null);
17730
+ }
17731
+ }, [editableEquations, previewOnly]);
17732
+ useEffect9(() => {
17733
+ const next = resolveInitialDocument2(initialDocument, uiLocale, documentMeta);
17734
+ setDocumentNode(next.document);
17735
+ setError(next.error);
17736
+ setSelectedMath(null);
17737
+ setCollapsedBlockIds(/* @__PURE__ */ new Set());
17738
+ historyRef.current = createDocument2History();
17739
+ setHistoryTick((tick) => tick + 1);
17740
+ }, [initialDocument, documentMeta, uiLocale]);
17741
+ useEffect9(() => {
17742
+ onDocumentChange?.(documentNode);
17743
+ }, [documentNode, onDocumentChange]);
17744
+ useEffect9(() => {
17745
+ onDocumentJsonChange?.(documentJson);
17746
+ }, [documentJson, onDocumentJsonChange]);
17747
+ useEffect9(() => {
17748
+ onLatexChange?.(latex);
17749
+ }, [latex, onLatexChange]);
17750
+ useEffect9(() => {
17751
+ const pending = pendingFocusRef.current;
17752
+ const root = widgetRef.current;
17753
+ if (!pending || !root) {
17780
17754
  return;
17781
17755
  }
17782
- const safeOffset = Math.max(0, Math.min(pending.caretOffset, textarea.value.length));
17783
- textarea.focus();
17784
- textarea.setSelectionRange(safeOffset, safeOffset);
17785
- });
17786
- }, [documentNode]);
17787
- const bumpHistoryUi = useCallback2(() => {
17788
- setHistoryTick((tick) => tick + 1);
17789
- }, []);
17790
- const applyDocument = useCallback2(
17791
- (next, mode = "immediate") => {
17792
- if (mode === "immediate") {
17793
- pushDocument2Snapshot(historyRef.current, documentRef.current);
17794
- bumpHistoryUi();
17795
- } else if (mode === "text") {
17796
- if (!textSnapshotArmedRef.current) {
17756
+ pendingFocusRef.current = null;
17757
+ requestAnimationFrame(() => {
17758
+ if (pending.kind === "math") {
17759
+ const mathButton = Array.from(root.querySelectorAll("[data-math-token-id]")).find(
17760
+ (button) => button.dataset.mathTokenId === pending.tokenId
17761
+ );
17762
+ mathButton?.focus();
17763
+ return;
17764
+ }
17765
+ if (pending.kind === "cite") {
17766
+ const citeButton = Array.from(root.querySelectorAll("[data-cite-token-id]")).find(
17767
+ (button) => button.dataset.citeTokenId === pending.tokenId
17768
+ );
17769
+ citeButton?.focus();
17770
+ return;
17771
+ }
17772
+ if (pending.kind === "ref") {
17773
+ const refButton = Array.from(root.querySelectorAll("[data-ref-token-id]")).find(
17774
+ (button) => button.dataset.refTokenId === pending.tokenId
17775
+ );
17776
+ refButton?.focus();
17777
+ return;
17778
+ }
17779
+ const textarea = Array.from(root.querySelectorAll("textarea[data-field-id][data-text-token-id]")).find(
17780
+ (element) => element.dataset.fieldId === pending.fieldId && element.dataset.textTokenId === pending.textTokenId
17781
+ );
17782
+ if (!textarea) {
17783
+ return;
17784
+ }
17785
+ const safeOffset = Math.max(0, Math.min(pending.caretOffset, textarea.value.length));
17786
+ textarea.focus();
17787
+ textarea.setSelectionRange(safeOffset, safeOffset);
17788
+ });
17789
+ }, [documentNode]);
17790
+ const bumpHistoryUi = useCallback2(() => {
17791
+ setHistoryTick((tick) => tick + 1);
17792
+ }, []);
17793
+ const applyDocument = useCallback2(
17794
+ (next, mode = "immediate") => {
17795
+ if (mode === "immediate") {
17797
17796
  pushDocument2Snapshot(historyRef.current, documentRef.current);
17798
- textSnapshotArmedRef.current = true;
17799
17797
  bumpHistoryUi();
17798
+ } else if (mode === "text") {
17799
+ if (!textSnapshotArmedRef.current) {
17800
+ pushDocument2Snapshot(historyRef.current, documentRef.current);
17801
+ textSnapshotArmedRef.current = true;
17802
+ bumpHistoryUi();
17803
+ }
17804
+ if (textDebounceRef.current !== null) {
17805
+ window.clearTimeout(textDebounceRef.current);
17806
+ }
17807
+ textDebounceRef.current = window.setTimeout(() => {
17808
+ textSnapshotArmedRef.current = false;
17809
+ }, 400);
17800
17810
  }
17801
- if (textDebounceRef.current !== null) {
17802
- window.clearTimeout(textDebounceRef.current);
17811
+ documentRef.current = next;
17812
+ setDocumentNode(next);
17813
+ },
17814
+ [bumpHistoryUi]
17815
+ );
17816
+ const afterBlockId = useCallback2(() => resolveInsertAfterBlockId(documentRef.current, editorFocusRef.current), []);
17817
+ const insertImageBlock = useCallback2(
17818
+ (srcOrAssetId = "") => {
17819
+ clearBlockSelection();
17820
+ const after = resolveInsertAfterBlockId(documentRef.current, editorFocusRef.current);
17821
+ applyDocument(addDocument2ImageBlock(documentRef.current, srcOrAssetId, after), "immediate");
17822
+ },
17823
+ [applyDocument]
17824
+ );
17825
+ useImperativeHandle2(
17826
+ ref,
17827
+ () => ({
17828
+ insertImageBlock,
17829
+ updateImageBlockValue(blockId, value) {
17830
+ applyDocument(updateDocument2ImageValue(documentRef.current, blockId, value), "immediate");
17831
+ },
17832
+ getDocumentJson() {
17833
+ return toDocumentJson2(documentRef.current);
17803
17834
  }
17804
- textDebounceRef.current = window.setTimeout(() => {
17805
- textSnapshotArmedRef.current = false;
17806
- }, 400);
17835
+ }),
17836
+ [applyDocument, insertImageBlock]
17837
+ );
17838
+ function undoDocument() {
17839
+ const restored = restoreDocument2Undo(historyRef.current, documentRef.current);
17840
+ if (!restored) {
17841
+ return;
17807
17842
  }
17808
- setDocumentNode(next);
17809
- },
17810
- [bumpHistoryUi]
17811
- );
17812
- const afterBlockId = useCallback2(() => resolveInsertAfterBlockId(documentRef.current, editorFocus), [editorFocus]);
17813
- function undoDocument() {
17814
- const restored = restoreDocument2Undo(historyRef.current, documentRef.current);
17815
- if (!restored) {
17816
- return;
17817
- }
17818
- textSnapshotArmedRef.current = false;
17819
- clearBlockSelection();
17820
- setDocumentNode(restored);
17821
- bumpHistoryUi();
17822
- }
17823
- function redoDocument() {
17824
- const restored = restoreDocument2Redo(historyRef.current, documentRef.current);
17825
- if (!restored) {
17826
- return;
17843
+ textSnapshotArmedRef.current = false;
17844
+ clearBlockSelection();
17845
+ documentRef.current = restored;
17846
+ setDocumentNode(restored);
17847
+ bumpHistoryUi();
17827
17848
  }
17828
- textSnapshotArmedRef.current = false;
17829
- clearBlockSelection();
17830
- setDocumentNode(restored);
17831
- bumpHistoryUi();
17832
- }
17833
- function openBlock(blockId) {
17834
- if (!blockId) {
17835
- return;
17849
+ function redoDocument() {
17850
+ const restored = restoreDocument2Redo(historyRef.current, documentRef.current);
17851
+ if (!restored) {
17852
+ return;
17853
+ }
17854
+ textSnapshotArmedRef.current = false;
17855
+ clearBlockSelection();
17856
+ documentRef.current = restored;
17857
+ setDocumentNode(restored);
17858
+ bumpHistoryUi();
17836
17859
  }
17837
- setCollapsedBlockIds((current) => {
17838
- if (!current.has(blockId)) {
17839
- return current;
17860
+ function openBlock(blockId) {
17861
+ if (!blockId) {
17862
+ return;
17840
17863
  }
17841
- const next = new Set(current);
17842
- next.delete(blockId);
17843
- return next;
17844
- });
17845
- }
17846
- function toggleBlockCollapse(blockId) {
17847
- setCollapsedBlockIds((current) => {
17848
- const next = new Set(current);
17849
- if (next.has(blockId)) {
17864
+ setCollapsedBlockIds((current) => {
17865
+ if (!current.has(blockId)) {
17866
+ return current;
17867
+ }
17868
+ const next = new Set(current);
17850
17869
  next.delete(blockId);
17851
- } else {
17852
- next.add(blockId);
17853
- }
17854
- return next;
17855
- });
17856
- }
17857
- function collapseAllBlocks() {
17858
- setCollapsedBlockIds(new Set(documentRef.current.blocks.map((block) => block.id)));
17859
- }
17860
- function openAllBlocks() {
17861
- setCollapsedBlockIds(/* @__PURE__ */ new Set());
17862
- }
17863
- async function copyDebugText(text) {
17864
- try {
17865
- await navigator.clipboard.writeText(text);
17866
- } catch {
17870
+ return next;
17871
+ });
17867
17872
  }
17868
- }
17869
- function openDebugJsonImport() {
17870
- setDebugImportText(JSON.stringify(documentJson, null, 2));
17871
- setDebugImportError("");
17872
- setDebugImportOpen(true);
17873
- }
17874
- function applyDebugJsonImport() {
17875
- const parsed = parseJsonDebugInput(debugImportText);
17876
- if (!parsed.ok) {
17877
- setDebugImportError(parsed.error);
17878
- return;
17873
+ function toggleBlockCollapse(blockId) {
17874
+ setCollapsedBlockIds((current) => {
17875
+ const next = new Set(current);
17876
+ if (next.has(blockId)) {
17877
+ next.delete(blockId);
17878
+ } else {
17879
+ next.add(blockId);
17880
+ }
17881
+ return next;
17882
+ });
17879
17883
  }
17880
- try {
17881
- const imported = fromDocumentJson2(parsed.value);
17882
- textSnapshotArmedRef.current = false;
17883
- if (textDebounceRef.current !== null) {
17884
- window.clearTimeout(textDebounceRef.current);
17885
- textDebounceRef.current = null;
17886
- }
17887
- setDocumentNode(imported);
17888
- setError(null);
17889
- setSelectedMath(null);
17890
- setCitePicker(null);
17891
- setRefPicker(null);
17892
- clearBlockSelection();
17884
+ function collapseAllBlocks() {
17885
+ setCollapsedBlockIds(new Set(documentRef.current.blocks.map((block) => block.id)));
17886
+ }
17887
+ function openAllBlocks() {
17893
17888
  setCollapsedBlockIds(/* @__PURE__ */ new Set());
17894
- setEditorFocus(createEmptyDocument2EditorFocus());
17895
- historyRef.current = createDocument2History();
17896
- bumpHistoryUi();
17889
+ }
17890
+ async function copyDebugText(text) {
17891
+ try {
17892
+ await navigator.clipboard.writeText(text);
17893
+ } catch {
17894
+ }
17895
+ }
17896
+ function openDebugJsonImport() {
17897
+ setDebugImportText(JSON.stringify(documentJson, null, 2));
17897
17898
  setDebugImportError("");
17898
- setDebugImportOpen(false);
17899
- } catch (importError) {
17900
- setDebugImportError(importError instanceof Error ? importError.message : String(importError));
17899
+ setDebugImportOpen(true);
17901
17900
  }
17902
- }
17903
- useEffect9(() => {
17904
- const root = widgetRef.current;
17905
- if (!root) {
17906
- return;
17901
+ function applyDebugJsonImport() {
17902
+ const parsed = parseJsonDebugInput(debugImportText);
17903
+ if (!parsed.ok) {
17904
+ setDebugImportError(parsed.error);
17905
+ return;
17906
+ }
17907
+ try {
17908
+ const imported = fromDocumentJson2(parsed.value);
17909
+ textSnapshotArmedRef.current = false;
17910
+ if (textDebounceRef.current !== null) {
17911
+ window.clearTimeout(textDebounceRef.current);
17912
+ textDebounceRef.current = null;
17913
+ }
17914
+ setDocumentNode(imported);
17915
+ setError(null);
17916
+ setSelectedMath(null);
17917
+ setCitePicker(null);
17918
+ setRefPicker(null);
17919
+ clearBlockSelection();
17920
+ setCollapsedBlockIds(/* @__PURE__ */ new Set());
17921
+ setEditorFocus(createEmptyDocument2EditorFocus());
17922
+ historyRef.current = createDocument2History();
17923
+ bumpHistoryUi();
17924
+ setDebugImportError("");
17925
+ setDebugImportOpen(false);
17926
+ } catch (importError) {
17927
+ setDebugImportError(importError instanceof Error ? importError.message : String(importError));
17928
+ }
17907
17929
  }
17908
- const onKeyDown = (event) => {
17909
- if (!editorOpen) {
17930
+ useEffect9(() => {
17931
+ const root = widgetRef.current;
17932
+ if (!root) {
17910
17933
  return;
17911
17934
  }
17912
- const mod = event.ctrlKey || event.metaKey;
17913
- if (!mod) {
17935
+ const onKeyDown = (event) => {
17936
+ if (!editorOpen) {
17937
+ return;
17938
+ }
17939
+ const mod = event.ctrlKey || event.metaKey;
17940
+ if (!mod) {
17941
+ return;
17942
+ }
17943
+ if (event.key.toLowerCase() === "z" && !event.shiftKey) {
17944
+ event.preventDefault();
17945
+ undoDocument();
17946
+ } else if (event.key.toLowerCase() === "z" && event.shiftKey || event.key.toLowerCase() === "y") {
17947
+ event.preventDefault();
17948
+ redoDocument();
17949
+ }
17950
+ };
17951
+ root.addEventListener("keydown", onKeyDown);
17952
+ return () => root.removeEventListener("keydown", onKeyDown);
17953
+ }, [editorOpen]);
17954
+ function rememberFieldFocus(blockId, fieldId, textTokenId, caretOffset, selectionStart, selectionEnd) {
17955
+ openBlock(blockId);
17956
+ clearBlockSelection();
17957
+ setEditorFocus({ blockId, fieldId, textTokenId, caretOffset, selectionStart, selectionEnd });
17958
+ }
17959
+ function rememberMathFocus(blockId, fieldId) {
17960
+ openBlock(blockId);
17961
+ clearBlockSelection();
17962
+ setEditorFocus({ blockId, fieldId, textTokenId: null, caretOffset: 0, selectionStart: 0, selectionEnd: 0 });
17963
+ }
17964
+ function rememberBlockFocus(blockId) {
17965
+ openBlock(blockId);
17966
+ setEditorFocus((current) => ({ ...current, blockId }));
17967
+ }
17968
+ function onFieldBlur() {
17969
+ textSnapshotArmedRef.current = false;
17970
+ }
17971
+ function openNewEquation(mode) {
17972
+ if (!editableEquations) {
17914
17973
  return;
17915
17974
  }
17916
- if (event.key.toLowerCase() === "z" && !event.shiftKey) {
17917
- event.preventDefault();
17918
- undoDocument();
17919
- } else if (event.key.toLowerCase() === "z" && event.shiftKey || event.key.toLowerCase() === "y") {
17920
- event.preventDefault();
17921
- redoDocument();
17975
+ const target = resolveInsertField(documentRef.current, editorFocus);
17976
+ if (target?.fieldId) {
17977
+ openBlock(topLevelBlockIdForField(documentRef.current, target.fieldId));
17922
17978
  }
17923
- };
17924
- root.addEventListener("keydown", onKeyDown);
17925
- return () => root.removeEventListener("keydown", onKeyDown);
17926
- }, [editorOpen]);
17927
- function rememberFieldFocus(blockId, fieldId, textTokenId, caretOffset, selectionStart, selectionEnd) {
17928
- openBlock(blockId);
17929
- clearBlockSelection();
17930
- setEditorFocus({ blockId, fieldId, textTokenId, caretOffset, selectionStart, selectionEnd });
17931
- }
17932
- function rememberMathFocus(blockId, fieldId) {
17933
- openBlock(blockId);
17934
- clearBlockSelection();
17935
- setEditorFocus({ blockId, fieldId, textTokenId: null, caretOffset: 0, selectionStart: 0, selectionEnd: 0 });
17936
- }
17937
- function rememberBlockFocus(blockId) {
17938
- openBlock(blockId);
17939
- setEditorFocus((current) => ({ ...current, blockId }));
17940
- }
17941
- function onFieldBlur() {
17942
- textSnapshotArmedRef.current = false;
17943
- }
17944
- function openNewEquation(mode) {
17945
- if (!editableEquations) {
17946
- return;
17947
- }
17948
- const target = resolveInsertField(documentRef.current, editorFocus);
17949
- if (target?.fieldId) {
17950
- openBlock(topLevelBlockIdForField(documentRef.current, target.fieldId));
17951
- }
17952
- setSelectedMath({
17953
- tokenId: null,
17954
- fieldId: target?.fieldId ?? null,
17955
- textTokenId: target?.textTokenId ?? null,
17956
- insertAt: target?.caretOffset ?? 0,
17957
- mathMode: mode,
17958
- session: equationSessionWithDocumentDigits(createEmptyEquationSession(equationSide)),
17959
- reason: null,
17960
- labelEnabled: false,
17961
- label: ""
17962
- });
17963
- }
17964
- function openMath(token) {
17965
- if (!editableEquations) {
17966
- return;
17979
+ setSelectedMath({
17980
+ tokenId: null,
17981
+ fieldId: target?.fieldId ?? null,
17982
+ textTokenId: target?.textTokenId ?? null,
17983
+ insertAt: target?.caretOffset ?? 0,
17984
+ mathMode: mode,
17985
+ session: equationSessionWithDocumentDigits(createEmptyEquationSession(equationSide)),
17986
+ reason: null,
17987
+ labelEnabled: false,
17988
+ label: ""
17989
+ });
17967
17990
  }
17968
- openBlock(topLevelBlockIdForToken(documentRef.current, token.id));
17969
- const result = mathTokenToEditorSession(token.math, equationSide);
17970
- const mode = token.display ? "display" : "inline";
17971
- if (!result.editable) {
17991
+ function openMath(token) {
17992
+ if (!editableEquations) {
17993
+ return;
17994
+ }
17995
+ openBlock(topLevelBlockIdForToken(documentRef.current, token.id));
17996
+ const result = mathTokenToEditorSession(token.math, equationSide);
17997
+ const mode = token.display ? "display" : "inline";
17998
+ if (!result.editable) {
17999
+ setSelectedMath({
18000
+ tokenId: token.id,
18001
+ fieldId: null,
18002
+ insertAt: 0,
18003
+ textTokenId: null,
18004
+ mathMode: mode,
18005
+ session: equationSessionWithDocumentDigits(createEmptyEquationSession(equationSide)),
18006
+ reason: result.reason,
18007
+ labelEnabled: Boolean(token.labelEnabled),
18008
+ label: token.label ?? ""
18009
+ });
18010
+ return;
18011
+ }
17972
18012
  setSelectedMath({
17973
18013
  tokenId: token.id,
17974
18014
  fieldId: null,
17975
18015
  insertAt: 0,
17976
18016
  textTokenId: null,
17977
18017
  mathMode: mode,
17978
- session: equationSessionWithDocumentDigits(createEmptyEquationSession(equationSide)),
17979
- reason: result.reason,
18018
+ session: equationSessionWithDocumentDigits(result.session),
18019
+ reason: null,
17980
18020
  labelEnabled: Boolean(token.labelEnabled),
17981
18021
  label: token.label ?? ""
17982
18022
  });
17983
- return;
17984
18023
  }
17985
- setSelectedMath({
17986
- tokenId: token.id,
17987
- fieldId: null,
17988
- insertAt: 0,
17989
- textTokenId: null,
17990
- mathMode: mode,
17991
- session: equationSessionWithDocumentDigits(result.session),
17992
- reason: null,
17993
- labelEnabled: Boolean(token.labelEnabled),
17994
- label: token.label ?? ""
17995
- });
17996
- }
17997
- function toggleEditorPanel() {
17998
- setEditorOpen((open) => {
17999
- if (open && !previewOpen) {
18000
- setPreviewOpen(true);
18024
+ function toggleEditorPanel() {
18025
+ setEditorOpen((open) => {
18026
+ if (open && !previewOpen) {
18027
+ setPreviewOpen(true);
18028
+ }
18029
+ return !open;
18030
+ });
18031
+ }
18032
+ function togglePreviewPanel() {
18033
+ setPreviewOpen((open) => {
18034
+ if (open && !editorOpen) {
18035
+ setEditorOpen(true);
18036
+ }
18037
+ return !open;
18038
+ });
18039
+ }
18040
+ function saveEquation(session) {
18041
+ if (!selectedMath) {
18042
+ return;
18001
18043
  }
18002
- return !open;
18003
- });
18004
- }
18005
- function togglePreviewPanel() {
18006
- setPreviewOpen((open) => {
18007
- if (open && !editorOpen) {
18008
- setEditorOpen(true);
18044
+ const delimiters = mathDelimiters(selectedMath.mathMode);
18045
+ if (selectedMath.tokenId) {
18046
+ let next2 = replaceMathTokenFromSession(
18047
+ documentRef.current,
18048
+ selectedMath.tokenId,
18049
+ session,
18050
+ delimiters.opening,
18051
+ delimiters.closing,
18052
+ equationSide
18053
+ );
18054
+ if (selectedMath.mathMode === "display") {
18055
+ next2 = updateMathTokenLabel(next2, selectedMath.tokenId, {
18056
+ labelEnabled: selectedMath.labelEnabled,
18057
+ label: selectedMath.label
18058
+ });
18059
+ } else {
18060
+ next2 = updateMathTokenLabel(next2, selectedMath.tokenId, { labelEnabled: false, label: "" });
18061
+ }
18062
+ pendingFocusRef.current = { kind: "math", tokenId: selectedMath.tokenId };
18063
+ applyDocument(next2, "immediate");
18064
+ setSelectedMath(null);
18065
+ return;
18009
18066
  }
18010
- return !open;
18011
- });
18012
- }
18013
- function saveEquation(session) {
18014
- if (!selectedMath) {
18015
- return;
18016
- }
18017
- const delimiters = mathDelimiters(selectedMath.mathMode);
18018
- if (selectedMath.tokenId) {
18019
- let next2 = replaceMathTokenFromSession(
18020
- documentRef.current,
18021
- selectedMath.tokenId,
18067
+ let current = documentRef.current;
18068
+ let fieldId = selectedMath.fieldId;
18069
+ let textTokenId = selectedMath.textTokenId;
18070
+ let insertAt = selectedMath.insertAt;
18071
+ if (!fieldId) {
18072
+ const anchor = afterBlockId();
18073
+ current = addDocument2TextBlock(current, "\\paragraph", anchor);
18074
+ const anchorIndex = anchor ? current.blocks.findIndex((block) => block.id === anchor) : -1;
18075
+ const newIndex = anchorIndex >= 0 ? anchorIndex + 1 : current.blocks.length - 1;
18076
+ const newBlock = current.blocks[newIndex];
18077
+ const field = newBlock?.kind === "textBlock" ? newBlock.field : null;
18078
+ if (!field) {
18079
+ setSelectedMath(null);
18080
+ return;
18081
+ }
18082
+ fieldId = field.id;
18083
+ textTokenId = field.tokens.find((token) => token.kind === "text")?.id ?? null;
18084
+ insertAt = 0;
18085
+ }
18086
+ let next = insertMathTokenAtCaret(
18087
+ current,
18088
+ fieldId,
18089
+ textTokenId,
18090
+ insertAt,
18022
18091
  session,
18023
18092
  delimiters.opening,
18024
18093
  delimiters.closing,
18025
18094
  equationSide
18026
18095
  );
18027
- if (selectedMath.mathMode === "display") {
18028
- next2 = updateMathTokenLabel(next2, selectedMath.tokenId, {
18029
- labelEnabled: selectedMath.labelEnabled,
18096
+ const trailingTextTokenId = trailingTextTokenAfterInsertedMath(current, next, fieldId, textTokenId, insertAt);
18097
+ const fieldAfter = findInlineFieldById(next, fieldId);
18098
+ const insertedMathId = trailingTextTokenId && fieldAfter ? fieldAfter.tokens[Math.max(
18099
+ 0,
18100
+ fieldAfter.tokens.findIndex((token) => token.id === trailingTextTokenId) - 1
18101
+ )]?.kind === "math" ? fieldAfter.tokens[Math.max(
18102
+ 0,
18103
+ fieldAfter.tokens.findIndex((token) => token.id === trailingTextTokenId) - 1
18104
+ )]?.id : null : fieldAfter?.tokens.filter((token) => token.kind === "math").at(-1)?.id ?? null;
18105
+ if (insertedMathId && selectedMath.mathMode === "display" && selectedMath.labelEnabled) {
18106
+ next = updateMathTokenLabel(next, insertedMathId, {
18107
+ labelEnabled: true,
18030
18108
  label: selectedMath.label
18031
18109
  });
18032
- } else {
18033
- next2 = updateMathTokenLabel(next2, selectedMath.tokenId, { labelEnabled: false, label: "" });
18034
18110
  }
18035
- pendingFocusRef.current = { kind: "math", tokenId: selectedMath.tokenId };
18036
- applyDocument(next2, "immediate");
18111
+ if (trailingTextTokenId) {
18112
+ pendingFocusRef.current = { kind: "text", fieldId, textTokenId: trailingTextTokenId, caretOffset: 0 };
18113
+ }
18114
+ applyDocument(next, "immediate");
18037
18115
  setSelectedMath(null);
18038
- return;
18039
18116
  }
18040
- let current = documentRef.current;
18041
- let fieldId = selectedMath.fieldId;
18042
- let textTokenId = selectedMath.textTokenId;
18043
- let insertAt = selectedMath.insertAt;
18044
- if (!fieldId) {
18045
- const anchor = afterBlockId();
18046
- current = addDocument2TextBlock(current, "\\paragraph", anchor);
18047
- const anchorIndex = anchor ? current.blocks.findIndex((block) => block.id === anchor) : -1;
18048
- const newIndex = anchorIndex >= 0 ? anchorIndex + 1 : current.blocks.length - 1;
18049
- const newBlock = current.blocks[newIndex];
18050
- const field = newBlock?.kind === "textBlock" ? newBlock.field : null;
18051
- if (!field) {
18052
- setSelectedMath(null);
18117
+ function deleteSelectedEquation() {
18118
+ if (!selectedMath?.tokenId) {
18053
18119
  return;
18054
18120
  }
18055
- fieldId = field.id;
18056
- textTokenId = field.tokens.find((token) => token.kind === "text")?.id ?? null;
18057
- insertAt = 0;
18058
- }
18059
- let next = insertMathTokenAtCaret(
18060
- current,
18061
- fieldId,
18062
- textTokenId,
18063
- insertAt,
18064
- session,
18065
- delimiters.opening,
18066
- delimiters.closing,
18067
- equationSide
18068
- );
18069
- const trailingTextTokenId = trailingTextTokenAfterInsertedMath(current, next, fieldId, textTokenId, insertAt);
18070
- const fieldAfter = findInlineFieldById(next, fieldId);
18071
- const insertedMathId = trailingTextTokenId && fieldAfter ? fieldAfter.tokens[Math.max(
18072
- 0,
18073
- fieldAfter.tokens.findIndex((token) => token.id === trailingTextTokenId) - 1
18074
- )]?.kind === "math" ? fieldAfter.tokens[Math.max(
18075
- 0,
18076
- fieldAfter.tokens.findIndex((token) => token.id === trailingTextTokenId) - 1
18077
- )]?.id : null : fieldAfter?.tokens.filter((token) => token.kind === "math").at(-1)?.id ?? null;
18078
- if (insertedMathId && selectedMath.mathMode === "display" && selectedMath.labelEnabled) {
18079
- next = updateMathTokenLabel(next, insertedMathId, {
18080
- labelEnabled: true,
18081
- label: selectedMath.label
18082
- });
18083
- }
18084
- if (trailingTextTokenId) {
18085
- pendingFocusRef.current = { kind: "text", fieldId, textTokenId: trailingTextTokenId, caretOffset: 0 };
18086
- }
18087
- applyDocument(next, "immediate");
18088
- setSelectedMath(null);
18089
- }
18090
- function deleteSelectedEquation() {
18091
- if (!selectedMath?.tokenId) {
18092
- return;
18121
+ const current = documentRef.current;
18122
+ const next = removeMathTokenById(current, selectedMath.tokenId);
18123
+ pendingFocusRef.current = focusAfterDeletedMath(current, next, selectedMath.tokenId);
18124
+ applyDocument(next, "immediate");
18125
+ setSelectedMath(null);
18093
18126
  }
18094
- const current = documentRef.current;
18095
- const next = removeMathTokenById(current, selectedMath.tokenId);
18096
- pendingFocusRef.current = focusAfterDeletedMath(current, next, selectedMath.tokenId);
18097
- applyDocument(next, "immediate");
18098
- setSelectedMath(null);
18099
- }
18100
- function deleteMathToken(tokenId) {
18101
- const current = documentRef.current;
18102
- const next = removeMathTokenById(current, tokenId);
18103
- pendingFocusRef.current = focusAfterDeletedMath(current, next, tokenId);
18104
- applyDocument(next, "immediate");
18105
- }
18106
- function openCitePickerForInsert() {
18107
- const target = resolveInsertField(documentRef.current, editorFocus);
18108
- setCitePicker({
18109
- tokenId: null,
18110
- fieldId: target?.fieldId ?? null,
18111
- textTokenId: target?.textTokenId ?? editorFocus.textTokenId,
18112
- caretOffset: target?.caretOffset ?? editorFocus.caretOffset,
18113
- keys: []
18114
- });
18115
- }
18116
- function openCite(token) {
18117
- setCitePicker({
18118
- tokenId: token.id,
18119
- fieldId: null,
18120
- textTokenId: null,
18121
- caretOffset: 0,
18122
- keys: [...token.keys]
18123
- });
18124
- }
18125
- function confirmCiteKeys(keys) {
18126
- if (!citePicker || keys.length === 0) {
18127
- setCitePicker(null);
18128
- return;
18127
+ function deleteMathToken(tokenId) {
18128
+ const current = documentRef.current;
18129
+ const next = removeMathTokenById(current, tokenId);
18130
+ pendingFocusRef.current = focusAfterDeletedMath(current, next, tokenId);
18131
+ applyDocument(next, "immediate");
18132
+ }
18133
+ function openCitePickerForInsert() {
18134
+ const target = resolveInsertField(documentRef.current, editorFocus);
18135
+ setCitePicker({
18136
+ tokenId: null,
18137
+ fieldId: target?.fieldId ?? null,
18138
+ textTokenId: target?.textTokenId ?? editorFocus.textTokenId,
18139
+ caretOffset: target?.caretOffset ?? editorFocus.caretOffset,
18140
+ keys: []
18141
+ });
18129
18142
  }
18130
- if (citePicker.tokenId) {
18131
- applyDocument(updateCiteTokenKeys(documentRef.current, citePicker.tokenId, keys), "immediate");
18132
- pendingFocusRef.current = { kind: "cite", tokenId: citePicker.tokenId };
18133
- setCitePicker(null);
18134
- return;
18143
+ function openCite(token) {
18144
+ setCitePicker({
18145
+ tokenId: token.id,
18146
+ fieldId: null,
18147
+ textTokenId: null,
18148
+ caretOffset: 0,
18149
+ keys: [...token.keys]
18150
+ });
18135
18151
  }
18136
- const target = resolveInsertField(documentRef.current, editorFocus);
18137
- const fieldId = citePicker.fieldId ?? target?.fieldId;
18138
- if (!fieldId) {
18152
+ function confirmCiteKeys(keys) {
18153
+ if (!citePicker || keys.length === 0) {
18154
+ setCitePicker(null);
18155
+ return;
18156
+ }
18157
+ if (citePicker.tokenId) {
18158
+ applyDocument(updateCiteTokenKeys(documentRef.current, citePicker.tokenId, keys), "immediate");
18159
+ pendingFocusRef.current = { kind: "cite", tokenId: citePicker.tokenId };
18160
+ setCitePicker(null);
18161
+ return;
18162
+ }
18163
+ const target = resolveInsertField(documentRef.current, editorFocus);
18164
+ const fieldId = citePicker.fieldId ?? target?.fieldId;
18165
+ if (!fieldId) {
18166
+ setCitePicker(null);
18167
+ return;
18168
+ }
18169
+ const textTokenId = citePicker.textTokenId ?? target?.textTokenId ?? null;
18170
+ const caretOffset = citePicker.caretOffset ?? target?.caretOffset ?? 0;
18171
+ const next = insertCiteTokenAtCaret(documentRef.current, fieldId, textTokenId, caretOffset, keys);
18172
+ applyDocument(next, "immediate");
18139
18173
  setCitePicker(null);
18140
- return;
18141
18174
  }
18142
- const textTokenId = citePicker.textTokenId ?? target?.textTokenId ?? null;
18143
- const caretOffset = citePicker.caretOffset ?? target?.caretOffset ?? 0;
18144
- const next = insertCiteTokenAtCaret(documentRef.current, fieldId, textTokenId, caretOffset, keys);
18145
- applyDocument(next, "immediate");
18146
- setCitePicker(null);
18147
- }
18148
- function deleteCiteToken(tokenId) {
18149
- applyDocument(removeCiteTokenById(documentRef.current, tokenId), "immediate");
18150
- }
18151
- function openRefPickerForInsert() {
18152
- const target = resolveInsertField(documentRef.current, editorFocus);
18153
- setRefPicker({
18154
- tokenId: null,
18155
- fieldId: target?.fieldId ?? null,
18156
- textTokenId: target?.textTokenId ?? editorFocus.textTokenId,
18157
- caretOffset: target?.caretOffset ?? editorFocus.caretOffset,
18158
- keys: [],
18159
- refCommand: "ref"
18160
- });
18161
- }
18162
- function openRef(token) {
18163
- setRefPicker({
18164
- tokenId: token.id,
18165
- fieldId: null,
18166
- textTokenId: null,
18167
- caretOffset: 0,
18168
- keys: [...token.keys],
18169
- refCommand: token.refCommand
18170
- });
18171
- }
18172
- function confirmRefKeys(keys, refCommand) {
18173
- if (!refPicker || keys.length === 0) {
18174
- setRefPicker(null);
18175
- return;
18175
+ function deleteCiteToken(tokenId) {
18176
+ applyDocument(removeCiteTokenById(documentRef.current, tokenId), "immediate");
18177
+ }
18178
+ function openRefPickerForInsert() {
18179
+ const target = resolveInsertField(documentRef.current, editorFocus);
18180
+ setRefPicker({
18181
+ tokenId: null,
18182
+ fieldId: target?.fieldId ?? null,
18183
+ textTokenId: target?.textTokenId ?? editorFocus.textTokenId,
18184
+ caretOffset: target?.caretOffset ?? editorFocus.caretOffset,
18185
+ keys: [],
18186
+ refCommand: "ref"
18187
+ });
18176
18188
  }
18177
- if (refPicker.tokenId) {
18178
- applyDocument(updateRefTokenKeys(documentRef.current, refPicker.tokenId, keys, refCommand), "immediate");
18179
- pendingFocusRef.current = { kind: "ref", tokenId: refPicker.tokenId };
18180
- setRefPicker(null);
18181
- return;
18189
+ function openRef(token) {
18190
+ setRefPicker({
18191
+ tokenId: token.id,
18192
+ fieldId: null,
18193
+ textTokenId: null,
18194
+ caretOffset: 0,
18195
+ keys: [...token.keys],
18196
+ refCommand: token.refCommand
18197
+ });
18182
18198
  }
18183
- const target = resolveInsertField(documentRef.current, editorFocus);
18184
- const fieldId = refPicker.fieldId ?? target?.fieldId;
18185
- if (!fieldId) {
18199
+ function confirmRefKeys(keys, refCommand) {
18200
+ if (!refPicker || keys.length === 0) {
18201
+ setRefPicker(null);
18202
+ return;
18203
+ }
18204
+ if (refPicker.tokenId) {
18205
+ applyDocument(updateRefTokenKeys(documentRef.current, refPicker.tokenId, keys, refCommand), "immediate");
18206
+ pendingFocusRef.current = { kind: "ref", tokenId: refPicker.tokenId };
18207
+ setRefPicker(null);
18208
+ return;
18209
+ }
18210
+ const target = resolveInsertField(documentRef.current, editorFocus);
18211
+ const fieldId = refPicker.fieldId ?? target?.fieldId;
18212
+ if (!fieldId) {
18213
+ setRefPicker(null);
18214
+ return;
18215
+ }
18216
+ const textTokenId = refPicker.textTokenId ?? target?.textTokenId ?? null;
18217
+ const caretOffset = refPicker.caretOffset ?? target?.caretOffset ?? 0;
18218
+ const next = insertRefTokenAtCaret(documentRef.current, fieldId, textTokenId, caretOffset, keys, refCommand);
18219
+ applyDocument(next, "immediate");
18186
18220
  setRefPicker(null);
18187
- return;
18188
18221
  }
18189
- const textTokenId = refPicker.textTokenId ?? target?.textTokenId ?? null;
18190
- const caretOffset = refPicker.caretOffset ?? target?.caretOffset ?? 0;
18191
- const next = insertRefTokenAtCaret(documentRef.current, fieldId, textTokenId, caretOffset, keys, refCommand);
18192
- applyDocument(next, "immediate");
18193
- setRefPicker(null);
18194
- }
18195
- function deleteRefToken(tokenId) {
18196
- applyDocument(removeRefTokenById(documentRef.current, tokenId), "immediate");
18197
- }
18198
- function toggleInlineTextStyle(styleName) {
18199
- if (!canFormatText || !editorFocus.fieldId || !editorFocus.textTokenId) {
18200
- return;
18222
+ function deleteRefToken(tokenId) {
18223
+ applyDocument(removeRefTokenById(documentRef.current, tokenId), "immediate");
18201
18224
  }
18202
- applyDocument(
18203
- toggleTextTokenStyle(
18204
- documentRef.current,
18205
- editorFocus.fieldId,
18206
- editorFocus.textTokenId,
18207
- editorFocus.selectionStart,
18208
- editorFocus.selectionEnd,
18209
- styleName
18210
- ),
18211
- "immediate"
18212
- );
18213
- }
18214
- const showEditorPanel = !previewOnly && editorOpen;
18215
- const showPreviewPanel = previewOnly || previewOpen;
18216
- return /* @__PURE__ */ jsx17(
18217
- "div",
18218
- {
18219
- ref: widgetRef,
18220
- className: ["butex-document2-widget", className].filter(Boolean).join(" "),
18221
- dir: uiLocaleDirection(uiLocale),
18222
- lang: uiLocale,
18223
- children: /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__shell", children: [
18224
- !previewOnly ? /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__toolbar", children: [
18225
- /* @__PURE__ */ jsx17(
18226
- DocumentInsertToolbar,
18227
- {
18228
- canUndo,
18229
- canRedo,
18230
- editableEquations,
18231
- uiLocale,
18232
- digitForm,
18233
- selectionCount,
18234
- canMoveSelectionUp,
18235
- canMoveSelectionDown,
18236
- canFormatText,
18237
- activeTextStyles,
18238
- onUndo: undoDocument,
18239
- onRedo: redoDocument,
18240
- onToggleTextStyle: toggleInlineTextStyle,
18241
- onMoveSelectionUp: () => moveSelectedBlocks(-1),
18242
- onMoveSelectionDown: () => moveSelectedBlocks(1),
18243
- onDeleteSelection: deleteSelectedBlocks,
18244
- onAddSection: () => {
18245
- clearBlockSelection();
18246
- applyDocument(addDocument2TextBlock(documentRef.current, "\\section", afterBlockId()), "immediate");
18247
- },
18248
- onAddSubsection: () => {
18249
- clearBlockSelection();
18250
- applyDocument(addDocument2TextBlock(documentRef.current, "\\subsection", afterBlockId()), "immediate");
18251
- },
18252
- onAddSubsubsection: () => {
18253
- clearBlockSelection();
18254
- applyDocument(addDocument2TextBlock(documentRef.current, "\\subsubsection", afterBlockId()), "immediate");
18255
- },
18256
- onAddParagraph: () => {
18257
- clearBlockSelection();
18258
- applyDocument(addDocument2TextBlock(documentRef.current, "\\paragraph", afterBlockId()), "immediate");
18259
- },
18260
- onAddInlineEquation: () => openNewEquation("inline"),
18261
- onAddDisplayEquation: () => openNewEquation("display"),
18262
- onAddTable: (rowCount, colCount) => {
18263
- clearBlockSelection();
18264
- applyDocument(addDocument2TableBlock(documentRef.current, "l".repeat(colCount), rowCount, colCount, afterBlockId()), "immediate");
18265
- },
18266
- onAddList: () => {
18267
- clearBlockSelection();
18268
- applyDocument(addDocument2ListBlock(documentRef.current, false, afterBlockId()), "immediate");
18269
- },
18270
- onAddEnumerate: () => {
18271
- clearBlockSelection();
18272
- applyDocument(addDocument2ListBlock(documentRef.current, true, afterBlockId()), "immediate");
18273
- },
18274
- onAddFigure: () => {
18275
- clearBlockSelection();
18276
- applyDocument(addDocument2ImageBlock(documentRef.current, "", afterBlockId()), "immediate");
18277
- },
18278
- onInsertCitation: openCitePickerForInsert,
18279
- onInsertInternalRef: openRefPickerForInsert,
18280
- onInsertBibliography: () => {
18281
- clearBlockSelection();
18282
- applyDocument(ensureDocument2BibliographyBlock(documentRef.current, afterBlockId()), "immediate");
18283
- },
18284
- onManageReferences: () => setReferencesOpen(true),
18285
- onManageLabels: () => setLabelsOpen(true),
18286
- onOpenArticleMeta: () => focusArticleMetaPanel(articleMetaPanelRef.current),
18287
- onDigitFormChange: (next) => {
18288
- setDigitFormState(next);
18289
- onDigitFormChange?.(next);
18290
- }
18291
- }
18292
- ),
18293
- /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.panels, children: [
18294
- /* @__PURE__ */ jsx17("button", { type: "button", "aria-pressed": editorOpen, onClick: toggleEditorPanel, children: editorOpen ? messages.hideEditor : messages.editor }),
18295
- /* @__PURE__ */ jsx17("button", { type: "button", "aria-pressed": previewOpen, onClick: togglePreviewPanel, children: previewOpen ? messages.hidePreview : messages.preview })
18296
- ] }),
18297
- /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.collapseBlocks, children: [
18298
- /* @__PURE__ */ jsx17("button", { type: "button", onClick: collapseAllBlocks, children: messages.collapseAll }),
18299
- /* @__PURE__ */ jsx17("button", { type: "button", onClick: openAllBlocks, children: messages.openAll })
18300
- ] })
18301
- ] }) : null,
18302
- error ? /* @__PURE__ */ jsx17("p", { className: "butex-document2-widget__error", children: error }) : null,
18303
- /* @__PURE__ */ jsxs15(
18304
- "div",
18305
- {
18306
- className: `butex-document2-widget__layout butex-document2-widget__layout--editor-${showEditorPanel ? "open" : "closed"} butex-document2-widget__layout--preview-${showPreviewPanel ? "open" : "closed"}`,
18307
- children: [
18308
- !previewOnly ? /* @__PURE__ */ jsx17(
18309
- "section",
18310
- {
18311
- className: "butex-document2-widget__panel butex-document2-widget__editor-panel",
18312
- "aria-label": messages.documentEditor,
18313
- "aria-hidden": !showEditorPanel,
18314
- children: /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__blocks", children: [
18315
- /* @__PURE__ */ jsx17(
18316
- ArticleMetaPanel,
18317
- {
18318
- meta: documentNode.meta ?? emptyDocument2Meta(),
18319
- uiLocale,
18320
- digitForm,
18321
- panelRef: articleMetaPanelRef,
18322
- onChange: (patch) => {
18323
- clearBlockSelection();
18324
- applyDocument(updateDocument2Meta(documentRef.current, patch), "text");
18325
- }
18326
- }
18327
- ),
18328
- documentNode.blocks.map((block, blockIndex) => /* @__PURE__ */ jsx17(
18329
- BlockEditor,
18330
- {
18331
- block,
18332
- references: documentNode.references,
18333
- documentNode,
18334
- documentDirection,
18335
- digitForm,
18336
- mathOutput,
18337
- equationSide,
18338
- editableEquations,
18339
- editableCitations: !previewOnly,
18340
- uiLocale,
18341
- isCollapsed: collapsedBlockIds.has(block.id),
18342
- selected: Boolean(blockSelection && blockIndex >= blockSelection.from && blockIndex <= blockSelection.to),
18343
- onToggleSelect: toggleSelectBlock,
18344
- onTextChange: (fieldId, tokenId, text) => {
18345
- clearBlockSelection();
18346
- applyDocument(updateTextToken(documentRef.current, fieldId, tokenId, text), "text");
18347
- },
18348
- onOpenMath: openMath,
18349
- onDeleteMath: editableEquations ? deleteMathToken : void 0,
18350
- onOpenCite: openCite,
18351
- onDeleteCite: deleteCiteToken,
18352
- onOpenRef: openRef,
18353
- onDeleteRef: deleteRefToken,
18354
- onToggleCollapse: toggleBlockCollapse,
18355
- onBlockFocus: rememberBlockFocus,
18356
- onFieldFocus: rememberFieldFocus,
18357
- onMathFocus: rememberMathFocus,
18358
- onFieldBlur,
18359
- onImageSrcChange: (blockId, value) => {
18360
- clearBlockSelection();
18361
- applyDocument(updateDocument2ImageValue(documentRef.current, blockId, value), "text");
18362
- },
18363
- onFloatMetaChange: (blockId, kind, patch) => {
18364
- clearBlockSelection();
18365
- applyDocument(
18366
- kind === "image" ? updateDocument2ImageMeta(documentRef.current, blockId, patch) : updateDocument2TableMeta(documentRef.current, blockId, patch),
18367
- "text"
18368
- );
18369
- },
18370
- onParagraphCenteredChange: (blockId, centered) => {
18371
- clearBlockSelection();
18372
- applyDocument(updateDocument2TextBlockCentered(documentRef.current, blockId, centered), "text");
18373
- },
18374
- onAddListItem: (listBlockId) => {
18375
- clearBlockSelection();
18376
- applyDocument(addDocument2ListItem(documentRef.current, listBlockId), "immediate");
18377
- },
18378
- onRemoveListItem: (listBlockId, itemId) => {
18379
- clearBlockSelection();
18380
- applyDocument(removeDocument2ListItem(documentRef.current, listBlockId, itemId), "immediate");
18381
- },
18382
- onManageReferences: () => setReferencesOpen(true)
18383
- },
18384
- block.id
18385
- ))
18386
- ] })
18387
- }
18388
- ) : null,
18389
- /* @__PURE__ */ jsx17(
18390
- "section",
18391
- {
18392
- className: "butex-document2-widget__panel butex-document2-widget__preview-panel",
18393
- "aria-label": messages.documentPreview,
18394
- "aria-hidden": !showPreviewPanel,
18395
- children: /* @__PURE__ */ jsx17(
18396
- DocumentPreview,
18397
- {
18398
- blocks: preview.blocks,
18399
- output: mathOutput,
18400
- documentDirection,
18401
- uiLocale,
18402
- digitForm,
18403
- resolveImageUrl
18404
- }
18405
- )
18406
- }
18407
- )
18408
- ]
18409
- }
18225
+ function toggleInlineTextStyle(styleName) {
18226
+ if (!canFormatText || !editorFocus.fieldId || !editorFocus.textTokenId) {
18227
+ return;
18228
+ }
18229
+ applyDocument(
18230
+ toggleTextTokenStyle(
18231
+ documentRef.current,
18232
+ editorFocus.fieldId,
18233
+ editorFocus.textTokenId,
18234
+ editorFocus.selectionStart,
18235
+ editorFocus.selectionEnd,
18236
+ styleName
18410
18237
  ),
18411
- debugEnabled ? /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__dev", children: [
18412
- debugEnabled && documentNode.diagnostics.length > 0 ? /* @__PURE__ */ jsxs15(Fragment4, { children: [
18413
- /* @__PURE__ */ jsx17("strong", { children: messages.importWarnings }),
18414
- documentNode.diagnostics.map((diagnostic) => /* @__PURE__ */ jsx17("p", { className: "butex-document2-widget__dev-diagnostic", children: formatDocument2Diagnostic(diagnostic, messages) }, `${diagnostic.path}-${diagnostic.message}`))
18415
- ] }) : null,
18416
- /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__dev-actions", children: [
18417
- /* @__PURE__ */ jsx17("button", { type: "button", onClick: () => void copyDebugText(JSON.stringify(documentJson, null, 2)), children: "Copy JSON" }),
18418
- /* @__PURE__ */ jsx17("button", { type: "button", onClick: () => void copyDebugText(latex), children: "Copy TeX" }),
18419
- /* @__PURE__ */ jsx17("button", { type: "button", "aria-expanded": debugImportOpen, onClick: openDebugJsonImport, children: "Import JSON" })
18420
- ] }),
18421
- debugImportOpen ? /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__dev-import", children: [
18238
+ "immediate"
18239
+ );
18240
+ }
18241
+ const showEditorPanel = !previewOnly && editorOpen;
18242
+ const showPreviewPanel = previewOnly || previewOpen;
18243
+ return /* @__PURE__ */ jsx17(
18244
+ "div",
18245
+ {
18246
+ ref: widgetRef,
18247
+ className: ["butex-document2-widget", className].filter(Boolean).join(" "),
18248
+ dir: uiLocaleDirection(uiLocale),
18249
+ lang: uiLocale,
18250
+ children: /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__shell", children: [
18251
+ !previewOnly ? /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__toolbar", children: [
18422
18252
  /* @__PURE__ */ jsx17(
18423
- "textarea",
18253
+ DocumentInsertToolbar,
18424
18254
  {
18425
- value: debugImportText,
18426
- "aria-label": "Import Document2 JSON",
18427
- spellCheck: false,
18428
- onChange: (event) => {
18429
- setDebugImportText(event.currentTarget.value);
18430
- setDebugImportError("");
18255
+ canUndo,
18256
+ canRedo,
18257
+ editableEquations,
18258
+ uiLocale,
18259
+ digitForm,
18260
+ selectionCount,
18261
+ canMoveSelectionUp,
18262
+ canMoveSelectionDown,
18263
+ canFormatText,
18264
+ activeTextStyles,
18265
+ onUndo: undoDocument,
18266
+ onRedo: redoDocument,
18267
+ onToggleTextStyle: toggleInlineTextStyle,
18268
+ onMoveSelectionUp: () => moveSelectedBlocks(-1),
18269
+ onMoveSelectionDown: () => moveSelectedBlocks(1),
18270
+ onDeleteSelection: deleteSelectedBlocks,
18271
+ onAddSection: () => {
18272
+ clearBlockSelection();
18273
+ applyDocument(addDocument2TextBlock(documentRef.current, "\\section", afterBlockId()), "immediate");
18274
+ },
18275
+ onAddSubsection: () => {
18276
+ clearBlockSelection();
18277
+ applyDocument(addDocument2TextBlock(documentRef.current, "\\subsection", afterBlockId()), "immediate");
18278
+ },
18279
+ onAddSubsubsection: () => {
18280
+ clearBlockSelection();
18281
+ applyDocument(addDocument2TextBlock(documentRef.current, "\\subsubsection", afterBlockId()), "immediate");
18282
+ },
18283
+ onAddParagraph: () => {
18284
+ clearBlockSelection();
18285
+ applyDocument(addDocument2TextBlock(documentRef.current, "\\paragraph", afterBlockId()), "immediate");
18286
+ },
18287
+ onAddInlineEquation: () => openNewEquation("inline"),
18288
+ onAddDisplayEquation: () => openNewEquation("display"),
18289
+ onAddTable: (rowCount, colCount) => {
18290
+ clearBlockSelection();
18291
+ applyDocument(addDocument2TableBlock(documentRef.current, "l".repeat(colCount), rowCount, colCount, afterBlockId()), "immediate");
18292
+ },
18293
+ onAddList: () => {
18294
+ clearBlockSelection();
18295
+ applyDocument(addDocument2ListBlock(documentRef.current, false, afterBlockId()), "immediate");
18296
+ },
18297
+ onAddEnumerate: () => {
18298
+ clearBlockSelection();
18299
+ applyDocument(addDocument2ListBlock(documentRef.current, true, afterBlockId()), "immediate");
18300
+ },
18301
+ onAddFigure: () => insertImageBlock(""),
18302
+ onInsertCitation: openCitePickerForInsert,
18303
+ onInsertInternalRef: openRefPickerForInsert,
18304
+ onInsertBibliography: () => {
18305
+ clearBlockSelection();
18306
+ applyDocument(ensureDocument2BibliographyBlock(documentRef.current, afterBlockId()), "immediate");
18307
+ },
18308
+ onManageReferences: () => setReferencesOpen(true),
18309
+ onManageLabels: () => setLabelsOpen(true),
18310
+ onOpenArticleMeta: () => focusArticleMetaPanel(articleMetaPanelRef.current),
18311
+ onDigitFormChange: (next) => {
18312
+ setDigitFormState(next);
18313
+ onDigitFormChange?.(next);
18431
18314
  }
18432
18315
  }
18433
18316
  ),
18317
+ /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.panels, children: [
18318
+ /* @__PURE__ */ jsx17("button", { type: "button", "aria-pressed": editorOpen, onClick: toggleEditorPanel, children: editorOpen ? messages.hideEditor : messages.editor }),
18319
+ /* @__PURE__ */ jsx17("button", { type: "button", "aria-pressed": previewOpen, onClick: togglePreviewPanel, children: previewOpen ? messages.hidePreview : messages.preview })
18320
+ ] }),
18321
+ /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__toolbar-group", role: "group", "aria-label": messages.collapseBlocks, children: [
18322
+ /* @__PURE__ */ jsx17("button", { type: "button", onClick: collapseAllBlocks, children: messages.collapseAll }),
18323
+ /* @__PURE__ */ jsx17("button", { type: "button", onClick: openAllBlocks, children: messages.openAll })
18324
+ ] })
18325
+ ] }) : null,
18326
+ error ? /* @__PURE__ */ jsx17("p", { className: "butex-document2-widget__error", children: error }) : null,
18327
+ /* @__PURE__ */ jsxs15(
18328
+ "div",
18329
+ {
18330
+ className: `butex-document2-widget__layout butex-document2-widget__layout--editor-${showEditorPanel ? "open" : "closed"} butex-document2-widget__layout--preview-${showPreviewPanel ? "open" : "closed"}`,
18331
+ children: [
18332
+ !previewOnly ? /* @__PURE__ */ jsx17(
18333
+ "section",
18334
+ {
18335
+ className: "butex-document2-widget__panel butex-document2-widget__editor-panel",
18336
+ "aria-label": messages.documentEditor,
18337
+ "aria-hidden": !showEditorPanel,
18338
+ children: /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__blocks", children: [
18339
+ /* @__PURE__ */ jsx17(
18340
+ ArticleMetaPanel,
18341
+ {
18342
+ meta: documentNode.meta ?? emptyDocument2Meta(),
18343
+ uiLocale,
18344
+ digitForm,
18345
+ panelRef: articleMetaPanelRef,
18346
+ onChange: (patch) => {
18347
+ clearBlockSelection();
18348
+ applyDocument(updateDocument2Meta(documentRef.current, patch), "text");
18349
+ }
18350
+ }
18351
+ ),
18352
+ documentNode.blocks.map((block, blockIndex) => /* @__PURE__ */ jsx17(
18353
+ BlockEditor,
18354
+ {
18355
+ block,
18356
+ references: documentNode.references,
18357
+ documentNode,
18358
+ documentDirection,
18359
+ digitForm,
18360
+ mathOutput,
18361
+ equationSide,
18362
+ editableEquations,
18363
+ editableCitations: !previewOnly,
18364
+ uiLocale,
18365
+ isCollapsed: collapsedBlockIds.has(block.id),
18366
+ selected: Boolean(blockSelection && blockIndex >= blockSelection.from && blockIndex <= blockSelection.to),
18367
+ onToggleSelect: toggleSelectBlock,
18368
+ onTextChange: (fieldId, tokenId, text) => {
18369
+ clearBlockSelection();
18370
+ applyDocument(updateTextToken(documentRef.current, fieldId, tokenId, text), "text");
18371
+ },
18372
+ onOpenMath: openMath,
18373
+ onDeleteMath: editableEquations ? deleteMathToken : void 0,
18374
+ onOpenCite: openCite,
18375
+ onDeleteCite: deleteCiteToken,
18376
+ onOpenRef: openRef,
18377
+ onDeleteRef: deleteRefToken,
18378
+ onToggleCollapse: toggleBlockCollapse,
18379
+ onBlockFocus: rememberBlockFocus,
18380
+ onFieldFocus: rememberFieldFocus,
18381
+ onMathFocus: rememberMathFocus,
18382
+ onFieldBlur,
18383
+ onImageSrcChange: (blockId, value) => {
18384
+ clearBlockSelection();
18385
+ applyDocument(updateDocument2ImageValue(documentRef.current, blockId, value), "text");
18386
+ },
18387
+ onFloatMetaChange: (blockId, kind, patch) => {
18388
+ clearBlockSelection();
18389
+ applyDocument(
18390
+ kind === "image" ? updateDocument2ImageMeta(documentRef.current, blockId, patch) : updateDocument2TableMeta(documentRef.current, blockId, patch),
18391
+ "text"
18392
+ );
18393
+ },
18394
+ onParagraphCenteredChange: (blockId, centered) => {
18395
+ clearBlockSelection();
18396
+ applyDocument(updateDocument2TextBlockCentered(documentRef.current, blockId, centered), "text");
18397
+ },
18398
+ onAddListItem: (listBlockId) => {
18399
+ clearBlockSelection();
18400
+ applyDocument(addDocument2ListItem(documentRef.current, listBlockId), "immediate");
18401
+ },
18402
+ onRemoveListItem: (listBlockId, itemId) => {
18403
+ clearBlockSelection();
18404
+ applyDocument(removeDocument2ListItem(documentRef.current, listBlockId, itemId), "immediate");
18405
+ },
18406
+ onManageReferences: () => setReferencesOpen(true)
18407
+ },
18408
+ block.id
18409
+ ))
18410
+ ] })
18411
+ }
18412
+ ) : null,
18413
+ /* @__PURE__ */ jsx17(
18414
+ "section",
18415
+ {
18416
+ className: "butex-document2-widget__panel butex-document2-widget__preview-panel",
18417
+ "aria-label": messages.documentPreview,
18418
+ "aria-hidden": !showPreviewPanel,
18419
+ children: /* @__PURE__ */ jsx17(
18420
+ DocumentPreview,
18421
+ {
18422
+ blocks: preview.blocks,
18423
+ output: mathOutput,
18424
+ documentDirection,
18425
+ uiLocale,
18426
+ digitForm,
18427
+ resolveImageUrl
18428
+ }
18429
+ )
18430
+ }
18431
+ )
18432
+ ]
18433
+ }
18434
+ ),
18435
+ debugEnabled ? /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__dev", children: [
18436
+ debugEnabled && documentNode.diagnostics.length > 0 ? /* @__PURE__ */ jsxs15(Fragment4, { children: [
18437
+ /* @__PURE__ */ jsx17("strong", { children: messages.importWarnings }),
18438
+ documentNode.diagnostics.map((diagnostic) => /* @__PURE__ */ jsx17("p", { className: "butex-document2-widget__dev-diagnostic", children: formatDocument2Diagnostic(diagnostic, messages) }, `${diagnostic.path}-${diagnostic.message}`))
18439
+ ] }) : null,
18434
18440
  /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__dev-actions", children: [
18435
- /* @__PURE__ */ jsx17("button", { type: "button", onClick: applyDebugJsonImport, children: "Apply" }),
18441
+ /* @__PURE__ */ jsx17("button", { type: "button", onClick: () => void copyDebugText(JSON.stringify(documentJson, null, 2)), children: "Copy JSON" }),
18442
+ /* @__PURE__ */ jsx17("button", { type: "button", onClick: () => void copyDebugText(latex), children: "Copy TeX" }),
18443
+ /* @__PURE__ */ jsx17("button", { type: "button", "aria-expanded": debugImportOpen, onClick: openDebugJsonImport, children: "Import JSON" })
18444
+ ] }),
18445
+ debugImportOpen ? /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__dev-import", children: [
18436
18446
  /* @__PURE__ */ jsx17(
18437
- "button",
18447
+ "textarea",
18438
18448
  {
18439
- type: "button",
18440
- onClick: () => {
18441
- setDebugImportOpen(false);
18449
+ value: debugImportText,
18450
+ "aria-label": "Import Document2 JSON",
18451
+ spellCheck: false,
18452
+ onChange: (event) => {
18453
+ setDebugImportText(event.currentTarget.value);
18442
18454
  setDebugImportError("");
18443
- },
18444
- children: "Cancel"
18455
+ }
18445
18456
  }
18446
- )
18447
- ] }),
18448
- debugImportError ? /* @__PURE__ */ jsx17("p", { className: "butex-document2-widget__dev-error", children: debugImportError }) : null
18457
+ ),
18458
+ /* @__PURE__ */ jsxs15("div", { className: "butex-document2-widget__dev-actions", children: [
18459
+ /* @__PURE__ */ jsx17("button", { type: "button", onClick: applyDebugJsonImport, children: "Apply" }),
18460
+ /* @__PURE__ */ jsx17(
18461
+ "button",
18462
+ {
18463
+ type: "button",
18464
+ onClick: () => {
18465
+ setDebugImportOpen(false);
18466
+ setDebugImportError("");
18467
+ },
18468
+ children: "Cancel"
18469
+ }
18470
+ )
18471
+ ] }),
18472
+ debugImportError ? /* @__PURE__ */ jsx17("p", { className: "butex-document2-widget__dev-error", children: debugImportError }) : null
18473
+ ] }) : null,
18474
+ /* @__PURE__ */ jsx17("strong", { children: "LaTeX" }),
18475
+ /* @__PURE__ */ jsx17("pre", { children: latex }),
18476
+ /* @__PURE__ */ jsx17("strong", { children: "JSON" }),
18477
+ /* @__PURE__ */ jsx17("pre", { children: JSON.stringify(documentJson, null, 2) }),
18478
+ /* @__PURE__ */ jsx17("strong", { children: "AST" }),
18479
+ /* @__PURE__ */ jsx17("pre", { children: JSON.stringify(documentNode, null, 2) })
18449
18480
  ] }) : null,
18450
- /* @__PURE__ */ jsx17("strong", { children: "LaTeX" }),
18451
- /* @__PURE__ */ jsx17("pre", { children: latex }),
18452
- /* @__PURE__ */ jsx17("strong", { children: "JSON" }),
18453
- /* @__PURE__ */ jsx17("pre", { children: JSON.stringify(documentJson, null, 2) }),
18454
- /* @__PURE__ */ jsx17("strong", { children: "AST" }),
18455
- /* @__PURE__ */ jsx17("pre", { children: JSON.stringify(documentNode, null, 2) })
18456
- ] }) : null,
18457
- !previewOnly && selectedMath ? /* @__PURE__ */ jsx17(
18458
- EquationDrawer,
18459
- {
18460
- debug: debugEnabled,
18461
- session: selectedMath.session,
18462
- reason: selectedMath.reason,
18463
- mathMode: selectedMath.mathMode,
18464
- canDelete: Boolean(selectedMath.tokenId),
18465
- equationSide,
18466
- uiLocale,
18467
- labelEnabled: selectedMath.labelEnabled,
18468
- label: selectedMath.label,
18469
- labels: documentLabels,
18470
- references: documentNode.references,
18471
- ownerId: selectedMath.tokenId ?? void 0,
18472
- onLabelEnabledChange: (enabled) => setSelectedMath((current) => current ? { ...current, labelEnabled: enabled } : current),
18473
- onLabelChange: (nextLabel) => setSelectedMath((current) => current ? { ...current, label: nextLabel } : current),
18474
- onMathModeChange: (mode) => setSelectedMath((current) => current ? { ...current, mathMode: mode } : current),
18475
- onClose: () => setSelectedMath(null),
18476
- onSave: saveEquation,
18477
- onDelete: deleteSelectedEquation
18478
- }
18479
- ) : null,
18480
- !previewOnly ? /* @__PURE__ */ jsx17(
18481
- CitePickerPopover,
18482
- {
18483
- open: citePicker !== null,
18484
- references: documentNode.references,
18485
- initialKeys: citePicker?.keys ?? [],
18486
- uiLocale,
18487
- digitForm,
18488
- onClose: () => setCitePicker(null),
18489
- onConfirm: confirmCiteKeys,
18490
- onManageReferences: () => {
18491
- setCitePicker(null);
18492
- setReferencesOpen(true);
18481
+ !previewOnly && selectedMath ? /* @__PURE__ */ jsx17(
18482
+ EquationDrawer,
18483
+ {
18484
+ debug: debugEnabled,
18485
+ session: selectedMath.session,
18486
+ reason: selectedMath.reason,
18487
+ mathMode: selectedMath.mathMode,
18488
+ canDelete: Boolean(selectedMath.tokenId),
18489
+ equationSide,
18490
+ uiLocale,
18491
+ labelEnabled: selectedMath.labelEnabled,
18492
+ label: selectedMath.label,
18493
+ labels: documentLabels,
18494
+ references: documentNode.references,
18495
+ ownerId: selectedMath.tokenId ?? void 0,
18496
+ onLabelEnabledChange: (enabled) => setSelectedMath((current) => current ? { ...current, labelEnabled: enabled } : current),
18497
+ onLabelChange: (nextLabel) => setSelectedMath((current) => current ? { ...current, label: nextLabel } : current),
18498
+ onMathModeChange: (mode) => setSelectedMath((current) => current ? { ...current, mathMode: mode } : current),
18499
+ onClose: () => setSelectedMath(null),
18500
+ onSave: saveEquation,
18501
+ onDelete: deleteSelectedEquation
18493
18502
  }
18494
- }
18495
- ) : null,
18496
- !previewOnly ? /* @__PURE__ */ jsx17(
18497
- RefPickerPopover,
18498
- {
18499
- open: refPicker !== null,
18500
- labels: documentLabels,
18501
- initialKeys: refPicker?.keys ?? [],
18502
- initialRefCommand: refPicker?.refCommand ?? "ref",
18503
- uiLocale,
18504
- digitForm,
18505
- onClose: () => setRefPicker(null),
18506
- onConfirm: confirmRefKeys,
18507
- onManageLabels: () => {
18508
- setRefPicker(null);
18509
- setLabelsOpen(true);
18503
+ ) : null,
18504
+ !previewOnly ? /* @__PURE__ */ jsx17(
18505
+ CitePickerPopover,
18506
+ {
18507
+ open: citePicker !== null,
18508
+ references: documentNode.references,
18509
+ initialKeys: citePicker?.keys ?? [],
18510
+ uiLocale,
18511
+ digitForm,
18512
+ onClose: () => setCitePicker(null),
18513
+ onConfirm: confirmCiteKeys,
18514
+ onManageReferences: () => {
18515
+ setCitePicker(null);
18516
+ setReferencesOpen(true);
18517
+ }
18510
18518
  }
18511
- }
18512
- ) : null,
18513
- !previewOnly ? /* @__PURE__ */ jsx17(
18514
- ReferencesPanel,
18515
- {
18516
- open: referencesOpen,
18517
- references: documentNode.references,
18518
- labels: documentLabels,
18519
- uiLocale,
18520
- digitForm,
18521
- onClose: () => setReferencesOpen(false),
18522
- onAdd: (partial) => applyDocument(addDocument2Reference(documentRef.current, partial), "immediate"),
18523
- onUpdate: (referenceId, patch) => applyDocument(updateDocument2Reference(documentRef.current, referenceId, patch), "immediate"),
18524
- onRemove: (referenceId) => applyDocument(removeDocument2Reference(documentRef.current, referenceId), "immediate"),
18525
- onMove: (referenceId, direction) => applyDocument(moveDocument2Reference(documentRef.current, referenceId, direction), "immediate")
18526
- }
18527
- ) : null,
18528
- !previewOnly ? /* @__PURE__ */ jsx17(
18529
- LabelsPanel,
18530
- {
18531
- open: labelsOpen,
18532
- labels: documentLabels,
18533
- references: documentNode.references,
18534
- uiLocale,
18535
- digitForm,
18536
- onClose: () => setLabelsOpen(false),
18537
- onUpdateFloat: (ownerId, kind, patch) => applyDocument(
18538
- kind === "fig" ? updateDocument2ImageMeta(documentRef.current, ownerId, patch) : updateDocument2TableMeta(documentRef.current, ownerId, patch),
18539
- "text"
18540
- ),
18541
- onUpdateEquationLabel: (tokenId, patch) => applyDocument(updateMathTokenLabel(documentRef.current, tokenId, patch), "text")
18542
- }
18543
- ) : null
18544
- ] })
18545
- }
18546
- );
18547
- }
18519
+ ) : null,
18520
+ !previewOnly ? /* @__PURE__ */ jsx17(
18521
+ RefPickerPopover,
18522
+ {
18523
+ open: refPicker !== null,
18524
+ labels: documentLabels,
18525
+ initialKeys: refPicker?.keys ?? [],
18526
+ initialRefCommand: refPicker?.refCommand ?? "ref",
18527
+ uiLocale,
18528
+ digitForm,
18529
+ onClose: () => setRefPicker(null),
18530
+ onConfirm: confirmRefKeys,
18531
+ onManageLabels: () => {
18532
+ setRefPicker(null);
18533
+ setLabelsOpen(true);
18534
+ }
18535
+ }
18536
+ ) : null,
18537
+ !previewOnly ? /* @__PURE__ */ jsx17(
18538
+ ReferencesPanel,
18539
+ {
18540
+ open: referencesOpen,
18541
+ references: documentNode.references,
18542
+ labels: documentLabels,
18543
+ uiLocale,
18544
+ digitForm,
18545
+ onClose: () => setReferencesOpen(false),
18546
+ onAdd: (partial) => applyDocument(addDocument2Reference(documentRef.current, partial), "immediate"),
18547
+ onUpdate: (referenceId, patch) => applyDocument(updateDocument2Reference(documentRef.current, referenceId, patch), "immediate"),
18548
+ onRemove: (referenceId) => applyDocument(removeDocument2Reference(documentRef.current, referenceId), "immediate"),
18549
+ onMove: (referenceId, direction) => applyDocument(moveDocument2Reference(documentRef.current, referenceId, direction), "immediate")
18550
+ }
18551
+ ) : null,
18552
+ !previewOnly ? /* @__PURE__ */ jsx17(
18553
+ LabelsPanel,
18554
+ {
18555
+ open: labelsOpen,
18556
+ labels: documentLabels,
18557
+ references: documentNode.references,
18558
+ uiLocale,
18559
+ digitForm,
18560
+ onClose: () => setLabelsOpen(false),
18561
+ onUpdateFloat: (ownerId, kind, patch) => applyDocument(
18562
+ kind === "fig" ? updateDocument2ImageMeta(documentRef.current, ownerId, patch) : updateDocument2TableMeta(documentRef.current, ownerId, patch),
18563
+ "text"
18564
+ ),
18565
+ onUpdateEquationLabel: (tokenId, patch) => applyDocument(updateMathTokenLabel(documentRef.current, tokenId, patch), "text")
18566
+ }
18567
+ ) : null
18568
+ ] })
18569
+ }
18570
+ );
18571
+ }
18572
+ );
18573
+ ButexDocumentEditor2.displayName = "ButexDocumentEditor2";
18548
18574
  export {
18549
18575
  ButexDocumentEditor2,
18550
18576
  DOCUMENT2_WIDGET_CSS,