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