@yurikilian/lex4 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -3
- package/dist/components/DocumentView.d.ts.map +1 -1
- package/dist/components/HeaderFooterActions.d.ts.map +1 -1
- package/dist/components/HeaderFooterToggle.d.ts.map +1 -1
- package/dist/components/PageBody.d.ts.map +1 -1
- package/dist/components/PageFooter.d.ts.map +1 -1
- package/dist/components/PageHeader.d.ts.map +1 -1
- package/dist/components/PageView.d.ts.map +1 -1
- package/dist/components/Toolbar.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/index.d.ts +1 -0
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/pt-BR.d.ts +3 -0
- package/dist/i18n/pt-BR.d.ts.map +1 -0
- package/dist/i18n/types.d.ts +42 -0
- package/dist/i18n/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lex4-editor.cjs +1025 -444
- package/dist/lex4-editor.cjs.map +1 -1
- package/dist/lex4-editor.js +1028 -447
- package/dist/lex4-editor.js.map +1 -1
- package/dist/lexical/plugins/font-plugin.d.ts +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 +49 -28
- 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,
|
|
@@ -1134,20 +1384,33 @@ const createLucideIcon = (iconName, iconNode) => {
|
|
|
1134
1384
|
* This source code is licensed under the ISC license.
|
|
1135
1385
|
* See the LICENSE file in the root directory of this source tree.
|
|
1136
1386
|
*/
|
|
1137
|
-
const __iconNode$
|
|
1387
|
+
const __iconNode$q = [
|
|
1388
|
+
["path", { d: "m15 16 2.536-7.328a1.02 1.02 1 0 1 1.928 0L22 16", key: "xik6mr" }],
|
|
1389
|
+
["path", { d: "M15.697 14h5.606", key: "1stdlc" }],
|
|
1390
|
+
["path", { d: "m2 16 4.039-9.69a.5.5 0 0 1 .923 0L11 16", key: "d5nyq2" }],
|
|
1391
|
+
["path", { d: "M3.304 13h6.392", key: "1q3zxz" }]
|
|
1392
|
+
];
|
|
1393
|
+
const ALargeSmall = createLucideIcon("a-large-small", __iconNode$q);
|
|
1394
|
+
/**
|
|
1395
|
+
* @license lucide-react v1.8.0 - ISC
|
|
1396
|
+
*
|
|
1397
|
+
* This source code is licensed under the ISC license.
|
|
1398
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1399
|
+
*/
|
|
1400
|
+
const __iconNode$p = [
|
|
1138
1401
|
[
|
|
1139
1402
|
"path",
|
|
1140
1403
|
{ d: "M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8", key: "mg9rjx" }
|
|
1141
1404
|
]
|
|
1142
1405
|
];
|
|
1143
|
-
const Bold = createLucideIcon("bold", __iconNode$
|
|
1406
|
+
const Bold = createLucideIcon("bold", __iconNode$p);
|
|
1144
1407
|
/**
|
|
1145
1408
|
* @license lucide-react v1.8.0 - ISC
|
|
1146
1409
|
*
|
|
1147
1410
|
* This source code is licensed under the ISC license.
|
|
1148
1411
|
* See the LICENSE file in the root directory of this source tree.
|
|
1149
1412
|
*/
|
|
1150
|
-
const __iconNode$
|
|
1413
|
+
const __iconNode$o = [
|
|
1151
1414
|
[
|
|
1152
1415
|
"path",
|
|
1153
1416
|
{ d: "M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1", key: "ezmyqa" }
|
|
@@ -1160,27 +1423,35 @@ const __iconNode$l = [
|
|
|
1160
1423
|
}
|
|
1161
1424
|
]
|
|
1162
1425
|
];
|
|
1163
|
-
const Braces = createLucideIcon("braces", __iconNode$
|
|
1426
|
+
const Braces = createLucideIcon("braces", __iconNode$o);
|
|
1164
1427
|
/**
|
|
1165
1428
|
* @license lucide-react v1.8.0 - ISC
|
|
1166
1429
|
*
|
|
1167
1430
|
* This source code is licensed under the ISC license.
|
|
1168
1431
|
* See the LICENSE file in the root directory of this source tree.
|
|
1169
1432
|
*/
|
|
1170
|
-
const __iconNode$
|
|
1433
|
+
const __iconNode$n = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
|
|
1434
|
+
const ChevronDown = createLucideIcon("chevron-down", __iconNode$n);
|
|
1435
|
+
/**
|
|
1436
|
+
* @license lucide-react v1.8.0 - ISC
|
|
1437
|
+
*
|
|
1438
|
+
* This source code is licensed under the ISC license.
|
|
1439
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1440
|
+
*/
|
|
1441
|
+
const __iconNode$m = [
|
|
1171
1442
|
["line", { x1: "15", x2: "15", y1: "12", y2: "18", key: "1p7wdc" }],
|
|
1172
1443
|
["line", { x1: "12", x2: "18", y1: "15", y2: "15", key: "1nscbv" }],
|
|
1173
1444
|
["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2", key: "17jyea" }],
|
|
1174
1445
|
["path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2", key: "zix9uf" }]
|
|
1175
1446
|
];
|
|
1176
|
-
const CopyPlus = createLucideIcon("copy-plus", __iconNode$
|
|
1447
|
+
const CopyPlus = createLucideIcon("copy-plus", __iconNode$m);
|
|
1177
1448
|
/**
|
|
1178
1449
|
* @license lucide-react v1.8.0 - ISC
|
|
1179
1450
|
*
|
|
1180
1451
|
* This source code is licensed under the ISC license.
|
|
1181
1452
|
* See the LICENSE file in the root directory of this source tree.
|
|
1182
1453
|
*/
|
|
1183
|
-
const __iconNode$
|
|
1454
|
+
const __iconNode$l = [
|
|
1184
1455
|
[
|
|
1185
1456
|
"path",
|
|
1186
1457
|
{
|
|
@@ -1190,65 +1461,52 @@ const __iconNode$j = [
|
|
|
1190
1461
|
],
|
|
1191
1462
|
["path", { d: "m5.082 11.09 8.828 8.828", key: "1wx5vj" }]
|
|
1192
1463
|
];
|
|
1193
|
-
const Eraser = createLucideIcon("eraser", __iconNode$
|
|
1464
|
+
const Eraser = createLucideIcon("eraser", __iconNode$l);
|
|
1194
1465
|
/**
|
|
1195
1466
|
* @license lucide-react v1.8.0 - ISC
|
|
1196
1467
|
*
|
|
1197
1468
|
* This source code is licensed under the ISC license.
|
|
1198
1469
|
* See the LICENSE file in the root directory of this source tree.
|
|
1199
1470
|
*/
|
|
1200
|
-
const __iconNode$
|
|
1201
|
-
["line", { x1: "4", x2: "20", y1: "9", y2: "9", key: "4lhtct" }],
|
|
1202
|
-
["line", { x1: "4", x2: "20", y1: "15", y2: "15", key: "vyu0kd" }],
|
|
1203
|
-
["line", { x1: "10", x2: "8", y1: "3", y2: "21", key: "1ggp8o" }],
|
|
1204
|
-
["line", { x1: "16", x2: "14", y1: "3", y2: "21", key: "weycgp" }]
|
|
1205
|
-
];
|
|
1206
|
-
const Hash = createLucideIcon("hash", __iconNode$i);
|
|
1207
|
-
/**
|
|
1208
|
-
* @license lucide-react v1.8.0 - ISC
|
|
1209
|
-
*
|
|
1210
|
-
* This source code is licensed under the ISC license.
|
|
1211
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
1212
|
-
*/
|
|
1213
|
-
const __iconNode$h = [
|
|
1471
|
+
const __iconNode$k = [
|
|
1214
1472
|
["line", { x1: "19", x2: "10", y1: "4", y2: "4", key: "15jd3p" }],
|
|
1215
1473
|
["line", { x1: "14", x2: "5", y1: "20", y2: "20", key: "bu0au3" }],
|
|
1216
1474
|
["line", { x1: "15", x2: "9", y1: "4", y2: "20", key: "uljnxc" }]
|
|
1217
1475
|
];
|
|
1218
|
-
const Italic = createLucideIcon("italic", __iconNode$
|
|
1476
|
+
const Italic = createLucideIcon("italic", __iconNode$k);
|
|
1219
1477
|
/**
|
|
1220
1478
|
* @license lucide-react v1.8.0 - ISC
|
|
1221
1479
|
*
|
|
1222
1480
|
* This source code is licensed under the ISC license.
|
|
1223
1481
|
* See the LICENSE file in the root directory of this source tree.
|
|
1224
1482
|
*/
|
|
1225
|
-
const __iconNode$
|
|
1483
|
+
const __iconNode$j = [
|
|
1226
1484
|
["path", { d: "M21 5H11", key: "us1j55" }],
|
|
1227
1485
|
["path", { d: "M21 12H11", key: "wd7e0v" }],
|
|
1228
1486
|
["path", { d: "M21 19H11", key: "saa85w" }],
|
|
1229
1487
|
["path", { d: "m7 8-4 4 4 4", key: "o5hrat" }]
|
|
1230
1488
|
];
|
|
1231
|
-
const ListIndentDecrease = createLucideIcon("list-indent-decrease", __iconNode$
|
|
1489
|
+
const ListIndentDecrease = createLucideIcon("list-indent-decrease", __iconNode$j);
|
|
1232
1490
|
/**
|
|
1233
1491
|
* @license lucide-react v1.8.0 - ISC
|
|
1234
1492
|
*
|
|
1235
1493
|
* This source code is licensed under the ISC license.
|
|
1236
1494
|
* See the LICENSE file in the root directory of this source tree.
|
|
1237
1495
|
*/
|
|
1238
|
-
const __iconNode$
|
|
1496
|
+
const __iconNode$i = [
|
|
1239
1497
|
["path", { d: "M21 5H11", key: "us1j55" }],
|
|
1240
1498
|
["path", { d: "M21 12H11", key: "wd7e0v" }],
|
|
1241
1499
|
["path", { d: "M21 19H11", key: "saa85w" }],
|
|
1242
1500
|
["path", { d: "m3 8 4 4-4 4", key: "1a3j6y" }]
|
|
1243
1501
|
];
|
|
1244
|
-
const ListIndentIncrease = createLucideIcon("list-indent-increase", __iconNode$
|
|
1502
|
+
const ListIndentIncrease = createLucideIcon("list-indent-increase", __iconNode$i);
|
|
1245
1503
|
/**
|
|
1246
1504
|
* @license lucide-react v1.8.0 - ISC
|
|
1247
1505
|
*
|
|
1248
1506
|
* This source code is licensed under the ISC license.
|
|
1249
1507
|
* See the LICENSE file in the root directory of this source tree.
|
|
1250
1508
|
*/
|
|
1251
|
-
const __iconNode$
|
|
1509
|
+
const __iconNode$h = [
|
|
1252
1510
|
["path", { d: "M11 5h10", key: "1cz7ny" }],
|
|
1253
1511
|
["path", { d: "M11 12h10", key: "1438ji" }],
|
|
1254
1512
|
["path", { d: "M11 19h10", key: "11t30w" }],
|
|
@@ -1256,14 +1514,14 @@ const __iconNode$e = [
|
|
|
1256
1514
|
["path", { d: "M4 9h2", key: "r1h2o0" }],
|
|
1257
1515
|
["path", { d: "M6.5 20H3.4c0-1 2.6-1.925 2.6-3.5a1.5 1.5 0 0 0-2.6-1.02", key: "xtkcd5" }]
|
|
1258
1516
|
];
|
|
1259
|
-
const ListOrdered = createLucideIcon("list-ordered", __iconNode$
|
|
1517
|
+
const ListOrdered = createLucideIcon("list-ordered", __iconNode$h);
|
|
1260
1518
|
/**
|
|
1261
1519
|
* @license lucide-react v1.8.0 - ISC
|
|
1262
1520
|
*
|
|
1263
1521
|
* This source code is licensed under the ISC license.
|
|
1264
1522
|
* See the LICENSE file in the root directory of this source tree.
|
|
1265
1523
|
*/
|
|
1266
|
-
const __iconNode$
|
|
1524
|
+
const __iconNode$g = [
|
|
1267
1525
|
["path", { d: "M3 5h.01", key: "18ugdj" }],
|
|
1268
1526
|
["path", { d: "M3 12h.01", key: "nlz23k" }],
|
|
1269
1527
|
["path", { d: "M3 19h.01", key: "noohij" }],
|
|
@@ -1271,127 +1529,168 @@ const __iconNode$d = [
|
|
|
1271
1529
|
["path", { d: "M8 12h13", key: "1za7za" }],
|
|
1272
1530
|
["path", { d: "M8 19h13", key: "m83p4d" }]
|
|
1273
1531
|
];
|
|
1274
|
-
const List = createLucideIcon("list", __iconNode$
|
|
1532
|
+
const List = createLucideIcon("list", __iconNode$g);
|
|
1275
1533
|
/**
|
|
1276
1534
|
* @license lucide-react v1.8.0 - ISC
|
|
1277
1535
|
*
|
|
1278
1536
|
* This source code is licensed under the ISC license.
|
|
1279
1537
|
* See the LICENSE file in the root directory of this source tree.
|
|
1280
1538
|
*/
|
|
1281
|
-
const __iconNode$
|
|
1539
|
+
const __iconNode$f = [
|
|
1282
1540
|
["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
|
|
1283
1541
|
["path", { d: "M15 3v18", key: "14nvp0" }]
|
|
1284
1542
|
];
|
|
1285
|
-
const PanelRight = createLucideIcon("panel-right", __iconNode$
|
|
1543
|
+
const PanelRight = createLucideIcon("panel-right", __iconNode$f);
|
|
1286
1544
|
/**
|
|
1287
1545
|
* @license lucide-react v1.8.0 - ISC
|
|
1288
1546
|
*
|
|
1289
1547
|
* This source code is licensed under the ISC license.
|
|
1290
1548
|
* See the LICENSE file in the root directory of this source tree.
|
|
1291
1549
|
*/
|
|
1292
|
-
const __iconNode$
|
|
1550
|
+
const __iconNode$e = [
|
|
1293
1551
|
["path", { d: "m15 14 5-5-5-5", key: "12vg1m" }],
|
|
1294
1552
|
["path", { d: "M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13", key: "6uklza" }]
|
|
1295
1553
|
];
|
|
1296
|
-
const Redo2 = createLucideIcon("redo-2", __iconNode$
|
|
1554
|
+
const Redo2 = createLucideIcon("redo-2", __iconNode$e);
|
|
1297
1555
|
/**
|
|
1298
1556
|
* @license lucide-react v1.8.0 - ISC
|
|
1299
1557
|
*
|
|
1300
1558
|
* This source code is licensed under the ISC license.
|
|
1301
1559
|
* See the LICENSE file in the root directory of this source tree.
|
|
1302
1560
|
*/
|
|
1303
|
-
const __iconNode$
|
|
1561
|
+
const __iconNode$d = [
|
|
1304
1562
|
["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
|
|
1305
1563
|
["path", { d: "M21 3v5h-5", key: "1q7to0" }],
|
|
1306
1564
|
["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
|
|
1307
1565
|
["path", { d: "M8 16H3v5", key: "1cv678" }]
|
|
1308
1566
|
];
|
|
1309
|
-
const RefreshCw = createLucideIcon("refresh-cw", __iconNode$
|
|
1567
|
+
const RefreshCw = createLucideIcon("refresh-cw", __iconNode$d);
|
|
1310
1568
|
/**
|
|
1311
1569
|
* @license lucide-react v1.8.0 - ISC
|
|
1312
1570
|
*
|
|
1313
1571
|
* This source code is licensed under the ISC license.
|
|
1314
1572
|
* See the LICENSE file in the root directory of this source tree.
|
|
1315
1573
|
*/
|
|
1316
|
-
const __iconNode$
|
|
1574
|
+
const __iconNode$c = [
|
|
1575
|
+
["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
|
|
1576
|
+
["path", { d: "M21 9H3", key: "1338ky" }],
|
|
1577
|
+
["path", { d: "M21 15H3", key: "9uk58r" }]
|
|
1578
|
+
];
|
|
1579
|
+
const Rows3 = createLucideIcon("rows-3", __iconNode$c);
|
|
1580
|
+
/**
|
|
1581
|
+
* @license lucide-react v1.8.0 - ISC
|
|
1582
|
+
*
|
|
1583
|
+
* This source code is licensed under the ISC license.
|
|
1584
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1585
|
+
*/
|
|
1586
|
+
const __iconNode$b = [
|
|
1317
1587
|
["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
|
|
1318
1588
|
["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
|
|
1319
1589
|
];
|
|
1320
|
-
const Search = createLucideIcon("search", __iconNode$
|
|
1590
|
+
const Search = createLucideIcon("search", __iconNode$b);
|
|
1321
1591
|
/**
|
|
1322
1592
|
* @license lucide-react v1.8.0 - ISC
|
|
1323
1593
|
*
|
|
1324
1594
|
* This source code is licensed under the ISC license.
|
|
1325
1595
|
* See the LICENSE file in the root directory of this source tree.
|
|
1326
1596
|
*/
|
|
1327
|
-
const __iconNode$
|
|
1597
|
+
const __iconNode$a = [
|
|
1598
|
+
[
|
|
1599
|
+
"path",
|
|
1600
|
+
{
|
|
1601
|
+
d: "M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915",
|
|
1602
|
+
key: "1i5ecw"
|
|
1603
|
+
}
|
|
1604
|
+
],
|
|
1605
|
+
["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
|
|
1606
|
+
];
|
|
1607
|
+
const Settings = createLucideIcon("settings", __iconNode$a);
|
|
1608
|
+
/**
|
|
1609
|
+
* @license lucide-react v1.8.0 - ISC
|
|
1610
|
+
*
|
|
1611
|
+
* This source code is licensed under the ISC license.
|
|
1612
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1613
|
+
*/
|
|
1614
|
+
const __iconNode$9 = [
|
|
1328
1615
|
["path", { d: "M16 4H9a3 3 0 0 0-2.83 4", key: "43sutm" }],
|
|
1329
1616
|
["path", { d: "M14 12a4 4 0 0 1 0 8H6", key: "nlfj13" }],
|
|
1330
1617
|
["line", { x1: "4", x2: "20", y1: "12", y2: "12", key: "1e0a9i" }]
|
|
1331
1618
|
];
|
|
1332
|
-
const Strikethrough = createLucideIcon("strikethrough", __iconNode$
|
|
1619
|
+
const Strikethrough = createLucideIcon("strikethrough", __iconNode$9);
|
|
1333
1620
|
/**
|
|
1334
1621
|
* @license lucide-react v1.8.0 - ISC
|
|
1335
1622
|
*
|
|
1336
1623
|
* This source code is licensed under the ISC license.
|
|
1337
1624
|
* See the LICENSE file in the root directory of this source tree.
|
|
1338
1625
|
*/
|
|
1339
|
-
const __iconNode$
|
|
1626
|
+
const __iconNode$8 = [
|
|
1340
1627
|
["path", { d: "M21 5H3", key: "1fi0y6" }],
|
|
1341
1628
|
["path", { d: "M17 12H7", key: "16if0g" }],
|
|
1342
1629
|
["path", { d: "M19 19H5", key: "vjpgq2" }]
|
|
1343
1630
|
];
|
|
1344
|
-
const TextAlignCenter = createLucideIcon("text-align-center", __iconNode$
|
|
1631
|
+
const TextAlignCenter = createLucideIcon("text-align-center", __iconNode$8);
|
|
1345
1632
|
/**
|
|
1346
1633
|
* @license lucide-react v1.8.0 - ISC
|
|
1347
1634
|
*
|
|
1348
1635
|
* This source code is licensed under the ISC license.
|
|
1349
1636
|
* See the LICENSE file in the root directory of this source tree.
|
|
1350
1637
|
*/
|
|
1351
|
-
const __iconNode$
|
|
1638
|
+
const __iconNode$7 = [
|
|
1352
1639
|
["path", { d: "M21 5H3", key: "1fi0y6" }],
|
|
1353
1640
|
["path", { d: "M21 12H9", key: "dn1m92" }],
|
|
1354
1641
|
["path", { d: "M21 19H7", key: "4cu937" }]
|
|
1355
1642
|
];
|
|
1356
|
-
const TextAlignEnd = createLucideIcon("text-align-end", __iconNode$
|
|
1643
|
+
const TextAlignEnd = createLucideIcon("text-align-end", __iconNode$7);
|
|
1357
1644
|
/**
|
|
1358
1645
|
* @license lucide-react v1.8.0 - ISC
|
|
1359
1646
|
*
|
|
1360
1647
|
* This source code is licensed under the ISC license.
|
|
1361
1648
|
* See the LICENSE file in the root directory of this source tree.
|
|
1362
1649
|
*/
|
|
1363
|
-
const __iconNode$
|
|
1650
|
+
const __iconNode$6 = [
|
|
1364
1651
|
["path", { d: "M3 5h18", key: "1u36vt" }],
|
|
1365
1652
|
["path", { d: "M3 12h18", key: "1i2n21" }],
|
|
1366
1653
|
["path", { d: "M3 19h18", key: "awlh7x" }]
|
|
1367
1654
|
];
|
|
1368
|
-
const TextAlignJustify = createLucideIcon("text-align-justify", __iconNode$
|
|
1655
|
+
const TextAlignJustify = createLucideIcon("text-align-justify", __iconNode$6);
|
|
1369
1656
|
/**
|
|
1370
1657
|
* @license lucide-react v1.8.0 - ISC
|
|
1371
1658
|
*
|
|
1372
1659
|
* This source code is licensed under the ISC license.
|
|
1373
1660
|
* See the LICENSE file in the root directory of this source tree.
|
|
1374
1661
|
*/
|
|
1375
|
-
const __iconNode$
|
|
1662
|
+
const __iconNode$5 = [
|
|
1376
1663
|
["path", { d: "M21 5H3", key: "1fi0y6" }],
|
|
1377
1664
|
["path", { d: "M15 12H3", key: "6jk70r" }],
|
|
1378
1665
|
["path", { d: "M17 19H3", key: "z6ezky" }]
|
|
1379
1666
|
];
|
|
1380
|
-
const TextAlignStart = createLucideIcon("text-align-start", __iconNode$
|
|
1667
|
+
const TextAlignStart = createLucideIcon("text-align-start", __iconNode$5);
|
|
1381
1668
|
/**
|
|
1382
1669
|
* @license lucide-react v1.8.0 - ISC
|
|
1383
1670
|
*
|
|
1384
1671
|
* This source code is licensed under the ISC license.
|
|
1385
1672
|
* See the LICENSE file in the root directory of this source tree.
|
|
1386
1673
|
*/
|
|
1387
|
-
const __iconNode$
|
|
1674
|
+
const __iconNode$4 = [
|
|
1388
1675
|
["path", { d: "M10 11v6", key: "nco0om" }],
|
|
1389
1676
|
["path", { d: "M14 11v6", key: "outv1u" }],
|
|
1390
1677
|
["path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6", key: "miytrc" }],
|
|
1391
1678
|
["path", { d: "M3 6h18", key: "d0wm0j" }],
|
|
1392
1679
|
["path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2", key: "e791ji" }]
|
|
1393
1680
|
];
|
|
1394
|
-
const Trash2 = createLucideIcon("trash-2", __iconNode$
|
|
1681
|
+
const Trash2 = createLucideIcon("trash-2", __iconNode$4);
|
|
1682
|
+
/**
|
|
1683
|
+
* @license lucide-react v1.8.0 - ISC
|
|
1684
|
+
*
|
|
1685
|
+
* This source code is licensed under the ISC license.
|
|
1686
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1687
|
+
*/
|
|
1688
|
+
const __iconNode$3 = [
|
|
1689
|
+
["path", { d: "M12 4v16", key: "1654pz" }],
|
|
1690
|
+
["path", { d: "M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2", key: "e0r10z" }],
|
|
1691
|
+
["path", { d: "M9 20h6", key: "s66wpe" }]
|
|
1692
|
+
];
|
|
1693
|
+
const Type = createLucideIcon("type", __iconNode$3);
|
|
1395
1694
|
/**
|
|
1396
1695
|
* @license lucide-react v1.8.0 - ISC
|
|
1397
1696
|
*
|
|
@@ -1414,123 +1713,17 @@ const __iconNode$1 = [
|
|
|
1414
1713
|
["path", { d: "M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11", key: "f3b9sd" }]
|
|
1415
1714
|
];
|
|
1416
1715
|
const Undo2 = createLucideIcon("undo-2", __iconNode$1);
|
|
1417
|
-
/**
|
|
1418
|
-
* @license lucide-react v1.8.0 - ISC
|
|
1419
|
-
*
|
|
1420
|
-
* This source code is licensed under the ISC license.
|
|
1421
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
1422
|
-
*/
|
|
1423
|
-
const __iconNode = [
|
|
1424
|
-
["path", { d: "M18 6 6 18", key: "1bl5f8" }],
|
|
1425
|
-
["path", { d: "m6 6 12 12", key: "d8bk6v" }]
|
|
1426
|
-
];
|
|
1427
|
-
const X = createLucideIcon("x", __iconNode);
|
|
1428
|
-
const DEFAULT_TRANSLATIONS = {
|
|
1429
|
-
toolbar: {
|
|
1430
|
-
undo: "Undo",
|
|
1431
|
-
redo: "Redo",
|
|
1432
|
-
bold: "Bold (Ctrl+B)",
|
|
1433
|
-
italic: "Italic (Ctrl+I)",
|
|
1434
|
-
underline: "Underline (Ctrl+U)",
|
|
1435
|
-
strikethrough: "Strikethrough",
|
|
1436
|
-
alignLeft: "Align Left",
|
|
1437
|
-
alignCenter: "Align Center",
|
|
1438
|
-
alignRight: "Align Right",
|
|
1439
|
-
justify: "Justify",
|
|
1440
|
-
numberedList: "Numbered List",
|
|
1441
|
-
bulletList: "Bullet List",
|
|
1442
|
-
indent: "Indent",
|
|
1443
|
-
outdent: "Outdent",
|
|
1444
|
-
openHistory: "Open History",
|
|
1445
|
-
closeHistory: "Close History"
|
|
1446
|
-
},
|
|
1447
|
-
history: {
|
|
1448
|
-
title: "History",
|
|
1449
|
-
subtitle: "Word-style session history (last 100 actions)",
|
|
1450
|
-
empty: "No history yet.",
|
|
1451
|
-
clearHistory: "Clear History",
|
|
1452
|
-
actions: {
|
|
1453
|
-
enabledHeadersFooters: "Enabled headers and footers",
|
|
1454
|
-
disabledHeadersFooters: "Disabled headers and footers",
|
|
1455
|
-
copiedHeaderToAll: "Copied header to all pages",
|
|
1456
|
-
copiedFooterToAll: "Copied footer to all pages",
|
|
1457
|
-
clearedHeader: "Cleared header",
|
|
1458
|
-
clearedFooter: "Cleared footer",
|
|
1459
|
-
clearedAllHeaders: "Cleared all headers",
|
|
1460
|
-
clearedAllFooters: "Cleared all footers",
|
|
1461
|
-
pageCounterSet: "Page counter set to {{value}}",
|
|
1462
|
-
boldApplied: "Bold applied",
|
|
1463
|
-
italicApplied: "Italic applied",
|
|
1464
|
-
underlineApplied: "Underline applied",
|
|
1465
|
-
strikethroughApplied: "Strikethrough applied",
|
|
1466
|
-
alignedLeft: "Aligned left",
|
|
1467
|
-
alignedCenter: "Aligned center",
|
|
1468
|
-
alignedRight: "Aligned right",
|
|
1469
|
-
justifiedText: "Justified text",
|
|
1470
|
-
insertedNumberedList: "Inserted numbered list",
|
|
1471
|
-
insertedBulletList: "Inserted bullet list",
|
|
1472
|
-
indentedContent: "Indented content",
|
|
1473
|
-
outdentedContent: "Outdented content",
|
|
1474
|
-
fontChanged: "Font changed to {{value}}",
|
|
1475
|
-
fontSizeChanged: "Font size changed to {{value}}pt"
|
|
1476
|
-
}
|
|
1477
|
-
},
|
|
1478
|
-
variables: {
|
|
1479
|
-
title: "Variables",
|
|
1480
|
-
available: "{{count}} available",
|
|
1481
|
-
refreshVariables: "Refresh variables",
|
|
1482
|
-
searchPlaceholder: "Search variables...",
|
|
1483
|
-
noVariablesFound: "No variables found",
|
|
1484
|
-
insertVariable: "Insert variable {{key}}",
|
|
1485
|
-
openPanel: "Open Variables",
|
|
1486
|
-
closePanel: "Close Variables"
|
|
1487
|
-
},
|
|
1488
|
-
header: {
|
|
1489
|
-
placeholder: "Header"
|
|
1490
|
-
},
|
|
1491
|
-
footer: {
|
|
1492
|
-
placeholder: "Footer"
|
|
1493
|
-
},
|
|
1494
|
-
sidebar: {
|
|
1495
|
-
close: "Close sidebar"
|
|
1496
|
-
}
|
|
1497
|
-
};
|
|
1498
|
-
function deepMerge(target, source) {
|
|
1499
|
-
if (typeof target !== "object" || target === null) {
|
|
1500
|
-
return source ?? target;
|
|
1501
|
-
}
|
|
1502
|
-
const result = { ...target };
|
|
1503
|
-
for (const key of Object.keys(source)) {
|
|
1504
|
-
const sourceVal = source[key];
|
|
1505
|
-
const targetVal = target[key];
|
|
1506
|
-
if (sourceVal !== void 0 && typeof sourceVal === "object" && sourceVal !== null && !Array.isArray(sourceVal) && typeof targetVal === "object" && targetVal !== null) {
|
|
1507
|
-
result[key] = deepMerge(targetVal, sourceVal);
|
|
1508
|
-
} else if (sourceVal !== void 0) {
|
|
1509
|
-
result[key] = sourceVal;
|
|
1510
|
-
}
|
|
1511
|
-
}
|
|
1512
|
-
return result;
|
|
1513
|
-
}
|
|
1514
|
-
const TranslationsContext = createContext(DEFAULT_TRANSLATIONS);
|
|
1515
|
-
function useTranslations() {
|
|
1516
|
-
return useContext(TranslationsContext);
|
|
1517
|
-
}
|
|
1518
|
-
function interpolate(template, params) {
|
|
1519
|
-
return template.replace(
|
|
1520
|
-
/\{\{(\w+)\}\}/g,
|
|
1521
|
-
(_, key) => String(params[key] ?? `{{${key}}}`)
|
|
1522
|
-
);
|
|
1523
|
-
}
|
|
1524
|
-
const TranslationsProvider = ({
|
|
1525
|
-
translations,
|
|
1526
|
-
children
|
|
1527
|
-
}) => {
|
|
1528
|
-
const merged = useMemo(
|
|
1529
|
-
() => translations ? deepMerge(DEFAULT_TRANSLATIONS, translations) : DEFAULT_TRANSLATIONS,
|
|
1530
|
-
[translations]
|
|
1531
|
-
);
|
|
1532
|
-
return /* @__PURE__ */ jsx(TranslationsContext.Provider, { value: merged, children });
|
|
1533
|
-
};
|
|
1716
|
+
/**
|
|
1717
|
+
* @license lucide-react v1.8.0 - ISC
|
|
1718
|
+
*
|
|
1719
|
+
* This source code is licensed under the ISC license.
|
|
1720
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1721
|
+
*/
|
|
1722
|
+
const __iconNode = [
|
|
1723
|
+
["path", { d: "M18 6 6 18", key: "1bl5f8" }],
|
|
1724
|
+
["path", { d: "m6 6 12 12", key: "d8bk6v" }]
|
|
1725
|
+
];
|
|
1726
|
+
const X = createLucideIcon("x", __iconNode);
|
|
1534
1727
|
const EditorSidebar = ({
|
|
1535
1728
|
title,
|
|
1536
1729
|
subtitle,
|
|
@@ -1637,7 +1830,7 @@ const HistorySidebar = () => {
|
|
|
1637
1830
|
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
1638
1831
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
1639
1832
|
/* @__PURE__ */ jsx("div", { className: `text-xs ${isCurrent ? "font-semibold text-blue-700" : "text-gray-900"}`, children: entry.label }),
|
|
1640
|
-
/* @__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 })
|
|
1641
1834
|
] }),
|
|
1642
1835
|
/* @__PURE__ */ jsx("div", { className: "shrink-0 text-xs text-gray-400", children: formatTimestamp(entry.timestamp) })
|
|
1643
1836
|
] })
|
|
@@ -1651,13 +1844,15 @@ const HeaderFooterToggle = ({
|
|
|
1651
1844
|
enabled,
|
|
1652
1845
|
onToggle
|
|
1653
1846
|
}) => {
|
|
1847
|
+
const t = useTranslations();
|
|
1654
1848
|
return /* @__PURE__ */ jsxs(
|
|
1655
1849
|
"label",
|
|
1656
1850
|
{
|
|
1657
1851
|
className: "flex items-center gap-1.5 cursor-pointer select-none",
|
|
1658
1852
|
"data-testid": "header-footer-toggle",
|
|
1659
1853
|
children: [
|
|
1660
|
-
/* @__PURE__ */ jsx(
|
|
1854
|
+
/* @__PURE__ */ jsx(Rows3, { size: 14, className: "text-gray-500" }),
|
|
1855
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-600", children: t.headerFooter.label }),
|
|
1661
1856
|
/* @__PURE__ */ jsx(
|
|
1662
1857
|
"button",
|
|
1663
1858
|
{
|
|
@@ -1688,6 +1883,12 @@ const HeaderFooterToggle = ({
|
|
|
1688
1883
|
}
|
|
1689
1884
|
);
|
|
1690
1885
|
};
|
|
1886
|
+
const PAGE_COUNTER_OPTIONS = [
|
|
1887
|
+
{ value: "none", label: "None" },
|
|
1888
|
+
{ value: "header", label: "Header" },
|
|
1889
|
+
{ value: "footer", label: "Footer" },
|
|
1890
|
+
{ value: "both", label: "Both" }
|
|
1891
|
+
];
|
|
1691
1892
|
const HeaderFooterActions = ({
|
|
1692
1893
|
activePageId,
|
|
1693
1894
|
pageCounterMode,
|
|
@@ -1699,119 +1900,154 @@ const HeaderFooterActions = ({
|
|
|
1699
1900
|
onClearAllHeaders,
|
|
1700
1901
|
onClearAllFooters
|
|
1701
1902
|
}) => {
|
|
1903
|
+
const [open, setOpen] = useState(false);
|
|
1904
|
+
const containerRef = useRef(null);
|
|
1702
1905
|
const hasActivePage = activePageId !== null;
|
|
1703
|
-
const
|
|
1704
|
-
|
|
1705
|
-
if (
|
|
1706
|
-
|
|
1707
|
-
|
|
1906
|
+
const close = useCallback(() => setOpen(false), []);
|
|
1907
|
+
useEffect(() => {
|
|
1908
|
+
if (!open) return;
|
|
1909
|
+
const handleClickOutside = (e) => {
|
|
1910
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
1911
|
+
close();
|
|
1912
|
+
}
|
|
1913
|
+
};
|
|
1914
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1915
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1916
|
+
}, [open, close]);
|
|
1917
|
+
const handleAction = (action) => {
|
|
1918
|
+
action();
|
|
1919
|
+
close();
|
|
1708
1920
|
};
|
|
1709
|
-
return /* @__PURE__ */ jsxs(
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1921
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "relative", "data-testid": "header-footer-actions", children: [
|
|
1922
|
+
/* @__PURE__ */ jsxs(
|
|
1923
|
+
"button",
|
|
1924
|
+
{
|
|
1925
|
+
type: "button",
|
|
1926
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
1927
|
+
onClick: () => setOpen(!open),
|
|
1928
|
+
className: `
|
|
1929
|
+
flex h-7 items-center gap-1 rounded px-1.5 text-xs transition-colors
|
|
1930
|
+
${open ? "bg-blue-50 text-blue-600" : "text-gray-600 hover:bg-gray-100 hover:text-gray-900"}
|
|
1931
|
+
`,
|
|
1932
|
+
"data-testid": "header-footer-menu-trigger",
|
|
1933
|
+
"aria-expanded": open,
|
|
1934
|
+
"aria-haspopup": "true",
|
|
1935
|
+
children: [
|
|
1936
|
+
/* @__PURE__ */ jsx(Settings, { size: 14 }),
|
|
1937
|
+
/* @__PURE__ */ jsx(ChevronDown, { size: 12 })
|
|
1938
|
+
]
|
|
1939
|
+
}
|
|
1940
|
+
),
|
|
1941
|
+
open && /* @__PURE__ */ jsxs(
|
|
1942
|
+
"div",
|
|
1943
|
+
{
|
|
1944
|
+
className: "absolute left-0 top-full mt-1 z-50 w-56 rounded-lg border border-gray-200 bg-white py-1 shadow-lg",
|
|
1945
|
+
role: "menu",
|
|
1946
|
+
"data-testid": "header-footer-menu",
|
|
1947
|
+
children: [
|
|
1948
|
+
/* @__PURE__ */ jsx(SectionLabel, { children: "Page counter" }),
|
|
1949
|
+
/* @__PURE__ */ jsx("div", { className: "px-3 pb-2 grid grid-cols-2 gap-1", "data-testid": "page-counter-mode", children: PAGE_COUNTER_OPTIONS.map(({ value, label }) => /* @__PURE__ */ jsx(
|
|
1950
|
+
"button",
|
|
1719
1951
|
{
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
"
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1952
|
+
type: "button",
|
|
1953
|
+
role: "menuitemradio",
|
|
1954
|
+
"aria-checked": pageCounterMode === value,
|
|
1955
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
1956
|
+
onClick: () => onPageCounterModeChange(value),
|
|
1957
|
+
className: `
|
|
1958
|
+
rounded px-2 py-1 text-xs text-left transition-colors
|
|
1959
|
+
${pageCounterMode === value ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-600 hover:bg-gray-100"}
|
|
1960
|
+
`,
|
|
1961
|
+
"data-testid": `page-counter-${value}`,
|
|
1962
|
+
children: label
|
|
1963
|
+
},
|
|
1964
|
+
value
|
|
1965
|
+
)) }),
|
|
1966
|
+
/* @__PURE__ */ jsx(MenuDivider, {}),
|
|
1967
|
+
/* @__PURE__ */ jsx(SectionLabel, { children: "Header" }),
|
|
1968
|
+
/* @__PURE__ */ jsx(
|
|
1969
|
+
MenuItem,
|
|
1970
|
+
{
|
|
1971
|
+
icon: /* @__PURE__ */ jsx(CopyPlus, { size: 14 }),
|
|
1972
|
+
label: "Copy to all pages",
|
|
1973
|
+
onClick: () => handleAction(onCopyHeaderToAll),
|
|
1974
|
+
disabled: !hasActivePage,
|
|
1975
|
+
testId: "copy-header-all"
|
|
1976
|
+
}
|
|
1977
|
+
),
|
|
1978
|
+
/* @__PURE__ */ jsx(
|
|
1979
|
+
MenuItem,
|
|
1980
|
+
{
|
|
1981
|
+
icon: /* @__PURE__ */ jsx(Eraser, { size: 14 }),
|
|
1982
|
+
label: "Clear this page",
|
|
1983
|
+
onClick: () => handleAction(onClearHeader),
|
|
1984
|
+
disabled: !hasActivePage,
|
|
1985
|
+
testId: "clear-header"
|
|
1986
|
+
}
|
|
1987
|
+
),
|
|
1988
|
+
/* @__PURE__ */ jsx(
|
|
1989
|
+
MenuItem,
|
|
1990
|
+
{
|
|
1991
|
+
icon: /* @__PURE__ */ jsx(Trash2, { size: 14 }),
|
|
1992
|
+
label: "Clear all",
|
|
1993
|
+
onClick: () => handleAction(onClearAllHeaders),
|
|
1994
|
+
testId: "clear-all-headers"
|
|
1995
|
+
}
|
|
1996
|
+
),
|
|
1997
|
+
/* @__PURE__ */ jsx(MenuDivider, {}),
|
|
1998
|
+
/* @__PURE__ */ jsx(SectionLabel, { children: "Footer" }),
|
|
1999
|
+
/* @__PURE__ */ jsx(
|
|
2000
|
+
MenuItem,
|
|
2001
|
+
{
|
|
2002
|
+
icon: /* @__PURE__ */ jsx(CopyPlus, { size: 14 }),
|
|
2003
|
+
label: "Copy to all pages",
|
|
2004
|
+
onClick: () => handleAction(onCopyFooterToAll),
|
|
2005
|
+
disabled: !hasActivePage,
|
|
2006
|
+
testId: "copy-footer-all"
|
|
2007
|
+
}
|
|
2008
|
+
),
|
|
2009
|
+
/* @__PURE__ */ jsx(
|
|
2010
|
+
MenuItem,
|
|
2011
|
+
{
|
|
2012
|
+
icon: /* @__PURE__ */ jsx(Eraser, { size: 14 }),
|
|
2013
|
+
label: "Clear this page",
|
|
2014
|
+
onClick: () => handleAction(onClearFooter),
|
|
2015
|
+
disabled: !hasActivePage,
|
|
2016
|
+
testId: "clear-footer"
|
|
2017
|
+
}
|
|
2018
|
+
),
|
|
2019
|
+
/* @__PURE__ */ jsx(
|
|
2020
|
+
MenuItem,
|
|
2021
|
+
{
|
|
2022
|
+
icon: /* @__PURE__ */ jsx(Trash2, { size: 14 }),
|
|
2023
|
+
label: "Clear all",
|
|
2024
|
+
onClick: () => handleAction(onClearAllFooters),
|
|
2025
|
+
testId: "clear-all-footers"
|
|
1731
2026
|
}
|
|
1732
2027
|
)
|
|
1733
|
-
]
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
ActionIconButton,
|
|
1738
|
-
{
|
|
1739
|
-
title: "Copy header to all pages",
|
|
1740
|
-
icon: /* @__PURE__ */ jsx(CopyPlus, { size: 13 }),
|
|
1741
|
-
onClick: onCopyHeaderToAll,
|
|
1742
|
-
disabled: !hasActivePage,
|
|
1743
|
-
testId: "copy-header-all"
|
|
1744
|
-
}
|
|
1745
|
-
),
|
|
1746
|
-
/* @__PURE__ */ jsx(
|
|
1747
|
-
ActionIconButton,
|
|
1748
|
-
{
|
|
1749
|
-
title: "Clear header on this page",
|
|
1750
|
-
icon: /* @__PURE__ */ jsx(Eraser, { size: 13 }),
|
|
1751
|
-
onClick: onClearHeader,
|
|
1752
|
-
disabled: !hasActivePage,
|
|
1753
|
-
testId: "clear-header"
|
|
1754
|
-
}
|
|
1755
|
-
),
|
|
1756
|
-
/* @__PURE__ */ jsx(
|
|
1757
|
-
ActionIconButton,
|
|
1758
|
-
{
|
|
1759
|
-
title: "Clear all headers",
|
|
1760
|
-
icon: /* @__PURE__ */ jsx(Trash2, { size: 13 }),
|
|
1761
|
-
onClick: onClearAllHeaders,
|
|
1762
|
-
testId: "clear-all-headers"
|
|
1763
|
-
}
|
|
1764
|
-
),
|
|
1765
|
-
/* @__PURE__ */ jsx(ActionDivider, {}),
|
|
1766
|
-
/* @__PURE__ */ jsx("span", { className: "text-gray-400 font-medium", children: "Footer" }),
|
|
1767
|
-
/* @__PURE__ */ jsx(
|
|
1768
|
-
ActionIconButton,
|
|
1769
|
-
{
|
|
1770
|
-
title: "Copy footer to all pages",
|
|
1771
|
-
icon: /* @__PURE__ */ jsx(CopyPlus, { size: 13 }),
|
|
1772
|
-
onClick: onCopyFooterToAll,
|
|
1773
|
-
disabled: !hasActivePage,
|
|
1774
|
-
testId: "copy-footer-all"
|
|
1775
|
-
}
|
|
1776
|
-
),
|
|
1777
|
-
/* @__PURE__ */ jsx(
|
|
1778
|
-
ActionIconButton,
|
|
1779
|
-
{
|
|
1780
|
-
title: "Clear footer on this page",
|
|
1781
|
-
icon: /* @__PURE__ */ jsx(Eraser, { size: 13 }),
|
|
1782
|
-
onClick: onClearFooter,
|
|
1783
|
-
disabled: !hasActivePage,
|
|
1784
|
-
testId: "clear-footer"
|
|
1785
|
-
}
|
|
1786
|
-
),
|
|
1787
|
-
/* @__PURE__ */ jsx(
|
|
1788
|
-
ActionIconButton,
|
|
1789
|
-
{
|
|
1790
|
-
title: "Clear all footers",
|
|
1791
|
-
icon: /* @__PURE__ */ jsx(Trash2, { size: 13 }),
|
|
1792
|
-
onClick: onClearAllFooters,
|
|
1793
|
-
testId: "clear-all-footers"
|
|
1794
|
-
}
|
|
1795
|
-
)
|
|
1796
|
-
]
|
|
1797
|
-
}
|
|
1798
|
-
);
|
|
2028
|
+
]
|
|
2029
|
+
}
|
|
2030
|
+
)
|
|
2031
|
+
] });
|
|
1799
2032
|
};
|
|
1800
|
-
const
|
|
2033
|
+
const SectionLabel = ({ children }) => /* @__PURE__ */ jsx("div", { className: "px-3 pt-2 pb-1 text-[10px] font-semibold uppercase tracking-wider text-gray-400", children });
|
|
2034
|
+
const MenuItem = ({ icon, label, onClick, disabled, testId }) => /* @__PURE__ */ jsxs(
|
|
1801
2035
|
"button",
|
|
1802
2036
|
{
|
|
1803
2037
|
type: "button",
|
|
1804
|
-
|
|
1805
|
-
"aria-label": title,
|
|
2038
|
+
role: "menuitem",
|
|
1806
2039
|
onMouseDown: (e) => e.preventDefault(),
|
|
1807
2040
|
onClick,
|
|
1808
2041
|
disabled,
|
|
1809
|
-
className: "flex
|
|
2042
|
+
className: "flex w-full items-center gap-2 px-3 py-1.5 text-xs text-gray-700 transition-colors\n hover:bg-gray-50 disabled:cursor-not-allowed disabled:text-gray-300",
|
|
1810
2043
|
"data-testid": testId,
|
|
1811
|
-
children:
|
|
2044
|
+
children: [
|
|
2045
|
+
icon,
|
|
2046
|
+
label
|
|
2047
|
+
]
|
|
1812
2048
|
}
|
|
1813
2049
|
);
|
|
1814
|
-
const
|
|
2050
|
+
const MenuDivider = () => /* @__PURE__ */ jsx("div", { className: "my-1 h-px bg-gray-100" });
|
|
1815
2051
|
function resolveExtensions(extensions) {
|
|
1816
2052
|
const resolved = {
|
|
1817
2053
|
nodes: [],
|
|
@@ -1886,10 +2122,10 @@ function useExtensionContext(getDocument, getActiveEditor) {
|
|
|
1886
2122
|
}), [getDocument, getActiveEditor, stateRef]);
|
|
1887
2123
|
}
|
|
1888
2124
|
const SUPPORTED_FONTS = [
|
|
2125
|
+
"Calibri",
|
|
1889
2126
|
"Inter",
|
|
1890
2127
|
"Times New Roman",
|
|
1891
2128
|
"Arial",
|
|
1892
|
-
"Calibri",
|
|
1893
2129
|
"Georgia",
|
|
1894
2130
|
"Courier New"
|
|
1895
2131
|
];
|
|
@@ -2153,87 +2389,107 @@ const Toolbar = () => {
|
|
|
2153
2389
|
},
|
|
2154
2390
|
[applyToBodyEditors, runToolbarAction, t.history.actions.fontSizeChanged]
|
|
2155
2391
|
);
|
|
2156
|
-
return /* @__PURE__ */
|
|
2392
|
+
return /* @__PURE__ */ jsxs(
|
|
2157
2393
|
"div",
|
|
2158
2394
|
{
|
|
2159
2395
|
className: "lex4-toolbar sticky top-0 z-10 bg-white border-b border-gray-200",
|
|
2160
2396
|
"data-testid": "toolbar",
|
|
2161
|
-
children:
|
|
2162
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-
|
|
2163
|
-
/* @__PURE__ */
|
|
2397
|
+
children: [
|
|
2398
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5", children: [
|
|
2399
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "history-controls", children: [
|
|
2400
|
+
/* @__PURE__ */ jsx(
|
|
2401
|
+
ToolbarIconButton,
|
|
2402
|
+
{
|
|
2403
|
+
title: t.toolbar.undo,
|
|
2404
|
+
testId: "btn-undo",
|
|
2405
|
+
disabled: !canUndo,
|
|
2406
|
+
onClick: undo,
|
|
2407
|
+
children: /* @__PURE__ */ jsx(Undo2, { size: 15 })
|
|
2408
|
+
}
|
|
2409
|
+
),
|
|
2410
|
+
/* @__PURE__ */ jsx(
|
|
2411
|
+
ToolbarIconButton,
|
|
2412
|
+
{
|
|
2413
|
+
title: t.toolbar.redo,
|
|
2414
|
+
testId: "btn-redo",
|
|
2415
|
+
disabled: !canRedo,
|
|
2416
|
+
onClick: redo,
|
|
2417
|
+
children: /* @__PURE__ */ jsx(Redo2, { size: 15 })
|
|
2418
|
+
}
|
|
2419
|
+
)
|
|
2420
|
+
] }),
|
|
2421
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
2422
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
2423
|
+
/* @__PURE__ */ jsx(Type, { size: 14, className: "text-gray-500" }),
|
|
2424
|
+
/* @__PURE__ */ jsx(
|
|
2425
|
+
"select",
|
|
2426
|
+
{
|
|
2427
|
+
className: "h-7 rounded border border-gray-200 bg-white px-2 text-xs text-gray-700\n focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400",
|
|
2428
|
+
"data-testid": "font-selector",
|
|
2429
|
+
defaultValue: "Calibri",
|
|
2430
|
+
onChange: handleFontChange,
|
|
2431
|
+
children: SUPPORTED_FONTS.map((font) => /* @__PURE__ */ jsx("option", { value: font, style: { fontFamily: font }, children: font }, font))
|
|
2432
|
+
}
|
|
2433
|
+
)
|
|
2434
|
+
] }),
|
|
2435
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
2436
|
+
/* @__PURE__ */ jsx(ALargeSmall, { size: 14, className: "text-gray-500" }),
|
|
2437
|
+
/* @__PURE__ */ jsx(
|
|
2438
|
+
"select",
|
|
2439
|
+
{
|
|
2440
|
+
className: "h-7 w-16 rounded border border-gray-200 bg-white px-1 text-xs text-gray-700\n focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400",
|
|
2441
|
+
"data-testid": "font-size-selector",
|
|
2442
|
+
defaultValue: "12",
|
|
2443
|
+
onChange: handleFontSizeChange,
|
|
2444
|
+
children: SUPPORTED_FONT_SIZES.map((size) => /* @__PURE__ */ jsx("option", { value: size, children: size }, size))
|
|
2445
|
+
}
|
|
2446
|
+
)
|
|
2447
|
+
] }),
|
|
2448
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
2449
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "format-group", children: [
|
|
2450
|
+
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.bold, testId: "btn-bold", onClick: handleBold, children: /* @__PURE__ */ jsx(Bold, { size: 15 }) }),
|
|
2451
|
+
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.italic, testId: "btn-italic", onClick: handleItalic, children: /* @__PURE__ */ jsx(Italic, { size: 15 }) }),
|
|
2452
|
+
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.underline, testId: "btn-underline", onClick: handleUnderline, children: /* @__PURE__ */ jsx(Underline, { size: 15 }) }),
|
|
2453
|
+
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.strikethrough, testId: "btn-strike", onClick: handleStrikethrough, children: /* @__PURE__ */ jsx(Strikethrough, { size: 15 }) })
|
|
2454
|
+
] }),
|
|
2455
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
2456
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "align-group", children: [
|
|
2457
|
+
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.alignLeft, testId: "btn-align-left", onClick: handleAlignLeft, children: /* @__PURE__ */ jsx(TextAlignStart, { size: 15 }) }),
|
|
2458
|
+
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.alignCenter, testId: "btn-align-center", onClick: handleAlignCenter, children: /* @__PURE__ */ jsx(TextAlignCenter, { size: 15 }) }),
|
|
2459
|
+
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.alignRight, testId: "btn-align-right", onClick: handleAlignRight, children: /* @__PURE__ */ jsx(TextAlignEnd, { size: 15 }) }),
|
|
2460
|
+
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.justify, testId: "btn-align-justify", onClick: handleAlignJustify, children: /* @__PURE__ */ jsx(TextAlignJustify, { size: 15 }) })
|
|
2461
|
+
] }),
|
|
2462
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
2463
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "list-group", children: [
|
|
2464
|
+
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.numberedList, testId: "btn-list-number", onClick: handleListNumber, children: /* @__PURE__ */ jsx(ListOrdered, { size: 15 }) }),
|
|
2465
|
+
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.bulletList, testId: "btn-list-bullet", onClick: handleListBullet, children: /* @__PURE__ */ jsx(List, { size: 15 }) }),
|
|
2466
|
+
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.indent, testId: "btn-indent", onClick: handleIndent, children: /* @__PURE__ */ jsx(ListIndentIncrease, { size: 15 }) }),
|
|
2467
|
+
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.outdent, testId: "btn-outdent", onClick: handleOutdent, children: /* @__PURE__ */ jsx(ListIndentDecrease, { size: 15 }) })
|
|
2468
|
+
] }),
|
|
2469
|
+
toolbarItems.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2470
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
2471
|
+
toolbarItems.map((ToolbarItem, idx) => /* @__PURE__ */ jsx(ToolbarItem, {}, idx))
|
|
2472
|
+
] }),
|
|
2473
|
+
/* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center", children: /* @__PURE__ */ jsx(
|
|
2164
2474
|
ToolbarIconButton,
|
|
2165
2475
|
{
|
|
2166
|
-
title: t.toolbar.
|
|
2167
|
-
testId: "
|
|
2168
|
-
|
|
2169
|
-
onClick:
|
|
2170
|
-
children: /* @__PURE__ */ jsx(
|
|
2476
|
+
title: historySidebarOpen ? t.toolbar.closeHistory : t.toolbar.openHistory,
|
|
2477
|
+
testId: "toggle-history-sidebar",
|
|
2478
|
+
active: historySidebarOpen,
|
|
2479
|
+
onClick: () => setHistorySidebarOpen(!historySidebarOpen),
|
|
2480
|
+
children: /* @__PURE__ */ jsx(PanelRight, { size: 15 })
|
|
2171
2481
|
}
|
|
2172
|
-
)
|
|
2482
|
+
) })
|
|
2483
|
+
] }),
|
|
2484
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 px-2 py-1 border-t border-gray-100", children: [
|
|
2173
2485
|
/* @__PURE__ */ jsx(
|
|
2174
|
-
|
|
2486
|
+
HeaderFooterToggle,
|
|
2175
2487
|
{
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
disabled: !canRedo,
|
|
2179
|
-
onClick: redo,
|
|
2180
|
-
children: /* @__PURE__ */ jsx(Redo2, { size: 15 })
|
|
2488
|
+
enabled: document2.headerFooterEnabled,
|
|
2489
|
+
onToggle: handleToggle
|
|
2181
2490
|
}
|
|
2182
|
-
)
|
|
2183
|
-
|
|
2184
|
-
/* @__PURE__ */ jsx(Divider, {}),
|
|
2185
|
-
/* @__PURE__ */ jsx(
|
|
2186
|
-
"select",
|
|
2187
|
-
{
|
|
2188
|
-
className: "h-7 rounded border border-gray-200 bg-white px-2 text-xs text-gray-700\n focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400",
|
|
2189
|
-
"data-testid": "font-selector",
|
|
2190
|
-
defaultValue: "Inter",
|
|
2191
|
-
onChange: handleFontChange,
|
|
2192
|
-
children: SUPPORTED_FONTS.map((font) => /* @__PURE__ */ jsx("option", { value: font, style: { fontFamily: font }, children: font }, font))
|
|
2193
|
-
}
|
|
2194
|
-
),
|
|
2195
|
-
/* @__PURE__ */ jsx(
|
|
2196
|
-
"select",
|
|
2197
|
-
{
|
|
2198
|
-
className: "h-7 w-16 rounded border border-gray-200 bg-white px-1 text-xs text-gray-700\n focus:border-blue-400 focus:outline-none focus:ring-1 focus:ring-blue-400",
|
|
2199
|
-
"data-testid": "font-size-selector",
|
|
2200
|
-
defaultValue: "12",
|
|
2201
|
-
onChange: handleFontSizeChange,
|
|
2202
|
-
children: SUPPORTED_FONT_SIZES.map((size) => /* @__PURE__ */ jsx("option", { value: size, children: size }, size))
|
|
2203
|
-
}
|
|
2204
|
-
),
|
|
2205
|
-
/* @__PURE__ */ jsx(Divider, {}),
|
|
2206
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "format-group", children: [
|
|
2207
|
-
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.bold, testId: "btn-bold", onClick: handleBold, children: /* @__PURE__ */ jsx(Bold, { size: 15 }) }),
|
|
2208
|
-
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.italic, testId: "btn-italic", onClick: handleItalic, children: /* @__PURE__ */ jsx(Italic, { size: 15 }) }),
|
|
2209
|
-
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.underline, testId: "btn-underline", onClick: handleUnderline, children: /* @__PURE__ */ jsx(Underline, { size: 15 }) }),
|
|
2210
|
-
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.strikethrough, testId: "btn-strike", onClick: handleStrikethrough, children: /* @__PURE__ */ jsx(Strikethrough, { size: 15 }) })
|
|
2211
|
-
] }),
|
|
2212
|
-
/* @__PURE__ */ jsx(Divider, {}),
|
|
2213
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "align-group", children: [
|
|
2214
|
-
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.alignLeft, testId: "btn-align-left", onClick: handleAlignLeft, children: /* @__PURE__ */ jsx(TextAlignStart, { size: 15 }) }),
|
|
2215
|
-
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.alignCenter, testId: "btn-align-center", onClick: handleAlignCenter, children: /* @__PURE__ */ jsx(TextAlignCenter, { size: 15 }) }),
|
|
2216
|
-
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.alignRight, testId: "btn-align-right", onClick: handleAlignRight, children: /* @__PURE__ */ jsx(TextAlignEnd, { size: 15 }) }),
|
|
2217
|
-
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.justify, testId: "btn-align-justify", onClick: handleAlignJustify, children: /* @__PURE__ */ jsx(TextAlignJustify, { size: 15 }) })
|
|
2218
|
-
] }),
|
|
2219
|
-
/* @__PURE__ */ jsx(Divider, {}),
|
|
2220
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "list-group", children: [
|
|
2221
|
-
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.numberedList, testId: "btn-list-number", onClick: handleListNumber, children: /* @__PURE__ */ jsx(ListOrdered, { size: 15 }) }),
|
|
2222
|
-
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.bulletList, testId: "btn-list-bullet", onClick: handleListBullet, children: /* @__PURE__ */ jsx(List, { size: 15 }) }),
|
|
2223
|
-
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.indent, testId: "btn-indent", onClick: handleIndent, children: /* @__PURE__ */ jsx(ListIndentIncrease, { size: 15 }) }),
|
|
2224
|
-
/* @__PURE__ */ jsx(ToolbarIconButton, { title: t.toolbar.outdent, testId: "btn-outdent", onClick: handleOutdent, children: /* @__PURE__ */ jsx(ListIndentDecrease, { size: 15 }) })
|
|
2225
|
-
] }),
|
|
2226
|
-
/* @__PURE__ */ jsx(Divider, {}),
|
|
2227
|
-
/* @__PURE__ */ jsx(
|
|
2228
|
-
HeaderFooterToggle,
|
|
2229
|
-
{
|
|
2230
|
-
enabled: document2.headerFooterEnabled,
|
|
2231
|
-
onToggle: handleToggle
|
|
2232
|
-
}
|
|
2233
|
-
),
|
|
2234
|
-
document2.headerFooterEnabled && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2235
|
-
/* @__PURE__ */ jsx(Divider, {}),
|
|
2236
|
-
/* @__PURE__ */ jsx(
|
|
2491
|
+
),
|
|
2492
|
+
document2.headerFooterEnabled && /* @__PURE__ */ jsx(
|
|
2237
2493
|
HeaderFooterActions,
|
|
2238
2494
|
{
|
|
2239
2495
|
activePageId,
|
|
@@ -2247,22 +2503,8 @@ const Toolbar = () => {
|
|
|
2247
2503
|
onClearAllFooters: handleClearAllFooters
|
|
2248
2504
|
}
|
|
2249
2505
|
)
|
|
2250
|
-
] })
|
|
2251
|
-
|
|
2252
|
-
/* @__PURE__ */ jsx(Divider, {}),
|
|
2253
|
-
toolbarItems.map((ToolbarItem, idx) => /* @__PURE__ */ jsx(ToolbarItem, {}, idx))
|
|
2254
|
-
] }),
|
|
2255
|
-
/* @__PURE__ */ jsx("div", { className: "ml-auto flex items-center", children: /* @__PURE__ */ jsx(
|
|
2256
|
-
ToolbarIconButton,
|
|
2257
|
-
{
|
|
2258
|
-
title: historySidebarOpen ? t.toolbar.closeHistory : t.toolbar.openHistory,
|
|
2259
|
-
testId: "toggle-history-sidebar",
|
|
2260
|
-
active: historySidebarOpen,
|
|
2261
|
-
onClick: () => setHistorySidebarOpen(!historySidebarOpen),
|
|
2262
|
-
children: /* @__PURE__ */ jsx(PanelRight, { size: 15 })
|
|
2263
|
-
}
|
|
2264
|
-
) })
|
|
2265
|
-
] })
|
|
2506
|
+
] })
|
|
2507
|
+
]
|
|
2266
2508
|
}
|
|
2267
2509
|
);
|
|
2268
2510
|
};
|
|
@@ -2333,6 +2575,19 @@ function mergeEditorStates(stateA, stateB) {
|
|
|
2333
2575
|
if (all.length === 0) return null;
|
|
2334
2576
|
return createEditorStateFromNodes(all);
|
|
2335
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
|
+
}
|
|
2336
2591
|
function usePagination(document2, dispatch) {
|
|
2337
2592
|
const reflowingRef = useRef(false);
|
|
2338
2593
|
const pendingReflowRef = useRef(false);
|
|
@@ -2367,7 +2622,61 @@ function usePagination(document2, dispatch) {
|
|
|
2367
2622
|
const footerH = document2.headerFooterEnabled ? page.footerHeight : 0;
|
|
2368
2623
|
const bodyHeight = computeBodyHeight(headerH, footerH);
|
|
2369
2624
|
const nodes = getTopLevelNodes(page.bodyState);
|
|
2370
|
-
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
|
+
}
|
|
2371
2680
|
const fitCount = estimateNodesFitting(page.bodyState, bodyHeight);
|
|
2372
2681
|
if (fitCount >= nodes.length) return;
|
|
2373
2682
|
const [keepState, overflowState] = splitEditorState(page.bodyState, fitCount);
|
|
@@ -2531,7 +2840,7 @@ function usePagination(document2, dispatch) {
|
|
|
2531
2840
|
}
|
|
2532
2841
|
const lexicalTheme = {
|
|
2533
2842
|
root: "lex4-root outline-none",
|
|
2534
|
-
paragraph: "lex4-paragraph
|
|
2843
|
+
paragraph: "lex4-paragraph text-justify",
|
|
2535
2844
|
heading: {
|
|
2536
2845
|
h1: "text-3xl font-bold mb-2",
|
|
2537
2846
|
h2: "text-2xl font-bold mb-2",
|
|
@@ -2737,6 +3046,213 @@ const ActiveEditorPlugin = ({
|
|
|
2737
3046
|
}, [editor, onFocus, pageId, region, setActiveEditor, setActivePageId]);
|
|
2738
3047
|
return null;
|
|
2739
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
|
+
}
|
|
2740
3256
|
function serializeNodeTree(node) {
|
|
2741
3257
|
const json = node.exportJSON();
|
|
2742
3258
|
if ($isElementNode(node)) {
|
|
@@ -2765,18 +3281,51 @@ const OverflowPlugin = ({
|
|
|
2765
3281
|
const children = Array.from(rootElement.children);
|
|
2766
3282
|
if (children.length === 0) return;
|
|
2767
3283
|
if (children.length <= 1) {
|
|
2768
|
-
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
|
+
);
|
|
2769
3312
|
return;
|
|
2770
3313
|
}
|
|
2771
3314
|
processingRef.current = true;
|
|
2772
3315
|
debug("overflow", `OVERFLOW detected: content=${contentHeight}px available=${availableHeight}px children=${children.length}`);
|
|
2773
3316
|
let splitIndex = children.length;
|
|
3317
|
+
let firstBlockOverflows = false;
|
|
2774
3318
|
for (let i = 0; i < children.length; i++) {
|
|
2775
3319
|
const child = children[i];
|
|
2776
3320
|
const childBottom = child.offsetTop + child.offsetHeight;
|
|
2777
|
-
if (childBottom > availableHeight
|
|
2778
|
-
|
|
2779
|
-
|
|
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)`);
|
|
2780
3329
|
break;
|
|
2781
3330
|
}
|
|
2782
3331
|
}
|
|
@@ -2794,15 +3343,37 @@ const OverflowPlugin = ({
|
|
|
2794
3343
|
processingRef.current = false;
|
|
2795
3344
|
return;
|
|
2796
3345
|
}
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
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
|
+
}
|
|
2801
3371
|
}
|
|
2802
|
-
|
|
2803
|
-
|
|
3372
|
+
if (overflowNodes.length === 0) {
|
|
3373
|
+
processingRef.current = false;
|
|
3374
|
+
return;
|
|
2804
3375
|
}
|
|
2805
|
-
debug("overflow", `extracted ${overflowNodes.length} overflow nodes
|
|
3376
|
+
debug("overflow", `extracted ${overflowNodes.length} overflow nodes total`);
|
|
2806
3377
|
const overflowState = {
|
|
2807
3378
|
root: {
|
|
2808
3379
|
children: overflowNodes,
|
|
@@ -2883,16 +3454,10 @@ const OverflowPlugin = ({
|
|
|
2883
3454
|
}, [editor]);
|
|
2884
3455
|
return null;
|
|
2885
3456
|
};
|
|
2886
|
-
function createPageLabel(region, pageNumber) {
|
|
2887
|
-
if (region === "body") {
|
|
2888
|
-
return pageNumber ? `Page ${pageNumber}` : "Body";
|
|
2889
|
-
}
|
|
2890
|
-
const regionLabel = region.charAt(0).toUpperCase() + region.slice(1);
|
|
2891
|
-
return pageNumber ? `${regionLabel} Page ${pageNumber}` : regionLabel;
|
|
2892
|
-
}
|
|
2893
3457
|
const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
2894
3458
|
const [editor] = useLexicalComposerContext();
|
|
2895
3459
|
const { document: document2, queueHistoryAction } = useDocument();
|
|
3460
|
+
const t = useTranslations();
|
|
2896
3461
|
const context = useMemo(() => {
|
|
2897
3462
|
const pageNumber = document2.pages.findIndex((page) => page.id === pageId);
|
|
2898
3463
|
return {
|
|
@@ -2900,9 +3465,18 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
2900
3465
|
source: region
|
|
2901
3466
|
};
|
|
2902
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]);
|
|
2903
3477
|
useEffect(() => {
|
|
2904
|
-
const buildDescriptor = (
|
|
2905
|
-
label: `${
|
|
3478
|
+
const buildDescriptor = (label) => ({
|
|
3479
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
2906
3480
|
source: context.source,
|
|
2907
3481
|
pageId,
|
|
2908
3482
|
region
|
|
@@ -2910,15 +3484,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
2910
3484
|
return editor.registerCommand(
|
|
2911
3485
|
CONTROLLED_TEXT_INSERTION_COMMAND,
|
|
2912
3486
|
() => {
|
|
2913
|
-
queueHistoryAction(buildDescriptor(
|
|
3487
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.typedText));
|
|
2914
3488
|
return false;
|
|
2915
3489
|
},
|
|
2916
3490
|
COMMAND_PRIORITY_LOW
|
|
2917
3491
|
);
|
|
2918
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3492
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
2919
3493
|
useEffect(() => {
|
|
2920
|
-
const buildDescriptor = (
|
|
2921
|
-
label: `${
|
|
3494
|
+
const buildDescriptor = (label) => ({
|
|
3495
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
2922
3496
|
source: context.source,
|
|
2923
3497
|
pageId,
|
|
2924
3498
|
region
|
|
@@ -2932,15 +3506,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
2932
3506
|
if (event.key.length !== 1) {
|
|
2933
3507
|
return false;
|
|
2934
3508
|
}
|
|
2935
|
-
queueHistoryAction(buildDescriptor(
|
|
3509
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.typedText));
|
|
2936
3510
|
return false;
|
|
2937
3511
|
},
|
|
2938
3512
|
COMMAND_PRIORITY_LOW
|
|
2939
3513
|
);
|
|
2940
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3514
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
2941
3515
|
useEffect(() => {
|
|
2942
|
-
const buildDescriptor = (
|
|
2943
|
-
label: `${
|
|
3516
|
+
const buildDescriptor = (label) => ({
|
|
3517
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
2944
3518
|
source: context.source,
|
|
2945
3519
|
pageId,
|
|
2946
3520
|
region
|
|
@@ -2953,15 +3527,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
2953
3527
|
if (text.trim().length === 0) {
|
|
2954
3528
|
return false;
|
|
2955
3529
|
}
|
|
2956
|
-
queueHistoryAction(buildDescriptor(
|
|
3530
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.pastedContent));
|
|
2957
3531
|
return false;
|
|
2958
3532
|
},
|
|
2959
3533
|
COMMAND_PRIORITY_LOW
|
|
2960
3534
|
);
|
|
2961
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3535
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
2962
3536
|
useEffect(() => {
|
|
2963
|
-
const buildDescriptor = (
|
|
2964
|
-
label: `${
|
|
3537
|
+
const buildDescriptor = (label) => ({
|
|
3538
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
2965
3539
|
source: context.source,
|
|
2966
3540
|
pageId,
|
|
2967
3541
|
region
|
|
@@ -2969,15 +3543,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
2969
3543
|
return editor.registerCommand(
|
|
2970
3544
|
KEY_ENTER_COMMAND,
|
|
2971
3545
|
() => {
|
|
2972
|
-
queueHistoryAction(buildDescriptor(
|
|
3546
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.insertedLineBreak));
|
|
2973
3547
|
return false;
|
|
2974
3548
|
},
|
|
2975
3549
|
COMMAND_PRIORITY_LOW
|
|
2976
3550
|
);
|
|
2977
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3551
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
2978
3552
|
useEffect(() => {
|
|
2979
|
-
const buildDescriptor = (
|
|
2980
|
-
label: `${
|
|
3553
|
+
const buildDescriptor = (label) => ({
|
|
3554
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
2981
3555
|
source: context.source,
|
|
2982
3556
|
pageId,
|
|
2983
3557
|
region
|
|
@@ -2985,15 +3559,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
2985
3559
|
return editor.registerCommand(
|
|
2986
3560
|
KEY_BACKSPACE_COMMAND,
|
|
2987
3561
|
() => {
|
|
2988
|
-
queueHistoryAction(buildDescriptor(
|
|
3562
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.deletedBackward));
|
|
2989
3563
|
return false;
|
|
2990
3564
|
},
|
|
2991
3565
|
COMMAND_PRIORITY_LOW
|
|
2992
3566
|
);
|
|
2993
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3567
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
2994
3568
|
useEffect(() => {
|
|
2995
|
-
const buildDescriptor = (
|
|
2996
|
-
label: `${
|
|
3569
|
+
const buildDescriptor = (label) => ({
|
|
3570
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
2997
3571
|
source: context.source,
|
|
2998
3572
|
pageId,
|
|
2999
3573
|
region
|
|
@@ -3001,15 +3575,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3001
3575
|
return editor.registerCommand(
|
|
3002
3576
|
KEY_DELETE_COMMAND,
|
|
3003
3577
|
() => {
|
|
3004
|
-
queueHistoryAction(buildDescriptor(
|
|
3578
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.deletedForward));
|
|
3005
3579
|
return false;
|
|
3006
3580
|
},
|
|
3007
3581
|
COMMAND_PRIORITY_LOW
|
|
3008
3582
|
);
|
|
3009
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3583
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3010
3584
|
useEffect(() => {
|
|
3011
|
-
const buildDescriptor = (
|
|
3012
|
-
label: `${
|
|
3585
|
+
const buildDescriptor = (label) => ({
|
|
3586
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
3013
3587
|
source: context.source,
|
|
3014
3588
|
pageId,
|
|
3015
3589
|
region
|
|
@@ -3017,15 +3591,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3017
3591
|
return editor.registerCommand(
|
|
3018
3592
|
FORMAT_TEXT_COMMAND,
|
|
3019
3593
|
() => {
|
|
3020
|
-
queueHistoryAction(buildDescriptor(
|
|
3594
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.formattedText));
|
|
3021
3595
|
return false;
|
|
3022
3596
|
},
|
|
3023
3597
|
COMMAND_PRIORITY_LOW
|
|
3024
3598
|
);
|
|
3025
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3599
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3026
3600
|
useEffect(() => {
|
|
3027
|
-
const buildDescriptor = (
|
|
3028
|
-
label: `${
|
|
3601
|
+
const buildDescriptor = (label) => ({
|
|
3602
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
3029
3603
|
source: context.source,
|
|
3030
3604
|
pageId,
|
|
3031
3605
|
region
|
|
@@ -3033,12 +3607,12 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3033
3607
|
return editor.registerCommand(
|
|
3034
3608
|
FORMAT_ELEMENT_COMMAND,
|
|
3035
3609
|
() => {
|
|
3036
|
-
queueHistoryAction(buildDescriptor(
|
|
3610
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.formattedParagraph));
|
|
3037
3611
|
return false;
|
|
3038
3612
|
},
|
|
3039
3613
|
COMMAND_PRIORITY_LOW
|
|
3040
3614
|
);
|
|
3041
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3615
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3042
3616
|
return null;
|
|
3043
3617
|
};
|
|
3044
3618
|
function getCollapsedTextPosition(rootElement) {
|
|
@@ -3143,6 +3717,7 @@ const PageBody = ({
|
|
|
3143
3717
|
readOnly = false
|
|
3144
3718
|
}) => {
|
|
3145
3719
|
const { nodes, bodyPlugins, themeOverrides } = useExtensions();
|
|
3720
|
+
const t = useTranslations();
|
|
3146
3721
|
const config = useMemo(
|
|
3147
3722
|
() => {
|
|
3148
3723
|
var _a, _b;
|
|
@@ -3196,7 +3771,7 @@ const PageBody = ({
|
|
|
3196
3771
|
style: { overflow: "visible" }
|
|
3197
3772
|
}
|
|
3198
3773
|
),
|
|
3199
|
-
placeholder: /* @__PURE__ */ jsx("div", { className: "absolute top-0 left-0 text-gray-400 pointer-events-none select-none", children:
|
|
3774
|
+
placeholder: /* @__PURE__ */ jsx("div", { className: "absolute top-0 left-0 text-gray-400 pointer-events-none select-none", children: t.body.placeholder }),
|
|
3200
3775
|
ErrorBoundary: LexicalErrorBoundary
|
|
3201
3776
|
}
|
|
3202
3777
|
),
|
|
@@ -3336,10 +3911,10 @@ const PageHeader = ({
|
|
|
3336
3911
|
ContentEditable,
|
|
3337
3912
|
{
|
|
3338
3913
|
ref: contentRef,
|
|
3339
|
-
className: `outline-none p-2 text-
|
|
3914
|
+
className: `outline-none p-2 text-gray-600 min-h-[24px] ${hasPageCounter ? "pr-24" : ""}`
|
|
3340
3915
|
}
|
|
3341
3916
|
),
|
|
3342
|
-
placeholder: /* @__PURE__ */ jsx("div", { className: `absolute top-0 left-0 text-gray-400 pointer-events-none select-none p-2
|
|
3917
|
+
placeholder: /* @__PURE__ */ jsx("div", { className: `absolute top-0 left-0 text-gray-400 pointer-events-none select-none p-2 ${hasPageCounter ? "pr-24" : ""}`, children: t.header.placeholder }),
|
|
3343
3918
|
ErrorBoundary: LexicalErrorBoundary
|
|
3344
3919
|
}
|
|
3345
3920
|
),
|
|
@@ -3416,10 +3991,10 @@ const PageFooter = ({
|
|
|
3416
3991
|
ContentEditable,
|
|
3417
3992
|
{
|
|
3418
3993
|
ref: contentRef,
|
|
3419
|
-
className: `outline-none p-2 text-
|
|
3994
|
+
className: `outline-none p-2 text-gray-600 min-h-[24px] ${hasPageCounter ? "pr-24" : ""}`
|
|
3420
3995
|
}
|
|
3421
3996
|
),
|
|
3422
|
-
placeholder: /* @__PURE__ */ jsx("div", { className: `absolute top-0 left-0 text-gray-400 pointer-events-none select-none p-2
|
|
3997
|
+
placeholder: /* @__PURE__ */ jsx("div", { className: `absolute top-0 left-0 text-gray-400 pointer-events-none select-none p-2 ${hasPageCounter ? "pr-24" : ""}`, children: t.footer.placeholder }),
|
|
3423
3998
|
ErrorBoundary: LexicalErrorBoundary
|
|
3424
3999
|
}
|
|
3425
4000
|
),
|
|
@@ -3450,10 +4025,14 @@ const PageView = React.memo(({
|
|
|
3450
4025
|
onMoveToNextPage
|
|
3451
4026
|
}) => {
|
|
3452
4027
|
const { document: document2, dispatch, setActivePageId } = useDocument();
|
|
4028
|
+
const t = useTranslations();
|
|
3453
4029
|
const page = document2.pages.find((p) => p.id === pageId);
|
|
3454
4030
|
const showHeaderFooter = document2.headerFooterEnabled;
|
|
3455
4031
|
const pageCounterMode = document2.pageCounterMode;
|
|
3456
|
-
const pageCounterLabel =
|
|
4032
|
+
const pageCounterLabel = interpolate(t.pageCounter.format, {
|
|
4033
|
+
current: pageIndex + 1,
|
|
4034
|
+
total: document2.pages.length
|
|
4035
|
+
});
|
|
3457
4036
|
if (!page) return null;
|
|
3458
4037
|
const handleBodyChange = useCallback(
|
|
3459
4038
|
(bodyState) => {
|
|
@@ -3544,6 +4123,7 @@ const DocumentView = () => {
|
|
|
3544
4123
|
setActiveEditor,
|
|
3545
4124
|
setActivePageId
|
|
3546
4125
|
} = useDocument();
|
|
4126
|
+
const t = useTranslations();
|
|
3547
4127
|
const { handlePageUnderflow, reflowAll } = usePagination(document2, dispatch);
|
|
3548
4128
|
const previousBodyHeightsRef = useRef(null);
|
|
3549
4129
|
const pasteOverflowSequenceRef = useRef(false);
|
|
@@ -3708,7 +4288,7 @@ const DocumentView = () => {
|
|
|
3708
4288
|
}
|
|
3709
4289
|
runHistoryAction(
|
|
3710
4290
|
{
|
|
3711
|
-
label:
|
|
4291
|
+
label: `${t.historyLabels.deletedBackward} - ${interpolate(t.regions.page, { page: pageIndex + 1 })}`,
|
|
3712
4292
|
source: "body",
|
|
3713
4293
|
pageId,
|
|
3714
4294
|
region: "body"
|
|
@@ -3730,7 +4310,7 @@ const DocumentView = () => {
|
|
|
3730
4310
|
}
|
|
3731
4311
|
runHistoryAction(
|
|
3732
4312
|
{
|
|
3733
|
-
label:
|
|
4313
|
+
label: `${t.historyLabels.deletedForward} - ${interpolate(t.regions.page, { page: pageIndex + 1 })}`,
|
|
3734
4314
|
source: "body",
|
|
3735
4315
|
pageId,
|
|
3736
4316
|
region: "body"
|
|
@@ -3963,7 +4543,7 @@ const EditorChrome = ({
|
|
|
3963
4543
|
}
|
|
3964
4544
|
),
|
|
3965
4545
|
/* @__PURE__ */ jsx(Toolbar, {}),
|
|
3966
|
-
/* @__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: [
|
|
3967
4547
|
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 overflow-auto", children: /* @__PURE__ */ jsx(DocumentView, {}) }),
|
|
3968
4548
|
sidePanels.map((Panel, idx) => /* @__PURE__ */ jsx(Panel, {}, idx)),
|
|
3969
4549
|
/* @__PURE__ */ jsx(HistorySidebar, {})
|
|
@@ -4777,6 +5357,7 @@ export {
|
|
|
4777
5357
|
Lex4Editor,
|
|
4778
5358
|
MAX_FOOTER_HEIGHT_PX,
|
|
4779
5359
|
MAX_HEADER_HEIGHT_PX,
|
|
5360
|
+
PT_BR_TRANSLATIONS,
|
|
4780
5361
|
VariableNode,
|
|
4781
5362
|
astExtension,
|
|
4782
5363
|
buildSavePayload,
|