@yurikilian/lex4 0.2.2 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -3
- package/dist/components/DocumentView.d.ts.map +1 -1
- package/dist/components/PageView.d.ts.map +1 -1
- package/dist/context/document-provider.d.ts.map +1 -1
- package/dist/engine/overflow.d.ts +2 -0
- package/dist/engine/overflow.d.ts.map +1 -1
- package/dist/hooks/use-pagination.d.ts.map +1 -1
- package/dist/i18n/defaults.d.ts.map +1 -1
- package/dist/i18n/pt-BR.d.ts.map +1 -1
- package/dist/i18n/types.d.ts +36 -0
- package/dist/i18n/types.d.ts.map +1 -1
- package/dist/lex4-editor.cjs +670 -271
- package/dist/lex4-editor.cjs.map +1 -1
- package/dist/lex4-editor.js +673 -274
- package/dist/lex4-editor.js.map +1 -1
- package/dist/lexical/plugins/history-capture-plugin.d.ts.map +1 -1
- package/dist/lexical/plugins/overflow-plugin.d.ts.map +1 -1
- package/dist/lexical/utils/mid-block-split.d.ts +34 -0
- package/dist/lexical/utils/mid-block-split.d.ts.map +1 -0
- package/dist/style.css +212 -816
- package/dist/utils/editor-state-utils.d.ts +10 -0
- package/dist/utils/editor-state-utils.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/lex4-editor.js
CHANGED
|
@@ -2,10 +2,10 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
5
|
-
import React, { createContext, useContext, useReducer, useState, useRef,
|
|
6
|
-
import { $getRoot, $createRangeSelectionFromDom, $getSelection, $isRangeSelection, $isTextNode, FORMAT_ELEMENT_COMMAND, FORMAT_TEXT_COMMAND, OUTDENT_CONTENT_COMMAND, INDENT_CONTENT_COMMAND, $selectAll, KEY_TAB_COMMAND, COMMAND_PRIORITY_LOW, $isElementNode, $isParagraphNode, $setSelection, FOCUS_COMMAND, CONTROLLED_TEXT_INSERTION_COMMAND, KEY_DOWN_COMMAND, PASTE_COMMAND, KEY_ENTER_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_CRITICAL, $applyNodeReplacement, DecoratorNode, createCommand, $insertNodes, COMMAND_PRIORITY_EDITOR } from "lexical";
|
|
5
|
+
import React, { createContext, useContext, useMemo, useReducer, useState, useRef, useCallback, useEffect, forwardRef, createElement, useImperativeHandle } from "react";
|
|
6
|
+
import { $getRoot, $createRangeSelectionFromDom, $getSelection, $isRangeSelection, $isTextNode, FORMAT_ELEMENT_COMMAND, FORMAT_TEXT_COMMAND, OUTDENT_CONTENT_COMMAND, INDENT_CONTENT_COMMAND, $selectAll, KEY_TAB_COMMAND, COMMAND_PRIORITY_LOW, $isElementNode, $isParagraphNode, $setSelection, FOCUS_COMMAND, $splitNode, $getNearestNodeFromDOMNode, CONTROLLED_TEXT_INSERTION_COMMAND, KEY_DOWN_COMMAND, PASTE_COMMAND, KEY_ENTER_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, COMMAND_PRIORITY_HIGH, COMMAND_PRIORITY_CRITICAL, $applyNodeReplacement, DecoratorNode, createCommand, $insertNodes, COMMAND_PRIORITY_EDITOR } from "lexical";
|
|
7
7
|
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
|
|
8
|
-
import { INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, ListNode, ListItemNode } from "@lexical/list";
|
|
8
|
+
import { INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND, ListNode, ListItemNode, $isListNode } from "@lexical/list";
|
|
9
9
|
import { LexicalComposer } from "@lexical/react/LexicalComposer";
|
|
10
10
|
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
|
|
11
11
|
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
|
|
@@ -452,6 +452,258 @@ function jumpToHistoryEntry(history, entryIndex) {
|
|
|
452
452
|
caretSelection: ((_b = nextHistory.entries[nextHistory.cursor - 1]) == null ? void 0 : _b.caretSelection) ?? null
|
|
453
453
|
};
|
|
454
454
|
}
|
|
455
|
+
const DEFAULT_TRANSLATIONS = {
|
|
456
|
+
toolbar: {
|
|
457
|
+
undo: "Undo",
|
|
458
|
+
redo: "Redo",
|
|
459
|
+
bold: "Bold (Ctrl+B)",
|
|
460
|
+
italic: "Italic (Ctrl+I)",
|
|
461
|
+
underline: "Underline (Ctrl+U)",
|
|
462
|
+
strikethrough: "Strikethrough",
|
|
463
|
+
alignLeft: "Align Left",
|
|
464
|
+
alignCenter: "Align Center",
|
|
465
|
+
alignRight: "Align Right",
|
|
466
|
+
justify: "Justify",
|
|
467
|
+
numberedList: "Numbered List",
|
|
468
|
+
bulletList: "Bullet List",
|
|
469
|
+
indent: "Indent",
|
|
470
|
+
outdent: "Outdent",
|
|
471
|
+
openHistory: "Open History",
|
|
472
|
+
closeHistory: "Close History"
|
|
473
|
+
},
|
|
474
|
+
history: {
|
|
475
|
+
title: "History",
|
|
476
|
+
subtitle: "Word-style session history (last 100 actions)",
|
|
477
|
+
empty: "No history yet.",
|
|
478
|
+
clearHistory: "Clear History",
|
|
479
|
+
actions: {
|
|
480
|
+
enabledHeadersFooters: "Enabled headers and footers",
|
|
481
|
+
disabledHeadersFooters: "Disabled headers and footers",
|
|
482
|
+
copiedHeaderToAll: "Copied header to all pages",
|
|
483
|
+
copiedFooterToAll: "Copied footer to all pages",
|
|
484
|
+
clearedHeader: "Cleared header",
|
|
485
|
+
clearedFooter: "Cleared footer",
|
|
486
|
+
clearedAllHeaders: "Cleared all headers",
|
|
487
|
+
clearedAllFooters: "Cleared all footers",
|
|
488
|
+
pageCounterSet: "Page counter set to {{value}}",
|
|
489
|
+
boldApplied: "Bold applied",
|
|
490
|
+
italicApplied: "Italic applied",
|
|
491
|
+
underlineApplied: "Underline applied",
|
|
492
|
+
strikethroughApplied: "Strikethrough applied",
|
|
493
|
+
alignedLeft: "Aligned left",
|
|
494
|
+
alignedCenter: "Aligned center",
|
|
495
|
+
alignedRight: "Aligned right",
|
|
496
|
+
justifiedText: "Justified text",
|
|
497
|
+
insertedNumberedList: "Inserted numbered list",
|
|
498
|
+
insertedBulletList: "Inserted bullet list",
|
|
499
|
+
indentedContent: "Indented content",
|
|
500
|
+
outdentedContent: "Outdented content",
|
|
501
|
+
fontChanged: "Font changed to {{value}}",
|
|
502
|
+
fontSizeChanged: "Font size changed to {{value}}pt"
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
variables: {
|
|
506
|
+
title: "Variables",
|
|
507
|
+
available: "{{count}} available",
|
|
508
|
+
refreshVariables: "Refresh variables",
|
|
509
|
+
searchPlaceholder: "Search variables...",
|
|
510
|
+
noVariablesFound: "No variables found",
|
|
511
|
+
insertVariable: "Insert variable {{key}}",
|
|
512
|
+
openPanel: "Open Variables",
|
|
513
|
+
closePanel: "Close Variables"
|
|
514
|
+
},
|
|
515
|
+
header: {
|
|
516
|
+
placeholder: "Header"
|
|
517
|
+
},
|
|
518
|
+
footer: {
|
|
519
|
+
placeholder: "Footer"
|
|
520
|
+
},
|
|
521
|
+
body: {
|
|
522
|
+
placeholder: "Start typing..."
|
|
523
|
+
},
|
|
524
|
+
pageCounter: {
|
|
525
|
+
format: "Page {{current}} of {{total}}"
|
|
526
|
+
},
|
|
527
|
+
regions: {
|
|
528
|
+
body: "body",
|
|
529
|
+
header: "header",
|
|
530
|
+
footer: "footer",
|
|
531
|
+
document: "document",
|
|
532
|
+
toolbar: "toolbar",
|
|
533
|
+
overflow: "overflow",
|
|
534
|
+
history: "history",
|
|
535
|
+
page: "Page {{page}}"
|
|
536
|
+
},
|
|
537
|
+
headerFooter: {
|
|
538
|
+
label: "Headers & Footers"
|
|
539
|
+
},
|
|
540
|
+
sidebar: {
|
|
541
|
+
close: "Close sidebar"
|
|
542
|
+
},
|
|
543
|
+
historyLabels: {
|
|
544
|
+
typedText: "Typed text",
|
|
545
|
+
pastedContent: "Pasted content",
|
|
546
|
+
insertedLineBreak: "Inserted line break",
|
|
547
|
+
deletedBackward: "Deleted backward",
|
|
548
|
+
deletedForward: "Deleted forward",
|
|
549
|
+
formattedText: "Formatted text",
|
|
550
|
+
formattedParagraph: "Formatted paragraph",
|
|
551
|
+
editedBody: "Edited body",
|
|
552
|
+
editedHeader: "Edited header",
|
|
553
|
+
editedFooter: "Edited footer",
|
|
554
|
+
clearedDocumentBody: "Cleared document body",
|
|
555
|
+
resizedHeader: "Resized header",
|
|
556
|
+
resizedFooter: "Resized footer",
|
|
557
|
+
addedPage: "Added page",
|
|
558
|
+
removedPage: "Removed page",
|
|
559
|
+
documentReflow: "Document reflow",
|
|
560
|
+
updatedDocument: "Updated document"
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
const PT_BR_TRANSLATIONS = {
|
|
564
|
+
toolbar: {
|
|
565
|
+
undo: "Desfazer",
|
|
566
|
+
redo: "Refazer",
|
|
567
|
+
bold: "Negrito (Ctrl+B)",
|
|
568
|
+
italic: "Itálico (Ctrl+I)",
|
|
569
|
+
underline: "Sublinhado (Ctrl+U)",
|
|
570
|
+
strikethrough: "Tachado",
|
|
571
|
+
alignLeft: "Alinhar à Esquerda",
|
|
572
|
+
alignCenter: "Centralizar",
|
|
573
|
+
alignRight: "Alinhar à Direita",
|
|
574
|
+
justify: "Justificar",
|
|
575
|
+
numberedList: "Lista Numerada",
|
|
576
|
+
bulletList: "Lista com Marcadores",
|
|
577
|
+
indent: "Aumentar Recuo",
|
|
578
|
+
outdent: "Diminuir Recuo",
|
|
579
|
+
openHistory: "Abrir Histórico",
|
|
580
|
+
closeHistory: "Fechar Histórico"
|
|
581
|
+
},
|
|
582
|
+
history: {
|
|
583
|
+
title: "Histórico",
|
|
584
|
+
subtitle: "Histórico de sessão (últimas 100 ações)",
|
|
585
|
+
empty: "Nenhum histórico ainda.",
|
|
586
|
+
clearHistory: "Limpar Histórico",
|
|
587
|
+
actions: {
|
|
588
|
+
enabledHeadersFooters: "Cabeçalhos e rodapés ativados",
|
|
589
|
+
disabledHeadersFooters: "Cabeçalhos e rodapés desativados",
|
|
590
|
+
copiedHeaderToAll: "Cabeçalho copiado para todas as páginas",
|
|
591
|
+
copiedFooterToAll: "Rodapé copiado para todas as páginas",
|
|
592
|
+
clearedHeader: "Cabeçalho limpo",
|
|
593
|
+
clearedFooter: "Rodapé limpo",
|
|
594
|
+
clearedAllHeaders: "Todos os cabeçalhos limpos",
|
|
595
|
+
clearedAllFooters: "Todos os rodapés limpos",
|
|
596
|
+
pageCounterSet: "Contador de páginas definido como {{value}}",
|
|
597
|
+
boldApplied: "Negrito aplicado",
|
|
598
|
+
italicApplied: "Itálico aplicado",
|
|
599
|
+
underlineApplied: "Sublinhado aplicado",
|
|
600
|
+
strikethroughApplied: "Tachado aplicado",
|
|
601
|
+
alignedLeft: "Alinhado à esquerda",
|
|
602
|
+
alignedCenter: "Centralizado",
|
|
603
|
+
alignedRight: "Alinhado à direita",
|
|
604
|
+
justifiedText: "Texto justificado",
|
|
605
|
+
insertedNumberedList: "Lista numerada inserida",
|
|
606
|
+
insertedBulletList: "Lista com marcadores inserida",
|
|
607
|
+
indentedContent: "Conteúdo recuado",
|
|
608
|
+
outdentedContent: "Recuo reduzido",
|
|
609
|
+
fontChanged: "Fonte alterada para {{value}}",
|
|
610
|
+
fontSizeChanged: "Tamanho da fonte alterado para {{value}}pt"
|
|
611
|
+
}
|
|
612
|
+
},
|
|
613
|
+
variables: {
|
|
614
|
+
title: "Variáveis",
|
|
615
|
+
available: "{{count}} disponíveis",
|
|
616
|
+
refreshVariables: "Atualizar variáveis",
|
|
617
|
+
searchPlaceholder: "Buscar variáveis...",
|
|
618
|
+
noVariablesFound: "Nenhuma variável encontrada",
|
|
619
|
+
insertVariable: "Inserir variável {{key}}",
|
|
620
|
+
openPanel: "Abrir Variáveis",
|
|
621
|
+
closePanel: "Fechar Variáveis"
|
|
622
|
+
},
|
|
623
|
+
header: {
|
|
624
|
+
placeholder: "Cabeçalho"
|
|
625
|
+
},
|
|
626
|
+
footer: {
|
|
627
|
+
placeholder: "Rodapé"
|
|
628
|
+
},
|
|
629
|
+
body: {
|
|
630
|
+
placeholder: "Comece a digitar..."
|
|
631
|
+
},
|
|
632
|
+
pageCounter: {
|
|
633
|
+
format: "Página {{current}} de {{total}}"
|
|
634
|
+
},
|
|
635
|
+
regions: {
|
|
636
|
+
body: "corpo",
|
|
637
|
+
header: "cabeçalho",
|
|
638
|
+
footer: "rodapé",
|
|
639
|
+
document: "documento",
|
|
640
|
+
toolbar: "barra de ferramentas",
|
|
641
|
+
overflow: "estouro",
|
|
642
|
+
history: "histórico",
|
|
643
|
+
page: "Página {{page}}"
|
|
644
|
+
},
|
|
645
|
+
headerFooter: {
|
|
646
|
+
label: "Cabeçalhos e Rodapés"
|
|
647
|
+
},
|
|
648
|
+
sidebar: {
|
|
649
|
+
close: "Fechar barra lateral"
|
|
650
|
+
},
|
|
651
|
+
historyLabels: {
|
|
652
|
+
typedText: "Texto digitado",
|
|
653
|
+
pastedContent: "Conteúdo colado",
|
|
654
|
+
insertedLineBreak: "Quebra de linha inserida",
|
|
655
|
+
deletedBackward: "Exclusão para trás",
|
|
656
|
+
deletedForward: "Exclusão para frente",
|
|
657
|
+
formattedText: "Texto formatado",
|
|
658
|
+
formattedParagraph: "Parágrafo formatado",
|
|
659
|
+
editedBody: "Corpo editado",
|
|
660
|
+
editedHeader: "Cabeçalho editado",
|
|
661
|
+
editedFooter: "Rodapé editado",
|
|
662
|
+
clearedDocumentBody: "Corpo do documento limpo",
|
|
663
|
+
resizedHeader: "Cabeçalho redimensionado",
|
|
664
|
+
resizedFooter: "Rodapé redimensionado",
|
|
665
|
+
addedPage: "Página adicionada",
|
|
666
|
+
removedPage: "Página removida",
|
|
667
|
+
documentReflow: "Redistribuição do documento",
|
|
668
|
+
updatedDocument: "Documento atualizado"
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
function deepMerge(target, source) {
|
|
672
|
+
if (typeof target !== "object" || target === null) {
|
|
673
|
+
return source ?? target;
|
|
674
|
+
}
|
|
675
|
+
const result = { ...target };
|
|
676
|
+
for (const key of Object.keys(source)) {
|
|
677
|
+
const sourceVal = source[key];
|
|
678
|
+
const targetVal = target[key];
|
|
679
|
+
if (sourceVal !== void 0 && typeof sourceVal === "object" && sourceVal !== null && !Array.isArray(sourceVal) && typeof targetVal === "object" && targetVal !== null) {
|
|
680
|
+
result[key] = deepMerge(targetVal, sourceVal);
|
|
681
|
+
} else if (sourceVal !== void 0) {
|
|
682
|
+
result[key] = sourceVal;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
return result;
|
|
686
|
+
}
|
|
687
|
+
const TranslationsContext = createContext(DEFAULT_TRANSLATIONS);
|
|
688
|
+
function useTranslations() {
|
|
689
|
+
return useContext(TranslationsContext);
|
|
690
|
+
}
|
|
691
|
+
function interpolate(template, params) {
|
|
692
|
+
return template.replace(
|
|
693
|
+
/\{\{(\w+)\}\}/g,
|
|
694
|
+
(_, key) => String(params[key] ?? `{{${key}}}`)
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
const TranslationsProvider = ({
|
|
698
|
+
translations,
|
|
699
|
+
children
|
|
700
|
+
}) => {
|
|
701
|
+
const merged = useMemo(
|
|
702
|
+
() => translations ? deepMerge(DEFAULT_TRANSLATIONS, translations) : DEFAULT_TRANSLATIONS,
|
|
703
|
+
[translations]
|
|
704
|
+
);
|
|
705
|
+
return /* @__PURE__ */ jsx(TranslationsContext.Provider, { value: merged, children });
|
|
706
|
+
};
|
|
455
707
|
const HISTORY_RESTORE_SUPPRESSION_MS = 100;
|
|
456
708
|
const HISTORY_BATCH_FLUSH_MS = 16;
|
|
457
709
|
function cloneDocumentSnapshot(document2) {
|
|
@@ -524,12 +776,15 @@ function getPageNumber(document2, pageId) {
|
|
|
524
776
|
const index = document2.pages.findIndex((page) => page.id === pageId);
|
|
525
777
|
return index >= 0 ? index + 1 : null;
|
|
526
778
|
}
|
|
527
|
-
function describeAction(action, document2) {
|
|
779
|
+
function describeAction(action, document2, t) {
|
|
780
|
+
const pageSuffix = (pageId) => {
|
|
781
|
+
const num = getPageNumber(document2, pageId);
|
|
782
|
+
return num ? ` - ${interpolate(t.regions.page, { page: num })}` : "";
|
|
783
|
+
};
|
|
528
784
|
switch (action.type) {
|
|
529
785
|
case "UPDATE_PAGE_BODY": {
|
|
530
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
531
786
|
return {
|
|
532
|
-
label:
|
|
787
|
+
label: t.historyLabels.editedBody + pageSuffix(action.pageId),
|
|
533
788
|
source: "body",
|
|
534
789
|
pageId: action.pageId,
|
|
535
790
|
region: "body"
|
|
@@ -537,9 +792,8 @@ function describeAction(action, document2) {
|
|
|
537
792
|
}
|
|
538
793
|
case "UPDATE_PAGE_HEADER":
|
|
539
794
|
case "UPDATE_PAGE_HEADER_CONTENT": {
|
|
540
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
541
795
|
return {
|
|
542
|
-
label:
|
|
796
|
+
label: t.historyLabels.editedHeader + pageSuffix(action.pageId),
|
|
543
797
|
source: "header",
|
|
544
798
|
pageId: action.pageId,
|
|
545
799
|
region: "header"
|
|
@@ -547,9 +801,8 @@ function describeAction(action, document2) {
|
|
|
547
801
|
}
|
|
548
802
|
case "UPDATE_PAGE_FOOTER":
|
|
549
803
|
case "UPDATE_PAGE_FOOTER_CONTENT": {
|
|
550
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
551
804
|
return {
|
|
552
|
-
label:
|
|
805
|
+
label: t.historyLabels.editedFooter + pageSuffix(action.pageId),
|
|
553
806
|
source: "footer",
|
|
554
807
|
pageId: action.pageId,
|
|
555
808
|
region: "footer"
|
|
@@ -557,43 +810,41 @@ function describeAction(action, document2) {
|
|
|
557
810
|
}
|
|
558
811
|
case "SET_HEADER_FOOTER_ENABLED":
|
|
559
812
|
return {
|
|
560
|
-
label: action.enabled ?
|
|
813
|
+
label: action.enabled ? t.history.actions.enabledHeadersFooters : t.history.actions.disabledHeadersFooters,
|
|
561
814
|
source: "document",
|
|
562
815
|
region: "document"
|
|
563
816
|
};
|
|
564
817
|
case "SET_PAGE_COUNTER_MODE":
|
|
565
818
|
return {
|
|
566
|
-
label:
|
|
819
|
+
label: interpolate(t.history.actions.pageCounterSet, { value: action.mode }),
|
|
567
820
|
source: "document",
|
|
568
821
|
region: "document"
|
|
569
822
|
};
|
|
570
823
|
case "COPY_HEADER_TO_ALL":
|
|
571
824
|
return {
|
|
572
|
-
label:
|
|
825
|
+
label: t.history.actions.copiedHeaderToAll,
|
|
573
826
|
source: "toolbar",
|
|
574
827
|
pageId: action.sourcePageId,
|
|
575
828
|
region: "header"
|
|
576
829
|
};
|
|
577
830
|
case "COPY_FOOTER_TO_ALL":
|
|
578
831
|
return {
|
|
579
|
-
label:
|
|
832
|
+
label: t.history.actions.copiedFooterToAll,
|
|
580
833
|
source: "toolbar",
|
|
581
834
|
pageId: action.sourcePageId,
|
|
582
835
|
region: "footer"
|
|
583
836
|
};
|
|
584
837
|
case "CLEAR_HEADER": {
|
|
585
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
586
838
|
return {
|
|
587
|
-
label:
|
|
839
|
+
label: t.history.actions.clearedHeader + pageSuffix(action.pageId),
|
|
588
840
|
source: "toolbar",
|
|
589
841
|
pageId: action.pageId,
|
|
590
842
|
region: "header"
|
|
591
843
|
};
|
|
592
844
|
}
|
|
593
845
|
case "CLEAR_FOOTER": {
|
|
594
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
595
846
|
return {
|
|
596
|
-
label:
|
|
847
|
+
label: t.history.actions.clearedFooter + pageSuffix(action.pageId),
|
|
597
848
|
source: "toolbar",
|
|
598
849
|
pageId: action.pageId,
|
|
599
850
|
region: "footer"
|
|
@@ -601,35 +852,33 @@ function describeAction(action, document2) {
|
|
|
601
852
|
}
|
|
602
853
|
case "CLEAR_ALL_HEADERS":
|
|
603
854
|
return {
|
|
604
|
-
label:
|
|
855
|
+
label: t.history.actions.clearedAllHeaders,
|
|
605
856
|
source: "toolbar",
|
|
606
857
|
region: "header"
|
|
607
858
|
};
|
|
608
859
|
case "CLEAR_ALL_FOOTERS":
|
|
609
860
|
return {
|
|
610
|
-
label:
|
|
861
|
+
label: t.history.actions.clearedAllFooters,
|
|
611
862
|
source: "toolbar",
|
|
612
863
|
region: "footer"
|
|
613
864
|
};
|
|
614
865
|
case "CLEAR_DOCUMENT_CONTENT":
|
|
615
866
|
return {
|
|
616
|
-
label:
|
|
867
|
+
label: t.historyLabels.clearedDocumentBody,
|
|
617
868
|
source: "document",
|
|
618
869
|
region: "document"
|
|
619
870
|
};
|
|
620
871
|
case "SET_HEADER_HEIGHT": {
|
|
621
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
622
872
|
return {
|
|
623
|
-
label:
|
|
873
|
+
label: t.historyLabels.resizedHeader + pageSuffix(action.pageId),
|
|
624
874
|
source: "header",
|
|
625
875
|
pageId: action.pageId,
|
|
626
876
|
region: "header"
|
|
627
877
|
};
|
|
628
878
|
}
|
|
629
879
|
case "SET_FOOTER_HEIGHT": {
|
|
630
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
631
880
|
return {
|
|
632
|
-
label:
|
|
881
|
+
label: t.historyLabels.resizedFooter + pageSuffix(action.pageId),
|
|
633
882
|
source: "footer",
|
|
634
883
|
pageId: action.pageId,
|
|
635
884
|
region: "footer"
|
|
@@ -637,25 +886,25 @@ function describeAction(action, document2) {
|
|
|
637
886
|
}
|
|
638
887
|
case "ADD_PAGE":
|
|
639
888
|
return {
|
|
640
|
-
label:
|
|
889
|
+
label: t.historyLabels.addedPage,
|
|
641
890
|
source: "overflow",
|
|
642
891
|
region: "document"
|
|
643
892
|
};
|
|
644
893
|
case "REMOVE_PAGE":
|
|
645
894
|
return {
|
|
646
|
-
label:
|
|
895
|
+
label: t.historyLabels.removedPage,
|
|
647
896
|
source: "overflow",
|
|
648
897
|
region: "document"
|
|
649
898
|
};
|
|
650
899
|
case "SET_DOCUMENT":
|
|
651
900
|
return {
|
|
652
|
-
label:
|
|
901
|
+
label: t.historyLabels.documentReflow,
|
|
653
902
|
source: "overflow",
|
|
654
903
|
region: "document"
|
|
655
904
|
};
|
|
656
905
|
default:
|
|
657
906
|
return {
|
|
658
|
-
label:
|
|
907
|
+
label: t.historyLabels.updatedDocument,
|
|
659
908
|
source: "document",
|
|
660
909
|
region: "document"
|
|
661
910
|
};
|
|
@@ -682,6 +931,7 @@ const DocumentProvider = ({
|
|
|
682
931
|
const [globalSelectionActive, setGlobalSelectionActive] = useState(false);
|
|
683
932
|
const [historySidebarOpen, setHistorySidebarOpen] = useState(true);
|
|
684
933
|
const [focusAtEndVersion, setFocusAtEndVersion] = useState(0);
|
|
934
|
+
const t = useTranslations();
|
|
685
935
|
const activeEditorRef = useRef(null);
|
|
686
936
|
const activeCaretPositionRef = useRef(null);
|
|
687
937
|
const pendingCaretPositionRef = useRef(null);
|
|
@@ -875,7 +1125,7 @@ const DocumentProvider = ({
|
|
|
875
1125
|
};
|
|
876
1126
|
scheduleHistoryBatchFlush();
|
|
877
1127
|
} else {
|
|
878
|
-
const descriptor = describeAction(action, currentDocument);
|
|
1128
|
+
const descriptor = describeAction(action, currentDocument, t);
|
|
879
1129
|
setHistoryState((previousHistory) => {
|
|
880
1130
|
const nextHistory = recordHistoryEntry(
|
|
881
1131
|
previousHistory,
|
|
@@ -1474,194 +1724,6 @@ const __iconNode = [
|
|
|
1474
1724
|
["path", { d: "m6 6 12 12", key: "d8bk6v" }]
|
|
1475
1725
|
];
|
|
1476
1726
|
const X = createLucideIcon("x", __iconNode);
|
|
1477
|
-
const DEFAULT_TRANSLATIONS = {
|
|
1478
|
-
toolbar: {
|
|
1479
|
-
undo: "Undo",
|
|
1480
|
-
redo: "Redo",
|
|
1481
|
-
bold: "Bold (Ctrl+B)",
|
|
1482
|
-
italic: "Italic (Ctrl+I)",
|
|
1483
|
-
underline: "Underline (Ctrl+U)",
|
|
1484
|
-
strikethrough: "Strikethrough",
|
|
1485
|
-
alignLeft: "Align Left",
|
|
1486
|
-
alignCenter: "Align Center",
|
|
1487
|
-
alignRight: "Align Right",
|
|
1488
|
-
justify: "Justify",
|
|
1489
|
-
numberedList: "Numbered List",
|
|
1490
|
-
bulletList: "Bullet List",
|
|
1491
|
-
indent: "Indent",
|
|
1492
|
-
outdent: "Outdent",
|
|
1493
|
-
openHistory: "Open History",
|
|
1494
|
-
closeHistory: "Close History"
|
|
1495
|
-
},
|
|
1496
|
-
history: {
|
|
1497
|
-
title: "History",
|
|
1498
|
-
subtitle: "Word-style session history (last 100 actions)",
|
|
1499
|
-
empty: "No history yet.",
|
|
1500
|
-
clearHistory: "Clear History",
|
|
1501
|
-
actions: {
|
|
1502
|
-
enabledHeadersFooters: "Enabled headers and footers",
|
|
1503
|
-
disabledHeadersFooters: "Disabled headers and footers",
|
|
1504
|
-
copiedHeaderToAll: "Copied header to all pages",
|
|
1505
|
-
copiedFooterToAll: "Copied footer to all pages",
|
|
1506
|
-
clearedHeader: "Cleared header",
|
|
1507
|
-
clearedFooter: "Cleared footer",
|
|
1508
|
-
clearedAllHeaders: "Cleared all headers",
|
|
1509
|
-
clearedAllFooters: "Cleared all footers",
|
|
1510
|
-
pageCounterSet: "Page counter set to {{value}}",
|
|
1511
|
-
boldApplied: "Bold applied",
|
|
1512
|
-
italicApplied: "Italic applied",
|
|
1513
|
-
underlineApplied: "Underline applied",
|
|
1514
|
-
strikethroughApplied: "Strikethrough applied",
|
|
1515
|
-
alignedLeft: "Aligned left",
|
|
1516
|
-
alignedCenter: "Aligned center",
|
|
1517
|
-
alignedRight: "Aligned right",
|
|
1518
|
-
justifiedText: "Justified text",
|
|
1519
|
-
insertedNumberedList: "Inserted numbered list",
|
|
1520
|
-
insertedBulletList: "Inserted bullet list",
|
|
1521
|
-
indentedContent: "Indented content",
|
|
1522
|
-
outdentedContent: "Outdented content",
|
|
1523
|
-
fontChanged: "Font changed to {{value}}",
|
|
1524
|
-
fontSizeChanged: "Font size changed to {{value}}pt"
|
|
1525
|
-
}
|
|
1526
|
-
},
|
|
1527
|
-
variables: {
|
|
1528
|
-
title: "Variables",
|
|
1529
|
-
available: "{{count}} available",
|
|
1530
|
-
refreshVariables: "Refresh variables",
|
|
1531
|
-
searchPlaceholder: "Search variables...",
|
|
1532
|
-
noVariablesFound: "No variables found",
|
|
1533
|
-
insertVariable: "Insert variable {{key}}",
|
|
1534
|
-
openPanel: "Open Variables",
|
|
1535
|
-
closePanel: "Close Variables"
|
|
1536
|
-
},
|
|
1537
|
-
header: {
|
|
1538
|
-
placeholder: "Header"
|
|
1539
|
-
},
|
|
1540
|
-
footer: {
|
|
1541
|
-
placeholder: "Footer"
|
|
1542
|
-
},
|
|
1543
|
-
body: {
|
|
1544
|
-
placeholder: "Start typing..."
|
|
1545
|
-
},
|
|
1546
|
-
headerFooter: {
|
|
1547
|
-
label: "Headers & Footers"
|
|
1548
|
-
},
|
|
1549
|
-
sidebar: {
|
|
1550
|
-
close: "Close sidebar"
|
|
1551
|
-
}
|
|
1552
|
-
};
|
|
1553
|
-
const PT_BR_TRANSLATIONS = {
|
|
1554
|
-
toolbar: {
|
|
1555
|
-
undo: "Desfazer",
|
|
1556
|
-
redo: "Refazer",
|
|
1557
|
-
bold: "Negrito (Ctrl+B)",
|
|
1558
|
-
italic: "Itálico (Ctrl+I)",
|
|
1559
|
-
underline: "Sublinhado (Ctrl+U)",
|
|
1560
|
-
strikethrough: "Tachado",
|
|
1561
|
-
alignLeft: "Alinhar à Esquerda",
|
|
1562
|
-
alignCenter: "Centralizar",
|
|
1563
|
-
alignRight: "Alinhar à Direita",
|
|
1564
|
-
justify: "Justificar",
|
|
1565
|
-
numberedList: "Lista Numerada",
|
|
1566
|
-
bulletList: "Lista com Marcadores",
|
|
1567
|
-
indent: "Aumentar Recuo",
|
|
1568
|
-
outdent: "Diminuir Recuo",
|
|
1569
|
-
openHistory: "Abrir Histórico",
|
|
1570
|
-
closeHistory: "Fechar Histórico"
|
|
1571
|
-
},
|
|
1572
|
-
history: {
|
|
1573
|
-
title: "Histórico",
|
|
1574
|
-
subtitle: "Histórico de sessão (últimas 100 ações)",
|
|
1575
|
-
empty: "Nenhum histórico ainda.",
|
|
1576
|
-
clearHistory: "Limpar Histórico",
|
|
1577
|
-
actions: {
|
|
1578
|
-
enabledHeadersFooters: "Cabeçalhos e rodapés ativados",
|
|
1579
|
-
disabledHeadersFooters: "Cabeçalhos e rodapés desativados",
|
|
1580
|
-
copiedHeaderToAll: "Cabeçalho copiado para todas as páginas",
|
|
1581
|
-
copiedFooterToAll: "Rodapé copiado para todas as páginas",
|
|
1582
|
-
clearedHeader: "Cabeçalho limpo",
|
|
1583
|
-
clearedFooter: "Rodapé limpo",
|
|
1584
|
-
clearedAllHeaders: "Todos os cabeçalhos limpos",
|
|
1585
|
-
clearedAllFooters: "Todos os rodapés limpos",
|
|
1586
|
-
pageCounterSet: "Contador de páginas definido como {{value}}",
|
|
1587
|
-
boldApplied: "Negrito aplicado",
|
|
1588
|
-
italicApplied: "Itálico aplicado",
|
|
1589
|
-
underlineApplied: "Sublinhado aplicado",
|
|
1590
|
-
strikethroughApplied: "Tachado aplicado",
|
|
1591
|
-
alignedLeft: "Alinhado à esquerda",
|
|
1592
|
-
alignedCenter: "Centralizado",
|
|
1593
|
-
alignedRight: "Alinhado à direita",
|
|
1594
|
-
justifiedText: "Texto justificado",
|
|
1595
|
-
insertedNumberedList: "Lista numerada inserida",
|
|
1596
|
-
insertedBulletList: "Lista com marcadores inserida",
|
|
1597
|
-
indentedContent: "Conteúdo recuado",
|
|
1598
|
-
outdentedContent: "Recuo reduzido",
|
|
1599
|
-
fontChanged: "Fonte alterada para {{value}}",
|
|
1600
|
-
fontSizeChanged: "Tamanho da fonte alterado para {{value}}pt"
|
|
1601
|
-
}
|
|
1602
|
-
},
|
|
1603
|
-
variables: {
|
|
1604
|
-
title: "Variáveis",
|
|
1605
|
-
available: "{{count}} disponíveis",
|
|
1606
|
-
refreshVariables: "Atualizar variáveis",
|
|
1607
|
-
searchPlaceholder: "Buscar variáveis...",
|
|
1608
|
-
noVariablesFound: "Nenhuma variável encontrada",
|
|
1609
|
-
insertVariable: "Inserir variável {{key}}",
|
|
1610
|
-
openPanel: "Abrir Variáveis",
|
|
1611
|
-
closePanel: "Fechar Variáveis"
|
|
1612
|
-
},
|
|
1613
|
-
header: {
|
|
1614
|
-
placeholder: "Cabeçalho"
|
|
1615
|
-
},
|
|
1616
|
-
footer: {
|
|
1617
|
-
placeholder: "Rodapé"
|
|
1618
|
-
},
|
|
1619
|
-
body: {
|
|
1620
|
-
placeholder: "Comece a digitar..."
|
|
1621
|
-
},
|
|
1622
|
-
headerFooter: {
|
|
1623
|
-
label: "Cabeçalhos e Rodapés"
|
|
1624
|
-
},
|
|
1625
|
-
sidebar: {
|
|
1626
|
-
close: "Fechar barra lateral"
|
|
1627
|
-
}
|
|
1628
|
-
};
|
|
1629
|
-
function deepMerge(target, source) {
|
|
1630
|
-
if (typeof target !== "object" || target === null) {
|
|
1631
|
-
return source ?? target;
|
|
1632
|
-
}
|
|
1633
|
-
const result = { ...target };
|
|
1634
|
-
for (const key of Object.keys(source)) {
|
|
1635
|
-
const sourceVal = source[key];
|
|
1636
|
-
const targetVal = target[key];
|
|
1637
|
-
if (sourceVal !== void 0 && typeof sourceVal === "object" && sourceVal !== null && !Array.isArray(sourceVal) && typeof targetVal === "object" && targetVal !== null) {
|
|
1638
|
-
result[key] = deepMerge(targetVal, sourceVal);
|
|
1639
|
-
} else if (sourceVal !== void 0) {
|
|
1640
|
-
result[key] = sourceVal;
|
|
1641
|
-
}
|
|
1642
|
-
}
|
|
1643
|
-
return result;
|
|
1644
|
-
}
|
|
1645
|
-
const TranslationsContext = createContext(DEFAULT_TRANSLATIONS);
|
|
1646
|
-
function useTranslations() {
|
|
1647
|
-
return useContext(TranslationsContext);
|
|
1648
|
-
}
|
|
1649
|
-
function interpolate(template, params) {
|
|
1650
|
-
return template.replace(
|
|
1651
|
-
/\{\{(\w+)\}\}/g,
|
|
1652
|
-
(_, key) => String(params[key] ?? `{{${key}}}`)
|
|
1653
|
-
);
|
|
1654
|
-
}
|
|
1655
|
-
const TranslationsProvider = ({
|
|
1656
|
-
translations,
|
|
1657
|
-
children
|
|
1658
|
-
}) => {
|
|
1659
|
-
const merged = useMemo(
|
|
1660
|
-
() => translations ? deepMerge(DEFAULT_TRANSLATIONS, translations) : DEFAULT_TRANSLATIONS,
|
|
1661
|
-
[translations]
|
|
1662
|
-
);
|
|
1663
|
-
return /* @__PURE__ */ jsx(TranslationsContext.Provider, { value: merged, children });
|
|
1664
|
-
};
|
|
1665
1727
|
const EditorSidebar = ({
|
|
1666
1728
|
title,
|
|
1667
1729
|
subtitle,
|
|
@@ -1768,7 +1830,7 @@ const HistorySidebar = () => {
|
|
|
1768
1830
|
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
1769
1831
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
1770
1832
|
/* @__PURE__ */ jsx("div", { className: `text-xs ${isCurrent ? "font-semibold text-blue-700" : "text-gray-900"}`, children: entry.label }),
|
|
1771
|
-
/* @__PURE__ */ jsx("div", { className: "mt-0.5 text-xs text-gray-400", children: entry.source })
|
|
1833
|
+
/* @__PURE__ */ jsx("div", { className: "mt-0.5 text-xs text-gray-400", children: t.regions[entry.source] ?? entry.source })
|
|
1772
1834
|
] }),
|
|
1773
1835
|
/* @__PURE__ */ jsx("div", { className: "shrink-0 text-xs text-gray-400", children: formatTimestamp(entry.timestamp) })
|
|
1774
1836
|
] })
|
|
@@ -2513,6 +2575,19 @@ function mergeEditorStates(stateA, stateB) {
|
|
|
2513
2575
|
if (all.length === 0) return null;
|
|
2514
2576
|
return createEditorStateFromNodes(all);
|
|
2515
2577
|
}
|
|
2578
|
+
function splitBlockNode(block, childOffset) {
|
|
2579
|
+
const children = block.children ?? [];
|
|
2580
|
+
if (childOffset <= 0) return [null, structuredClone(block)];
|
|
2581
|
+
if (childOffset >= children.length) return [structuredClone(block), null];
|
|
2582
|
+
const before = children.slice(0, childOffset);
|
|
2583
|
+
const after = children.slice(childOffset);
|
|
2584
|
+
const makeCopy = (kids) => {
|
|
2585
|
+
const copy = structuredClone(block);
|
|
2586
|
+
copy.children = kids;
|
|
2587
|
+
return copy;
|
|
2588
|
+
};
|
|
2589
|
+
return [makeCopy(before), makeCopy(after)];
|
|
2590
|
+
}
|
|
2516
2591
|
function usePagination(document2, dispatch) {
|
|
2517
2592
|
const reflowingRef = useRef(false);
|
|
2518
2593
|
const pendingReflowRef = useRef(false);
|
|
@@ -2547,7 +2622,61 @@ function usePagination(document2, dispatch) {
|
|
|
2547
2622
|
const footerH = document2.headerFooterEnabled ? page.footerHeight : 0;
|
|
2548
2623
|
const bodyHeight = computeBodyHeight(headerH, footerH);
|
|
2549
2624
|
const nodes = getTopLevelNodes(page.bodyState);
|
|
2550
|
-
if (nodes.length <= 1)
|
|
2625
|
+
if (nodes.length <= 1) {
|
|
2626
|
+
if (nodes.length === 1) {
|
|
2627
|
+
const singleNode = nodes[0];
|
|
2628
|
+
const children = singleNode.children;
|
|
2629
|
+
if (children && children.length > 1) {
|
|
2630
|
+
const estimatedLineHeight = 24;
|
|
2631
|
+
const maxChildren = Math.max(1, Math.floor(bodyHeight / estimatedLineHeight));
|
|
2632
|
+
if (maxChildren < children.length) {
|
|
2633
|
+
const [keepBlock, overflowBlock] = splitBlockNode(singleNode, maxChildren);
|
|
2634
|
+
if (keepBlock && overflowBlock) {
|
|
2635
|
+
const keepState2 = createEditorStateFromNodes([keepBlock]);
|
|
2636
|
+
const overflowState2 = createEditorStateFromNodes([overflowBlock]);
|
|
2637
|
+
const nextPage2 = pages[pageIndex + 1];
|
|
2638
|
+
if (nextPage2) {
|
|
2639
|
+
const mergedBody = mergeEditorStates(overflowState2, nextPage2.bodyState);
|
|
2640
|
+
dispatch({
|
|
2641
|
+
type: "SET_DOCUMENT",
|
|
2642
|
+
document: {
|
|
2643
|
+
...document2,
|
|
2644
|
+
pages: pages.map((p, i) => {
|
|
2645
|
+
if (i === pageIndex) return { ...p, bodyState: keepState2 };
|
|
2646
|
+
if (i === pageIndex + 1) return { ...p, bodyState: mergedBody };
|
|
2647
|
+
return p;
|
|
2648
|
+
})
|
|
2649
|
+
}
|
|
2650
|
+
});
|
|
2651
|
+
} else {
|
|
2652
|
+
const newPage = {
|
|
2653
|
+
...createPageFromTemplate({
|
|
2654
|
+
headerState: document2.defaultHeaderState,
|
|
2655
|
+
footerState: document2.defaultFooterState,
|
|
2656
|
+
headerHeight: document2.defaultHeaderHeight,
|
|
2657
|
+
footerHeight: document2.defaultFooterHeight
|
|
2658
|
+
}),
|
|
2659
|
+
bodyState: overflowState2
|
|
2660
|
+
};
|
|
2661
|
+
dispatch({
|
|
2662
|
+
type: "SET_DOCUMENT",
|
|
2663
|
+
document: {
|
|
2664
|
+
...document2,
|
|
2665
|
+
pages: [
|
|
2666
|
+
...pages.map(
|
|
2667
|
+
(p, i) => i === pageIndex ? { ...p, bodyState: keepState2 } : p
|
|
2668
|
+
),
|
|
2669
|
+
newPage
|
|
2670
|
+
]
|
|
2671
|
+
}
|
|
2672
|
+
});
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
return;
|
|
2679
|
+
}
|
|
2551
2680
|
const fitCount = estimateNodesFitting(page.bodyState, bodyHeight);
|
|
2552
2681
|
if (fitCount >= nodes.length) return;
|
|
2553
2682
|
const [keepState, overflowState] = splitEditorState(page.bodyState, fitCount);
|
|
@@ -2917,6 +3046,213 @@ const ActiveEditorPlugin = ({
|
|
|
2917
3046
|
}, [editor, onFocus, pageId, region, setActiveEditor, setActivePageId]);
|
|
2918
3047
|
return null;
|
|
2919
3048
|
};
|
|
3049
|
+
function findMidBlockSplitPoint(blockElement, availableHeight) {
|
|
3050
|
+
const blockRect = blockElement.getBoundingClientRect();
|
|
3051
|
+
const maxBottom = blockRect.top + availableHeight;
|
|
3052
|
+
const textNodes = [];
|
|
3053
|
+
const walker = document.createTreeWalker(blockElement, NodeFilter.SHOW_TEXT);
|
|
3054
|
+
let walkNode;
|
|
3055
|
+
while (walkNode = walker.nextNode()) {
|
|
3056
|
+
if (walkNode.length > 0) {
|
|
3057
|
+
textNodes.push(walkNode);
|
|
3058
|
+
}
|
|
3059
|
+
}
|
|
3060
|
+
if (textNodes.length === 0) return null;
|
|
3061
|
+
const range = document.createRange();
|
|
3062
|
+
for (const textNode of textNodes) {
|
|
3063
|
+
range.selectNodeContents(textNode);
|
|
3064
|
+
const nodeRect = range.getBoundingClientRect();
|
|
3065
|
+
if (nodeRect.bottom <= maxBottom) {
|
|
3066
|
+
continue;
|
|
3067
|
+
}
|
|
3068
|
+
if (nodeRect.top >= maxBottom) {
|
|
3069
|
+
return backupToWordBoundary(textNode, 0);
|
|
3070
|
+
}
|
|
3071
|
+
let low = 0;
|
|
3072
|
+
let high = textNode.length;
|
|
3073
|
+
while (low < high) {
|
|
3074
|
+
const mid = Math.floor((low + high) / 2);
|
|
3075
|
+
range.setStart(textNode, 0);
|
|
3076
|
+
range.setEnd(textNode, mid + 1);
|
|
3077
|
+
const testRect = range.getBoundingClientRect();
|
|
3078
|
+
if (testRect.bottom > maxBottom) {
|
|
3079
|
+
high = mid;
|
|
3080
|
+
} else {
|
|
3081
|
+
low = mid + 1;
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
3084
|
+
return backupToWordBoundary(textNode, low);
|
|
3085
|
+
}
|
|
3086
|
+
return null;
|
|
3087
|
+
}
|
|
3088
|
+
function backupToWordBoundary(textNode, offset) {
|
|
3089
|
+
const text = textNode.textContent || "";
|
|
3090
|
+
if (offset <= 0 || offset >= text.length) {
|
|
3091
|
+
if (offset > 0 && offset < text.length) {
|
|
3092
|
+
return { textNode, offset };
|
|
3093
|
+
}
|
|
3094
|
+
if (offset > 0) return { textNode, offset };
|
|
3095
|
+
return null;
|
|
3096
|
+
}
|
|
3097
|
+
let adjusted = offset;
|
|
3098
|
+
while (adjusted > 0 && !/\s/.test(text[adjusted - 1])) {
|
|
3099
|
+
adjusted--;
|
|
3100
|
+
}
|
|
3101
|
+
if (adjusted <= 0) {
|
|
3102
|
+
adjusted = offset;
|
|
3103
|
+
}
|
|
3104
|
+
return { textNode, offset: adjusted };
|
|
3105
|
+
}
|
|
3106
|
+
function serializeNodeTree$1(node) {
|
|
3107
|
+
const json = node.exportJSON();
|
|
3108
|
+
if ($isElementNode(node)) {
|
|
3109
|
+
json.children = node.getChildren().map(serializeNodeTree$1);
|
|
3110
|
+
}
|
|
3111
|
+
return json;
|
|
3112
|
+
}
|
|
3113
|
+
function findListSplitIndex(listElement, availableHeight) {
|
|
3114
|
+
const listRect = listElement.getBoundingClientRect();
|
|
3115
|
+
const maxBottom = listRect.top + availableHeight;
|
|
3116
|
+
const children = Array.from(listElement.children);
|
|
3117
|
+
for (let i = 0; i < children.length; i++) {
|
|
3118
|
+
const child = children[i];
|
|
3119
|
+
const childRect = child.getBoundingClientRect();
|
|
3120
|
+
if (childRect.bottom > maxBottom && i > 0) {
|
|
3121
|
+
return i;
|
|
3122
|
+
}
|
|
3123
|
+
}
|
|
3124
|
+
return -1;
|
|
3125
|
+
}
|
|
3126
|
+
function performMidBlockSplit(rootElement, availableHeight, overflowBlockIndex) {
|
|
3127
|
+
const root = $getRoot();
|
|
3128
|
+
const allChildren = root.getChildren();
|
|
3129
|
+
const blockNode = allChildren[overflowBlockIndex];
|
|
3130
|
+
if (!blockNode || !$isElementNode(blockNode)) {
|
|
3131
|
+
debugWarn("overflow", "target node is not an ElementNode");
|
|
3132
|
+
return null;
|
|
3133
|
+
}
|
|
3134
|
+
const blockElements = Array.from(rootElement.children);
|
|
3135
|
+
const blockElement = blockElements[overflowBlockIndex];
|
|
3136
|
+
if (!blockElement) {
|
|
3137
|
+
debugWarn("overflow", "no DOM element for block index");
|
|
3138
|
+
return null;
|
|
3139
|
+
}
|
|
3140
|
+
const blockTop = blockElement.offsetTop;
|
|
3141
|
+
const heightForBlock = availableHeight - blockTop;
|
|
3142
|
+
if (heightForBlock <= 0) {
|
|
3143
|
+
debugWarn("overflow", "no space for block");
|
|
3144
|
+
return null;
|
|
3145
|
+
}
|
|
3146
|
+
if ($isListNode(blockNode)) {
|
|
3147
|
+
return splitListNode(blockNode, blockElement, heightForBlock);
|
|
3148
|
+
}
|
|
3149
|
+
return splitParagraphNode(blockNode, blockElement, heightForBlock);
|
|
3150
|
+
}
|
|
3151
|
+
function splitListNode(listNode, listElement, availableHeight) {
|
|
3152
|
+
const splitIndex = findListSplitIndex(listElement, availableHeight);
|
|
3153
|
+
if (splitIndex <= 0) {
|
|
3154
|
+
debug("overflow", "cannot split list — first item exceeds height");
|
|
3155
|
+
return null;
|
|
3156
|
+
}
|
|
3157
|
+
const [, overflowList] = $splitNode(listNode, splitIndex);
|
|
3158
|
+
const overflowNodes = [];
|
|
3159
|
+
const toRemove = [];
|
|
3160
|
+
overflowNodes.push(serializeNodeTree$1(overflowList));
|
|
3161
|
+
toRemove.push(overflowList);
|
|
3162
|
+
let nextSibling = overflowList.getNextSibling();
|
|
3163
|
+
while (nextSibling) {
|
|
3164
|
+
overflowNodes.push(serializeNodeTree$1(nextSibling));
|
|
3165
|
+
toRemove.push(nextSibling);
|
|
3166
|
+
nextSibling = nextSibling.getNextSibling();
|
|
3167
|
+
}
|
|
3168
|
+
for (const node of toRemove) {
|
|
3169
|
+
node.remove();
|
|
3170
|
+
}
|
|
3171
|
+
debug("overflow", `split list at item ${splitIndex}, extracted ${overflowNodes.length} overflow nodes`);
|
|
3172
|
+
return overflowNodes;
|
|
3173
|
+
}
|
|
3174
|
+
function splitParagraphNode(blockNode, blockElement, availableHeight) {
|
|
3175
|
+
const splitPoint = findMidBlockSplitPoint(blockElement, availableHeight);
|
|
3176
|
+
if (!splitPoint) {
|
|
3177
|
+
debug("overflow", "no valid split point found in paragraph");
|
|
3178
|
+
return null;
|
|
3179
|
+
}
|
|
3180
|
+
const lexicalNode = $getNearestNodeFromDOMNode(splitPoint.textNode);
|
|
3181
|
+
if (!lexicalNode || !$isTextNode(lexicalNode)) {
|
|
3182
|
+
debugWarn("overflow", "could not map DOM text node to Lexical TextNode");
|
|
3183
|
+
return null;
|
|
3184
|
+
}
|
|
3185
|
+
const [, afterText] = lexicalNode.splitText(splitPoint.offset);
|
|
3186
|
+
if (!afterText) {
|
|
3187
|
+
debugWarn("overflow", "splitText returned no second half");
|
|
3188
|
+
return null;
|
|
3189
|
+
}
|
|
3190
|
+
const parent = afterText.getParent();
|
|
3191
|
+
if (!parent || !$isElementNode(parent)) {
|
|
3192
|
+
debugWarn("overflow", "split text has no element parent");
|
|
3193
|
+
return null;
|
|
3194
|
+
}
|
|
3195
|
+
let directChild = afterText;
|
|
3196
|
+
let directChildParent = parent;
|
|
3197
|
+
while (directChildParent && directChildParent.getKey() !== blockNode.getKey()) {
|
|
3198
|
+
directChild = directChildParent;
|
|
3199
|
+
const next = directChildParent.getParent();
|
|
3200
|
+
if (!next || !$isElementNode(next)) {
|
|
3201
|
+
debugWarn("overflow", "could not find block node in parent chain");
|
|
3202
|
+
return null;
|
|
3203
|
+
}
|
|
3204
|
+
directChildParent = next;
|
|
3205
|
+
}
|
|
3206
|
+
const splitChildIndex = blockNode.getChildren().indexOf(directChild);
|
|
3207
|
+
if (splitChildIndex <= 0) {
|
|
3208
|
+
debug("overflow", "split index is 0 or not found — nothing to keep on this page");
|
|
3209
|
+
return null;
|
|
3210
|
+
}
|
|
3211
|
+
if (directChild !== afterText) {
|
|
3212
|
+
let current = parent;
|
|
3213
|
+
let childToSplitAt = afterText;
|
|
3214
|
+
while (current.getKey() !== blockNode.getKey()) {
|
|
3215
|
+
const childIdx = current.getChildren().indexOf(childToSplitAt);
|
|
3216
|
+
if (childIdx > 0) {
|
|
3217
|
+
$splitNode(current, childIdx);
|
|
3218
|
+
}
|
|
3219
|
+
childToSplitAt = current;
|
|
3220
|
+
const next = current.getParent();
|
|
3221
|
+
if (!next || !$isElementNode(next)) break;
|
|
3222
|
+
current = next;
|
|
3223
|
+
}
|
|
3224
|
+
}
|
|
3225
|
+
let finalSplitChild = afterText;
|
|
3226
|
+
let p = afterText.getParent();
|
|
3227
|
+
while (p && p.getKey() !== blockNode.getKey()) {
|
|
3228
|
+
finalSplitChild = p;
|
|
3229
|
+
p = p.getParent();
|
|
3230
|
+
}
|
|
3231
|
+
const finalSplitIndex = blockNode.getChildren().indexOf(finalSplitChild);
|
|
3232
|
+
if (finalSplitIndex <= 0) {
|
|
3233
|
+
debug("overflow", "final split index is 0 or not found — nothing to keep on this page");
|
|
3234
|
+
return null;
|
|
3235
|
+
}
|
|
3236
|
+
const [, overflowBlock] = $splitNode(blockNode, finalSplitIndex);
|
|
3237
|
+
const overflowNodes = [];
|
|
3238
|
+
const toRemove = [];
|
|
3239
|
+
overflowNodes.push(serializeNodeTree$1(overflowBlock));
|
|
3240
|
+
toRemove.push(overflowBlock);
|
|
3241
|
+
let nextSibling = overflowBlock.getNextSibling();
|
|
3242
|
+
while (nextSibling) {
|
|
3243
|
+
overflowNodes.push(serializeNodeTree$1(nextSibling));
|
|
3244
|
+
toRemove.push(nextSibling);
|
|
3245
|
+
nextSibling = nextSibling.getNextSibling();
|
|
3246
|
+
}
|
|
3247
|
+
for (const node of toRemove) {
|
|
3248
|
+
node.remove();
|
|
3249
|
+
}
|
|
3250
|
+
debug(
|
|
3251
|
+
"overflow",
|
|
3252
|
+
`split paragraph at offset ${splitPoint.offset}, extracted ${overflowNodes.length} overflow nodes`
|
|
3253
|
+
);
|
|
3254
|
+
return overflowNodes;
|
|
3255
|
+
}
|
|
2920
3256
|
function serializeNodeTree(node) {
|
|
2921
3257
|
const json = node.exportJSON();
|
|
2922
3258
|
if ($isElementNode(node)) {
|
|
@@ -2945,18 +3281,51 @@ const OverflowPlugin = ({
|
|
|
2945
3281
|
const children = Array.from(rootElement.children);
|
|
2946
3282
|
if (children.length === 0) return;
|
|
2947
3283
|
if (children.length <= 1) {
|
|
2948
|
-
debug("overflow", `single block overflows (content=${contentHeight}px > available=${availableHeight}px) —
|
|
3284
|
+
debug("overflow", `single block overflows (content=${contentHeight}px > available=${availableHeight}px) — attempting mid-block split`);
|
|
3285
|
+
processingRef.current = true;
|
|
3286
|
+
editor.update(
|
|
3287
|
+
() => {
|
|
3288
|
+
const overflowNodes = performMidBlockSplit(rootElement, availableHeight, 0);
|
|
3289
|
+
if (!overflowNodes || overflowNodes.length === 0) {
|
|
3290
|
+
debug("overflow", "mid-block split not possible for single block");
|
|
3291
|
+
processingRef.current = false;
|
|
3292
|
+
return;
|
|
3293
|
+
}
|
|
3294
|
+
const overflowState = {
|
|
3295
|
+
root: {
|
|
3296
|
+
children: overflowNodes,
|
|
3297
|
+
direction: null,
|
|
3298
|
+
format: "",
|
|
3299
|
+
indent: 0,
|
|
3300
|
+
type: "root",
|
|
3301
|
+
version: 1
|
|
3302
|
+
}
|
|
3303
|
+
};
|
|
3304
|
+
debug("overflow", `mid-block split extracted ${overflowNodes.length} overflow nodes from single block`);
|
|
3305
|
+
setTimeout(() => {
|
|
3306
|
+
onOverflowRef.current(overflowState, cause);
|
|
3307
|
+
processingRef.current = false;
|
|
3308
|
+
}, 0);
|
|
3309
|
+
},
|
|
3310
|
+
{ tag: "overflow-split" }
|
|
3311
|
+
);
|
|
2949
3312
|
return;
|
|
2950
3313
|
}
|
|
2951
3314
|
processingRef.current = true;
|
|
2952
3315
|
debug("overflow", `OVERFLOW detected: content=${contentHeight}px available=${availableHeight}px children=${children.length}`);
|
|
2953
3316
|
let splitIndex = children.length;
|
|
3317
|
+
let firstBlockOverflows = false;
|
|
2954
3318
|
for (let i = 0; i < children.length; i++) {
|
|
2955
3319
|
const child = children[i];
|
|
2956
3320
|
const childBottom = child.offsetTop + child.offsetHeight;
|
|
2957
|
-
if (childBottom > availableHeight
|
|
2958
|
-
|
|
2959
|
-
|
|
3321
|
+
if (childBottom > availableHeight) {
|
|
3322
|
+
if (i === 0) {
|
|
3323
|
+
firstBlockOverflows = true;
|
|
3324
|
+
splitIndex = 1;
|
|
3325
|
+
} else {
|
|
3326
|
+
splitIndex = i;
|
|
3327
|
+
}
|
|
3328
|
+
debug("overflow", `split at index ${i === 0 ? "0 (mid-block)" : i} (childBottom=${childBottom}px > ${availableHeight}px)`);
|
|
2960
3329
|
break;
|
|
2961
3330
|
}
|
|
2962
3331
|
}
|
|
@@ -2974,15 +3343,37 @@ const OverflowPlugin = ({
|
|
|
2974
3343
|
processingRef.current = false;
|
|
2975
3344
|
return;
|
|
2976
3345
|
}
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
3346
|
+
let overflowNodes = [];
|
|
3347
|
+
if (firstBlockOverflows) {
|
|
3348
|
+
const midBlockOverflow = performMidBlockSplit(rootElement, availableHeight, 0);
|
|
3349
|
+
if (midBlockOverflow && midBlockOverflow.length > 0) {
|
|
3350
|
+
overflowNodes.push(...midBlockOverflow);
|
|
3351
|
+
debug("overflow", `mid-block split on first block extracted ${midBlockOverflow.length} nodes`);
|
|
3352
|
+
} else {
|
|
3353
|
+
debug("overflow", "mid-block split failed on first block — keeping it whole");
|
|
3354
|
+
}
|
|
3355
|
+
const freshChildren = root.getChildren();
|
|
3356
|
+
const toRemove = freshChildren.slice(1);
|
|
3357
|
+
for (const node of toRemove) {
|
|
3358
|
+
overflowNodes.push(serializeNodeTree(node));
|
|
3359
|
+
}
|
|
3360
|
+
for (const node of toRemove) {
|
|
3361
|
+
node.remove();
|
|
3362
|
+
}
|
|
3363
|
+
} else {
|
|
3364
|
+
const toRemove = allChildren.slice(splitIndex);
|
|
3365
|
+
for (const node of toRemove) {
|
|
3366
|
+
overflowNodes.push(serializeNodeTree(node));
|
|
3367
|
+
}
|
|
3368
|
+
for (const node of toRemove) {
|
|
3369
|
+
node.remove();
|
|
3370
|
+
}
|
|
2981
3371
|
}
|
|
2982
|
-
|
|
2983
|
-
|
|
3372
|
+
if (overflowNodes.length === 0) {
|
|
3373
|
+
processingRef.current = false;
|
|
3374
|
+
return;
|
|
2984
3375
|
}
|
|
2985
|
-
debug("overflow", `extracted ${overflowNodes.length} overflow nodes
|
|
3376
|
+
debug("overflow", `extracted ${overflowNodes.length} overflow nodes total`);
|
|
2986
3377
|
const overflowState = {
|
|
2987
3378
|
root: {
|
|
2988
3379
|
children: overflowNodes,
|
|
@@ -3063,16 +3454,10 @@ const OverflowPlugin = ({
|
|
|
3063
3454
|
}, [editor]);
|
|
3064
3455
|
return null;
|
|
3065
3456
|
};
|
|
3066
|
-
function createPageLabel(region, pageNumber) {
|
|
3067
|
-
if (region === "body") {
|
|
3068
|
-
return pageNumber ? `Page ${pageNumber}` : "Body";
|
|
3069
|
-
}
|
|
3070
|
-
const regionLabel = region.charAt(0).toUpperCase() + region.slice(1);
|
|
3071
|
-
return pageNumber ? `${regionLabel} Page ${pageNumber}` : regionLabel;
|
|
3072
|
-
}
|
|
3073
3457
|
const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
3074
3458
|
const [editor] = useLexicalComposerContext();
|
|
3075
3459
|
const { document: document2, queueHistoryAction } = useDocument();
|
|
3460
|
+
const t = useTranslations();
|
|
3076
3461
|
const context = useMemo(() => {
|
|
3077
3462
|
const pageNumber = document2.pages.findIndex((page) => page.id === pageId);
|
|
3078
3463
|
return {
|
|
@@ -3080,9 +3465,18 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3080
3465
|
source: region
|
|
3081
3466
|
};
|
|
3082
3467
|
}, [document2.pages, pageId, region]);
|
|
3468
|
+
const createPageLabel = useMemo(() => {
|
|
3469
|
+
return (r, pageNumber) => {
|
|
3470
|
+
if (r === "body") {
|
|
3471
|
+
return pageNumber ? interpolate(t.regions.page, { page: pageNumber }) : t.regions.body;
|
|
3472
|
+
}
|
|
3473
|
+
const regionLabel = r === "header" ? t.regions.header : t.regions.footer;
|
|
3474
|
+
return pageNumber ? `${regionLabel} ${interpolate(t.regions.page, { page: pageNumber })}` : regionLabel;
|
|
3475
|
+
};
|
|
3476
|
+
}, [t]);
|
|
3083
3477
|
useEffect(() => {
|
|
3084
|
-
const buildDescriptor = (
|
|
3085
|
-
label: `${
|
|
3478
|
+
const buildDescriptor = (label) => ({
|
|
3479
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
3086
3480
|
source: context.source,
|
|
3087
3481
|
pageId,
|
|
3088
3482
|
region
|
|
@@ -3090,15 +3484,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3090
3484
|
return editor.registerCommand(
|
|
3091
3485
|
CONTROLLED_TEXT_INSERTION_COMMAND,
|
|
3092
3486
|
() => {
|
|
3093
|
-
queueHistoryAction(buildDescriptor(
|
|
3487
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.typedText));
|
|
3094
3488
|
return false;
|
|
3095
3489
|
},
|
|
3096
3490
|
COMMAND_PRIORITY_LOW
|
|
3097
3491
|
);
|
|
3098
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3492
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3099
3493
|
useEffect(() => {
|
|
3100
|
-
const buildDescriptor = (
|
|
3101
|
-
label: `${
|
|
3494
|
+
const buildDescriptor = (label) => ({
|
|
3495
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
3102
3496
|
source: context.source,
|
|
3103
3497
|
pageId,
|
|
3104
3498
|
region
|
|
@@ -3112,15 +3506,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3112
3506
|
if (event.key.length !== 1) {
|
|
3113
3507
|
return false;
|
|
3114
3508
|
}
|
|
3115
|
-
queueHistoryAction(buildDescriptor(
|
|
3509
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.typedText));
|
|
3116
3510
|
return false;
|
|
3117
3511
|
},
|
|
3118
3512
|
COMMAND_PRIORITY_LOW
|
|
3119
3513
|
);
|
|
3120
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3514
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3121
3515
|
useEffect(() => {
|
|
3122
|
-
const buildDescriptor = (
|
|
3123
|
-
label: `${
|
|
3516
|
+
const buildDescriptor = (label) => ({
|
|
3517
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
3124
3518
|
source: context.source,
|
|
3125
3519
|
pageId,
|
|
3126
3520
|
region
|
|
@@ -3133,15 +3527,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3133
3527
|
if (text.trim().length === 0) {
|
|
3134
3528
|
return false;
|
|
3135
3529
|
}
|
|
3136
|
-
queueHistoryAction(buildDescriptor(
|
|
3530
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.pastedContent));
|
|
3137
3531
|
return false;
|
|
3138
3532
|
},
|
|
3139
3533
|
COMMAND_PRIORITY_LOW
|
|
3140
3534
|
);
|
|
3141
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3535
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3142
3536
|
useEffect(() => {
|
|
3143
|
-
const buildDescriptor = (
|
|
3144
|
-
label: `${
|
|
3537
|
+
const buildDescriptor = (label) => ({
|
|
3538
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
3145
3539
|
source: context.source,
|
|
3146
3540
|
pageId,
|
|
3147
3541
|
region
|
|
@@ -3149,15 +3543,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3149
3543
|
return editor.registerCommand(
|
|
3150
3544
|
KEY_ENTER_COMMAND,
|
|
3151
3545
|
() => {
|
|
3152
|
-
queueHistoryAction(buildDescriptor(
|
|
3546
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.insertedLineBreak));
|
|
3153
3547
|
return false;
|
|
3154
3548
|
},
|
|
3155
3549
|
COMMAND_PRIORITY_LOW
|
|
3156
3550
|
);
|
|
3157
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3551
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3158
3552
|
useEffect(() => {
|
|
3159
|
-
const buildDescriptor = (
|
|
3160
|
-
label: `${
|
|
3553
|
+
const buildDescriptor = (label) => ({
|
|
3554
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
3161
3555
|
source: context.source,
|
|
3162
3556
|
pageId,
|
|
3163
3557
|
region
|
|
@@ -3165,15 +3559,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3165
3559
|
return editor.registerCommand(
|
|
3166
3560
|
KEY_BACKSPACE_COMMAND,
|
|
3167
3561
|
() => {
|
|
3168
|
-
queueHistoryAction(buildDescriptor(
|
|
3562
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.deletedBackward));
|
|
3169
3563
|
return false;
|
|
3170
3564
|
},
|
|
3171
3565
|
COMMAND_PRIORITY_LOW
|
|
3172
3566
|
);
|
|
3173
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3567
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3174
3568
|
useEffect(() => {
|
|
3175
|
-
const buildDescriptor = (
|
|
3176
|
-
label: `${
|
|
3569
|
+
const buildDescriptor = (label) => ({
|
|
3570
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
3177
3571
|
source: context.source,
|
|
3178
3572
|
pageId,
|
|
3179
3573
|
region
|
|
@@ -3181,15 +3575,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3181
3575
|
return editor.registerCommand(
|
|
3182
3576
|
KEY_DELETE_COMMAND,
|
|
3183
3577
|
() => {
|
|
3184
|
-
queueHistoryAction(buildDescriptor(
|
|
3578
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.deletedForward));
|
|
3185
3579
|
return false;
|
|
3186
3580
|
},
|
|
3187
3581
|
COMMAND_PRIORITY_LOW
|
|
3188
3582
|
);
|
|
3189
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3583
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3190
3584
|
useEffect(() => {
|
|
3191
|
-
const buildDescriptor = (
|
|
3192
|
-
label: `${
|
|
3585
|
+
const buildDescriptor = (label) => ({
|
|
3586
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
3193
3587
|
source: context.source,
|
|
3194
3588
|
pageId,
|
|
3195
3589
|
region
|
|
@@ -3197,15 +3591,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3197
3591
|
return editor.registerCommand(
|
|
3198
3592
|
FORMAT_TEXT_COMMAND,
|
|
3199
3593
|
() => {
|
|
3200
|
-
queueHistoryAction(buildDescriptor(
|
|
3594
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.formattedText));
|
|
3201
3595
|
return false;
|
|
3202
3596
|
},
|
|
3203
3597
|
COMMAND_PRIORITY_LOW
|
|
3204
3598
|
);
|
|
3205
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3599
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3206
3600
|
useEffect(() => {
|
|
3207
|
-
const buildDescriptor = (
|
|
3208
|
-
label: `${
|
|
3601
|
+
const buildDescriptor = (label) => ({
|
|
3602
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
3209
3603
|
source: context.source,
|
|
3210
3604
|
pageId,
|
|
3211
3605
|
region
|
|
@@ -3213,12 +3607,12 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3213
3607
|
return editor.registerCommand(
|
|
3214
3608
|
FORMAT_ELEMENT_COMMAND,
|
|
3215
3609
|
() => {
|
|
3216
|
-
queueHistoryAction(buildDescriptor(
|
|
3610
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.formattedParagraph));
|
|
3217
3611
|
return false;
|
|
3218
3612
|
},
|
|
3219
3613
|
COMMAND_PRIORITY_LOW
|
|
3220
3614
|
);
|
|
3221
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3615
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3222
3616
|
return null;
|
|
3223
3617
|
};
|
|
3224
3618
|
function getCollapsedTextPosition(rootElement) {
|
|
@@ -3631,10 +4025,14 @@ const PageView = React.memo(({
|
|
|
3631
4025
|
onMoveToNextPage
|
|
3632
4026
|
}) => {
|
|
3633
4027
|
const { document: document2, dispatch, setActivePageId } = useDocument();
|
|
4028
|
+
const t = useTranslations();
|
|
3634
4029
|
const page = document2.pages.find((p) => p.id === pageId);
|
|
3635
4030
|
const showHeaderFooter = document2.headerFooterEnabled;
|
|
3636
4031
|
const pageCounterMode = document2.pageCounterMode;
|
|
3637
|
-
const pageCounterLabel =
|
|
4032
|
+
const pageCounterLabel = interpolate(t.pageCounter.format, {
|
|
4033
|
+
current: pageIndex + 1,
|
|
4034
|
+
total: document2.pages.length
|
|
4035
|
+
});
|
|
3638
4036
|
if (!page) return null;
|
|
3639
4037
|
const handleBodyChange = useCallback(
|
|
3640
4038
|
(bodyState) => {
|
|
@@ -3725,6 +4123,7 @@ const DocumentView = () => {
|
|
|
3725
4123
|
setActiveEditor,
|
|
3726
4124
|
setActivePageId
|
|
3727
4125
|
} = useDocument();
|
|
4126
|
+
const t = useTranslations();
|
|
3728
4127
|
const { handlePageUnderflow, reflowAll } = usePagination(document2, dispatch);
|
|
3729
4128
|
const previousBodyHeightsRef = useRef(null);
|
|
3730
4129
|
const pasteOverflowSequenceRef = useRef(false);
|
|
@@ -3889,7 +4288,7 @@ const DocumentView = () => {
|
|
|
3889
4288
|
}
|
|
3890
4289
|
runHistoryAction(
|
|
3891
4290
|
{
|
|
3892
|
-
label:
|
|
4291
|
+
label: `${t.historyLabels.deletedBackward} - ${interpolate(t.regions.page, { page: pageIndex + 1 })}`,
|
|
3893
4292
|
source: "body",
|
|
3894
4293
|
pageId,
|
|
3895
4294
|
region: "body"
|
|
@@ -3911,7 +4310,7 @@ const DocumentView = () => {
|
|
|
3911
4310
|
}
|
|
3912
4311
|
runHistoryAction(
|
|
3913
4312
|
{
|
|
3914
|
-
label:
|
|
4313
|
+
label: `${t.historyLabels.deletedForward} - ${interpolate(t.regions.page, { page: pageIndex + 1 })}`,
|
|
3915
4314
|
source: "body",
|
|
3916
4315
|
pageId,
|
|
3917
4316
|
region: "body"
|
|
@@ -4144,7 +4543,7 @@ const EditorChrome = ({
|
|
|
4144
4543
|
}
|
|
4145
4544
|
),
|
|
4146
4545
|
/* @__PURE__ */ jsx(Toolbar, {}),
|
|
4147
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 overflow-hidden bg-gray-
|
|
4546
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 overflow-hidden bg-gray-200", children: [
|
|
4148
4547
|
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 overflow-auto", children: /* @__PURE__ */ jsx(DocumentView, {}) }),
|
|
4149
4548
|
sidePanels.map((Panel, idx) => /* @__PURE__ */ jsx(Panel, {}, idx)),
|
|
4150
4549
|
/* @__PURE__ */ jsx(HistorySidebar, {})
|