@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.cjs
CHANGED
|
@@ -454,6 +454,258 @@ function jumpToHistoryEntry(history, entryIndex) {
|
|
|
454
454
|
caretSelection: ((_b = nextHistory.entries[nextHistory.cursor - 1]) == null ? void 0 : _b.caretSelection) ?? null
|
|
455
455
|
};
|
|
456
456
|
}
|
|
457
|
+
const DEFAULT_TRANSLATIONS = {
|
|
458
|
+
toolbar: {
|
|
459
|
+
undo: "Undo",
|
|
460
|
+
redo: "Redo",
|
|
461
|
+
bold: "Bold (Ctrl+B)",
|
|
462
|
+
italic: "Italic (Ctrl+I)",
|
|
463
|
+
underline: "Underline (Ctrl+U)",
|
|
464
|
+
strikethrough: "Strikethrough",
|
|
465
|
+
alignLeft: "Align Left",
|
|
466
|
+
alignCenter: "Align Center",
|
|
467
|
+
alignRight: "Align Right",
|
|
468
|
+
justify: "Justify",
|
|
469
|
+
numberedList: "Numbered List",
|
|
470
|
+
bulletList: "Bullet List",
|
|
471
|
+
indent: "Indent",
|
|
472
|
+
outdent: "Outdent",
|
|
473
|
+
openHistory: "Open History",
|
|
474
|
+
closeHistory: "Close History"
|
|
475
|
+
},
|
|
476
|
+
history: {
|
|
477
|
+
title: "History",
|
|
478
|
+
subtitle: "Word-style session history (last 100 actions)",
|
|
479
|
+
empty: "No history yet.",
|
|
480
|
+
clearHistory: "Clear History",
|
|
481
|
+
actions: {
|
|
482
|
+
enabledHeadersFooters: "Enabled headers and footers",
|
|
483
|
+
disabledHeadersFooters: "Disabled headers and footers",
|
|
484
|
+
copiedHeaderToAll: "Copied header to all pages",
|
|
485
|
+
copiedFooterToAll: "Copied footer to all pages",
|
|
486
|
+
clearedHeader: "Cleared header",
|
|
487
|
+
clearedFooter: "Cleared footer",
|
|
488
|
+
clearedAllHeaders: "Cleared all headers",
|
|
489
|
+
clearedAllFooters: "Cleared all footers",
|
|
490
|
+
pageCounterSet: "Page counter set to {{value}}",
|
|
491
|
+
boldApplied: "Bold applied",
|
|
492
|
+
italicApplied: "Italic applied",
|
|
493
|
+
underlineApplied: "Underline applied",
|
|
494
|
+
strikethroughApplied: "Strikethrough applied",
|
|
495
|
+
alignedLeft: "Aligned left",
|
|
496
|
+
alignedCenter: "Aligned center",
|
|
497
|
+
alignedRight: "Aligned right",
|
|
498
|
+
justifiedText: "Justified text",
|
|
499
|
+
insertedNumberedList: "Inserted numbered list",
|
|
500
|
+
insertedBulletList: "Inserted bullet list",
|
|
501
|
+
indentedContent: "Indented content",
|
|
502
|
+
outdentedContent: "Outdented content",
|
|
503
|
+
fontChanged: "Font changed to {{value}}",
|
|
504
|
+
fontSizeChanged: "Font size changed to {{value}}pt"
|
|
505
|
+
}
|
|
506
|
+
},
|
|
507
|
+
variables: {
|
|
508
|
+
title: "Variables",
|
|
509
|
+
available: "{{count}} available",
|
|
510
|
+
refreshVariables: "Refresh variables",
|
|
511
|
+
searchPlaceholder: "Search variables...",
|
|
512
|
+
noVariablesFound: "No variables found",
|
|
513
|
+
insertVariable: "Insert variable {{key}}",
|
|
514
|
+
openPanel: "Open Variables",
|
|
515
|
+
closePanel: "Close Variables"
|
|
516
|
+
},
|
|
517
|
+
header: {
|
|
518
|
+
placeholder: "Header"
|
|
519
|
+
},
|
|
520
|
+
footer: {
|
|
521
|
+
placeholder: "Footer"
|
|
522
|
+
},
|
|
523
|
+
body: {
|
|
524
|
+
placeholder: "Start typing..."
|
|
525
|
+
},
|
|
526
|
+
pageCounter: {
|
|
527
|
+
format: "Page {{current}} of {{total}}"
|
|
528
|
+
},
|
|
529
|
+
regions: {
|
|
530
|
+
body: "body",
|
|
531
|
+
header: "header",
|
|
532
|
+
footer: "footer",
|
|
533
|
+
document: "document",
|
|
534
|
+
toolbar: "toolbar",
|
|
535
|
+
overflow: "overflow",
|
|
536
|
+
history: "history",
|
|
537
|
+
page: "Page {{page}}"
|
|
538
|
+
},
|
|
539
|
+
headerFooter: {
|
|
540
|
+
label: "Headers & Footers"
|
|
541
|
+
},
|
|
542
|
+
sidebar: {
|
|
543
|
+
close: "Close sidebar"
|
|
544
|
+
},
|
|
545
|
+
historyLabels: {
|
|
546
|
+
typedText: "Typed text",
|
|
547
|
+
pastedContent: "Pasted content",
|
|
548
|
+
insertedLineBreak: "Inserted line break",
|
|
549
|
+
deletedBackward: "Deleted backward",
|
|
550
|
+
deletedForward: "Deleted forward",
|
|
551
|
+
formattedText: "Formatted text",
|
|
552
|
+
formattedParagraph: "Formatted paragraph",
|
|
553
|
+
editedBody: "Edited body",
|
|
554
|
+
editedHeader: "Edited header",
|
|
555
|
+
editedFooter: "Edited footer",
|
|
556
|
+
clearedDocumentBody: "Cleared document body",
|
|
557
|
+
resizedHeader: "Resized header",
|
|
558
|
+
resizedFooter: "Resized footer",
|
|
559
|
+
addedPage: "Added page",
|
|
560
|
+
removedPage: "Removed page",
|
|
561
|
+
documentReflow: "Document reflow",
|
|
562
|
+
updatedDocument: "Updated document"
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
const PT_BR_TRANSLATIONS = {
|
|
566
|
+
toolbar: {
|
|
567
|
+
undo: "Desfazer",
|
|
568
|
+
redo: "Refazer",
|
|
569
|
+
bold: "Negrito (Ctrl+B)",
|
|
570
|
+
italic: "Itálico (Ctrl+I)",
|
|
571
|
+
underline: "Sublinhado (Ctrl+U)",
|
|
572
|
+
strikethrough: "Tachado",
|
|
573
|
+
alignLeft: "Alinhar à Esquerda",
|
|
574
|
+
alignCenter: "Centralizar",
|
|
575
|
+
alignRight: "Alinhar à Direita",
|
|
576
|
+
justify: "Justificar",
|
|
577
|
+
numberedList: "Lista Numerada",
|
|
578
|
+
bulletList: "Lista com Marcadores",
|
|
579
|
+
indent: "Aumentar Recuo",
|
|
580
|
+
outdent: "Diminuir Recuo",
|
|
581
|
+
openHistory: "Abrir Histórico",
|
|
582
|
+
closeHistory: "Fechar Histórico"
|
|
583
|
+
},
|
|
584
|
+
history: {
|
|
585
|
+
title: "Histórico",
|
|
586
|
+
subtitle: "Histórico de sessão (últimas 100 ações)",
|
|
587
|
+
empty: "Nenhum histórico ainda.",
|
|
588
|
+
clearHistory: "Limpar Histórico",
|
|
589
|
+
actions: {
|
|
590
|
+
enabledHeadersFooters: "Cabeçalhos e rodapés ativados",
|
|
591
|
+
disabledHeadersFooters: "Cabeçalhos e rodapés desativados",
|
|
592
|
+
copiedHeaderToAll: "Cabeçalho copiado para todas as páginas",
|
|
593
|
+
copiedFooterToAll: "Rodapé copiado para todas as páginas",
|
|
594
|
+
clearedHeader: "Cabeçalho limpo",
|
|
595
|
+
clearedFooter: "Rodapé limpo",
|
|
596
|
+
clearedAllHeaders: "Todos os cabeçalhos limpos",
|
|
597
|
+
clearedAllFooters: "Todos os rodapés limpos",
|
|
598
|
+
pageCounterSet: "Contador de páginas definido como {{value}}",
|
|
599
|
+
boldApplied: "Negrito aplicado",
|
|
600
|
+
italicApplied: "Itálico aplicado",
|
|
601
|
+
underlineApplied: "Sublinhado aplicado",
|
|
602
|
+
strikethroughApplied: "Tachado aplicado",
|
|
603
|
+
alignedLeft: "Alinhado à esquerda",
|
|
604
|
+
alignedCenter: "Centralizado",
|
|
605
|
+
alignedRight: "Alinhado à direita",
|
|
606
|
+
justifiedText: "Texto justificado",
|
|
607
|
+
insertedNumberedList: "Lista numerada inserida",
|
|
608
|
+
insertedBulletList: "Lista com marcadores inserida",
|
|
609
|
+
indentedContent: "Conteúdo recuado",
|
|
610
|
+
outdentedContent: "Recuo reduzido",
|
|
611
|
+
fontChanged: "Fonte alterada para {{value}}",
|
|
612
|
+
fontSizeChanged: "Tamanho da fonte alterado para {{value}}pt"
|
|
613
|
+
}
|
|
614
|
+
},
|
|
615
|
+
variables: {
|
|
616
|
+
title: "Variáveis",
|
|
617
|
+
available: "{{count}} disponíveis",
|
|
618
|
+
refreshVariables: "Atualizar variáveis",
|
|
619
|
+
searchPlaceholder: "Buscar variáveis...",
|
|
620
|
+
noVariablesFound: "Nenhuma variável encontrada",
|
|
621
|
+
insertVariable: "Inserir variável {{key}}",
|
|
622
|
+
openPanel: "Abrir Variáveis",
|
|
623
|
+
closePanel: "Fechar Variáveis"
|
|
624
|
+
},
|
|
625
|
+
header: {
|
|
626
|
+
placeholder: "Cabeçalho"
|
|
627
|
+
},
|
|
628
|
+
footer: {
|
|
629
|
+
placeholder: "Rodapé"
|
|
630
|
+
},
|
|
631
|
+
body: {
|
|
632
|
+
placeholder: "Comece a digitar..."
|
|
633
|
+
},
|
|
634
|
+
pageCounter: {
|
|
635
|
+
format: "Página {{current}} de {{total}}"
|
|
636
|
+
},
|
|
637
|
+
regions: {
|
|
638
|
+
body: "corpo",
|
|
639
|
+
header: "cabeçalho",
|
|
640
|
+
footer: "rodapé",
|
|
641
|
+
document: "documento",
|
|
642
|
+
toolbar: "barra de ferramentas",
|
|
643
|
+
overflow: "estouro",
|
|
644
|
+
history: "histórico",
|
|
645
|
+
page: "Página {{page}}"
|
|
646
|
+
},
|
|
647
|
+
headerFooter: {
|
|
648
|
+
label: "Cabeçalhos e Rodapés"
|
|
649
|
+
},
|
|
650
|
+
sidebar: {
|
|
651
|
+
close: "Fechar barra lateral"
|
|
652
|
+
},
|
|
653
|
+
historyLabels: {
|
|
654
|
+
typedText: "Texto digitado",
|
|
655
|
+
pastedContent: "Conteúdo colado",
|
|
656
|
+
insertedLineBreak: "Quebra de linha inserida",
|
|
657
|
+
deletedBackward: "Exclusão para trás",
|
|
658
|
+
deletedForward: "Exclusão para frente",
|
|
659
|
+
formattedText: "Texto formatado",
|
|
660
|
+
formattedParagraph: "Parágrafo formatado",
|
|
661
|
+
editedBody: "Corpo editado",
|
|
662
|
+
editedHeader: "Cabeçalho editado",
|
|
663
|
+
editedFooter: "Rodapé editado",
|
|
664
|
+
clearedDocumentBody: "Corpo do documento limpo",
|
|
665
|
+
resizedHeader: "Cabeçalho redimensionado",
|
|
666
|
+
resizedFooter: "Rodapé redimensionado",
|
|
667
|
+
addedPage: "Página adicionada",
|
|
668
|
+
removedPage: "Página removida",
|
|
669
|
+
documentReflow: "Redistribuição do documento",
|
|
670
|
+
updatedDocument: "Documento atualizado"
|
|
671
|
+
}
|
|
672
|
+
};
|
|
673
|
+
function deepMerge(target, source) {
|
|
674
|
+
if (typeof target !== "object" || target === null) {
|
|
675
|
+
return source ?? target;
|
|
676
|
+
}
|
|
677
|
+
const result = { ...target };
|
|
678
|
+
for (const key of Object.keys(source)) {
|
|
679
|
+
const sourceVal = source[key];
|
|
680
|
+
const targetVal = target[key];
|
|
681
|
+
if (sourceVal !== void 0 && typeof sourceVal === "object" && sourceVal !== null && !Array.isArray(sourceVal) && typeof targetVal === "object" && targetVal !== null) {
|
|
682
|
+
result[key] = deepMerge(targetVal, sourceVal);
|
|
683
|
+
} else if (sourceVal !== void 0) {
|
|
684
|
+
result[key] = sourceVal;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
return result;
|
|
688
|
+
}
|
|
689
|
+
const TranslationsContext = React.createContext(DEFAULT_TRANSLATIONS);
|
|
690
|
+
function useTranslations() {
|
|
691
|
+
return React.useContext(TranslationsContext);
|
|
692
|
+
}
|
|
693
|
+
function interpolate(template, params) {
|
|
694
|
+
return template.replace(
|
|
695
|
+
/\{\{(\w+)\}\}/g,
|
|
696
|
+
(_, key) => String(params[key] ?? `{{${key}}}`)
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
const TranslationsProvider = ({
|
|
700
|
+
translations,
|
|
701
|
+
children
|
|
702
|
+
}) => {
|
|
703
|
+
const merged = React.useMemo(
|
|
704
|
+
() => translations ? deepMerge(DEFAULT_TRANSLATIONS, translations) : DEFAULT_TRANSLATIONS,
|
|
705
|
+
[translations]
|
|
706
|
+
);
|
|
707
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TranslationsContext.Provider, { value: merged, children });
|
|
708
|
+
};
|
|
457
709
|
const HISTORY_RESTORE_SUPPRESSION_MS = 100;
|
|
458
710
|
const HISTORY_BATCH_FLUSH_MS = 16;
|
|
459
711
|
function cloneDocumentSnapshot(document2) {
|
|
@@ -526,12 +778,15 @@ function getPageNumber(document2, pageId) {
|
|
|
526
778
|
const index = document2.pages.findIndex((page) => page.id === pageId);
|
|
527
779
|
return index >= 0 ? index + 1 : null;
|
|
528
780
|
}
|
|
529
|
-
function describeAction(action, document2) {
|
|
781
|
+
function describeAction(action, document2, t) {
|
|
782
|
+
const pageSuffix = (pageId) => {
|
|
783
|
+
const num = getPageNumber(document2, pageId);
|
|
784
|
+
return num ? ` - ${interpolate(t.regions.page, { page: num })}` : "";
|
|
785
|
+
};
|
|
530
786
|
switch (action.type) {
|
|
531
787
|
case "UPDATE_PAGE_BODY": {
|
|
532
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
533
788
|
return {
|
|
534
|
-
label:
|
|
789
|
+
label: t.historyLabels.editedBody + pageSuffix(action.pageId),
|
|
535
790
|
source: "body",
|
|
536
791
|
pageId: action.pageId,
|
|
537
792
|
region: "body"
|
|
@@ -539,9 +794,8 @@ function describeAction(action, document2) {
|
|
|
539
794
|
}
|
|
540
795
|
case "UPDATE_PAGE_HEADER":
|
|
541
796
|
case "UPDATE_PAGE_HEADER_CONTENT": {
|
|
542
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
543
797
|
return {
|
|
544
|
-
label:
|
|
798
|
+
label: t.historyLabels.editedHeader + pageSuffix(action.pageId),
|
|
545
799
|
source: "header",
|
|
546
800
|
pageId: action.pageId,
|
|
547
801
|
region: "header"
|
|
@@ -549,9 +803,8 @@ function describeAction(action, document2) {
|
|
|
549
803
|
}
|
|
550
804
|
case "UPDATE_PAGE_FOOTER":
|
|
551
805
|
case "UPDATE_PAGE_FOOTER_CONTENT": {
|
|
552
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
553
806
|
return {
|
|
554
|
-
label:
|
|
807
|
+
label: t.historyLabels.editedFooter + pageSuffix(action.pageId),
|
|
555
808
|
source: "footer",
|
|
556
809
|
pageId: action.pageId,
|
|
557
810
|
region: "footer"
|
|
@@ -559,43 +812,41 @@ function describeAction(action, document2) {
|
|
|
559
812
|
}
|
|
560
813
|
case "SET_HEADER_FOOTER_ENABLED":
|
|
561
814
|
return {
|
|
562
|
-
label: action.enabled ?
|
|
815
|
+
label: action.enabled ? t.history.actions.enabledHeadersFooters : t.history.actions.disabledHeadersFooters,
|
|
563
816
|
source: "document",
|
|
564
817
|
region: "document"
|
|
565
818
|
};
|
|
566
819
|
case "SET_PAGE_COUNTER_MODE":
|
|
567
820
|
return {
|
|
568
|
-
label:
|
|
821
|
+
label: interpolate(t.history.actions.pageCounterSet, { value: action.mode }),
|
|
569
822
|
source: "document",
|
|
570
823
|
region: "document"
|
|
571
824
|
};
|
|
572
825
|
case "COPY_HEADER_TO_ALL":
|
|
573
826
|
return {
|
|
574
|
-
label:
|
|
827
|
+
label: t.history.actions.copiedHeaderToAll,
|
|
575
828
|
source: "toolbar",
|
|
576
829
|
pageId: action.sourcePageId,
|
|
577
830
|
region: "header"
|
|
578
831
|
};
|
|
579
832
|
case "COPY_FOOTER_TO_ALL":
|
|
580
833
|
return {
|
|
581
|
-
label:
|
|
834
|
+
label: t.history.actions.copiedFooterToAll,
|
|
582
835
|
source: "toolbar",
|
|
583
836
|
pageId: action.sourcePageId,
|
|
584
837
|
region: "footer"
|
|
585
838
|
};
|
|
586
839
|
case "CLEAR_HEADER": {
|
|
587
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
588
840
|
return {
|
|
589
|
-
label:
|
|
841
|
+
label: t.history.actions.clearedHeader + pageSuffix(action.pageId),
|
|
590
842
|
source: "toolbar",
|
|
591
843
|
pageId: action.pageId,
|
|
592
844
|
region: "header"
|
|
593
845
|
};
|
|
594
846
|
}
|
|
595
847
|
case "CLEAR_FOOTER": {
|
|
596
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
597
848
|
return {
|
|
598
|
-
label:
|
|
849
|
+
label: t.history.actions.clearedFooter + pageSuffix(action.pageId),
|
|
599
850
|
source: "toolbar",
|
|
600
851
|
pageId: action.pageId,
|
|
601
852
|
region: "footer"
|
|
@@ -603,35 +854,33 @@ function describeAction(action, document2) {
|
|
|
603
854
|
}
|
|
604
855
|
case "CLEAR_ALL_HEADERS":
|
|
605
856
|
return {
|
|
606
|
-
label:
|
|
857
|
+
label: t.history.actions.clearedAllHeaders,
|
|
607
858
|
source: "toolbar",
|
|
608
859
|
region: "header"
|
|
609
860
|
};
|
|
610
861
|
case "CLEAR_ALL_FOOTERS":
|
|
611
862
|
return {
|
|
612
|
-
label:
|
|
863
|
+
label: t.history.actions.clearedAllFooters,
|
|
613
864
|
source: "toolbar",
|
|
614
865
|
region: "footer"
|
|
615
866
|
};
|
|
616
867
|
case "CLEAR_DOCUMENT_CONTENT":
|
|
617
868
|
return {
|
|
618
|
-
label:
|
|
869
|
+
label: t.historyLabels.clearedDocumentBody,
|
|
619
870
|
source: "document",
|
|
620
871
|
region: "document"
|
|
621
872
|
};
|
|
622
873
|
case "SET_HEADER_HEIGHT": {
|
|
623
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
624
874
|
return {
|
|
625
|
-
label:
|
|
875
|
+
label: t.historyLabels.resizedHeader + pageSuffix(action.pageId),
|
|
626
876
|
source: "header",
|
|
627
877
|
pageId: action.pageId,
|
|
628
878
|
region: "header"
|
|
629
879
|
};
|
|
630
880
|
}
|
|
631
881
|
case "SET_FOOTER_HEIGHT": {
|
|
632
|
-
const pageNumber = getPageNumber(document2, action.pageId);
|
|
633
882
|
return {
|
|
634
|
-
label:
|
|
883
|
+
label: t.historyLabels.resizedFooter + pageSuffix(action.pageId),
|
|
635
884
|
source: "footer",
|
|
636
885
|
pageId: action.pageId,
|
|
637
886
|
region: "footer"
|
|
@@ -639,25 +888,25 @@ function describeAction(action, document2) {
|
|
|
639
888
|
}
|
|
640
889
|
case "ADD_PAGE":
|
|
641
890
|
return {
|
|
642
|
-
label:
|
|
891
|
+
label: t.historyLabels.addedPage,
|
|
643
892
|
source: "overflow",
|
|
644
893
|
region: "document"
|
|
645
894
|
};
|
|
646
895
|
case "REMOVE_PAGE":
|
|
647
896
|
return {
|
|
648
|
-
label:
|
|
897
|
+
label: t.historyLabels.removedPage,
|
|
649
898
|
source: "overflow",
|
|
650
899
|
region: "document"
|
|
651
900
|
};
|
|
652
901
|
case "SET_DOCUMENT":
|
|
653
902
|
return {
|
|
654
|
-
label:
|
|
903
|
+
label: t.historyLabels.documentReflow,
|
|
655
904
|
source: "overflow",
|
|
656
905
|
region: "document"
|
|
657
906
|
};
|
|
658
907
|
default:
|
|
659
908
|
return {
|
|
660
|
-
label:
|
|
909
|
+
label: t.historyLabels.updatedDocument,
|
|
661
910
|
source: "document",
|
|
662
911
|
region: "document"
|
|
663
912
|
};
|
|
@@ -684,6 +933,7 @@ const DocumentProvider = ({
|
|
|
684
933
|
const [globalSelectionActive, setGlobalSelectionActive] = React.useState(false);
|
|
685
934
|
const [historySidebarOpen, setHistorySidebarOpen] = React.useState(true);
|
|
686
935
|
const [focusAtEndVersion, setFocusAtEndVersion] = React.useState(0);
|
|
936
|
+
const t = useTranslations();
|
|
687
937
|
const activeEditorRef = React.useRef(null);
|
|
688
938
|
const activeCaretPositionRef = React.useRef(null);
|
|
689
939
|
const pendingCaretPositionRef = React.useRef(null);
|
|
@@ -877,7 +1127,7 @@ const DocumentProvider = ({
|
|
|
877
1127
|
};
|
|
878
1128
|
scheduleHistoryBatchFlush();
|
|
879
1129
|
} else {
|
|
880
|
-
const descriptor = describeAction(action, currentDocument);
|
|
1130
|
+
const descriptor = describeAction(action, currentDocument, t);
|
|
881
1131
|
setHistoryState((previousHistory) => {
|
|
882
1132
|
const nextHistory = recordHistoryEntry(
|
|
883
1133
|
previousHistory,
|
|
@@ -1136,20 +1386,33 @@ const createLucideIcon = (iconName, iconNode) => {
|
|
|
1136
1386
|
* This source code is licensed under the ISC license.
|
|
1137
1387
|
* See the LICENSE file in the root directory of this source tree.
|
|
1138
1388
|
*/
|
|
1139
|
-
const __iconNode$
|
|
1389
|
+
const __iconNode$q = [
|
|
1390
|
+
["path", { d: "m15 16 2.536-7.328a1.02 1.02 1 0 1 1.928 0L22 16", key: "xik6mr" }],
|
|
1391
|
+
["path", { d: "M15.697 14h5.606", key: "1stdlc" }],
|
|
1392
|
+
["path", { d: "m2 16 4.039-9.69a.5.5 0 0 1 .923 0L11 16", key: "d5nyq2" }],
|
|
1393
|
+
["path", { d: "M3.304 13h6.392", key: "1q3zxz" }]
|
|
1394
|
+
];
|
|
1395
|
+
const ALargeSmall = createLucideIcon("a-large-small", __iconNode$q);
|
|
1396
|
+
/**
|
|
1397
|
+
* @license lucide-react v1.8.0 - ISC
|
|
1398
|
+
*
|
|
1399
|
+
* This source code is licensed under the ISC license.
|
|
1400
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1401
|
+
*/
|
|
1402
|
+
const __iconNode$p = [
|
|
1140
1403
|
[
|
|
1141
1404
|
"path",
|
|
1142
1405
|
{ 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" }
|
|
1143
1406
|
]
|
|
1144
1407
|
];
|
|
1145
|
-
const Bold = createLucideIcon("bold", __iconNode$
|
|
1408
|
+
const Bold = createLucideIcon("bold", __iconNode$p);
|
|
1146
1409
|
/**
|
|
1147
1410
|
* @license lucide-react v1.8.0 - ISC
|
|
1148
1411
|
*
|
|
1149
1412
|
* This source code is licensed under the ISC license.
|
|
1150
1413
|
* See the LICENSE file in the root directory of this source tree.
|
|
1151
1414
|
*/
|
|
1152
|
-
const __iconNode$
|
|
1415
|
+
const __iconNode$o = [
|
|
1153
1416
|
[
|
|
1154
1417
|
"path",
|
|
1155
1418
|
{ 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" }
|
|
@@ -1162,27 +1425,35 @@ const __iconNode$l = [
|
|
|
1162
1425
|
}
|
|
1163
1426
|
]
|
|
1164
1427
|
];
|
|
1165
|
-
const Braces = createLucideIcon("braces", __iconNode$
|
|
1428
|
+
const Braces = createLucideIcon("braces", __iconNode$o);
|
|
1166
1429
|
/**
|
|
1167
1430
|
* @license lucide-react v1.8.0 - ISC
|
|
1168
1431
|
*
|
|
1169
1432
|
* This source code is licensed under the ISC license.
|
|
1170
1433
|
* See the LICENSE file in the root directory of this source tree.
|
|
1171
1434
|
*/
|
|
1172
|
-
const __iconNode$
|
|
1435
|
+
const __iconNode$n = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
|
|
1436
|
+
const ChevronDown = createLucideIcon("chevron-down", __iconNode$n);
|
|
1437
|
+
/**
|
|
1438
|
+
* @license lucide-react v1.8.0 - ISC
|
|
1439
|
+
*
|
|
1440
|
+
* This source code is licensed under the ISC license.
|
|
1441
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1442
|
+
*/
|
|
1443
|
+
const __iconNode$m = [
|
|
1173
1444
|
["line", { x1: "15", x2: "15", y1: "12", y2: "18", key: "1p7wdc" }],
|
|
1174
1445
|
["line", { x1: "12", x2: "18", y1: "15", y2: "15", key: "1nscbv" }],
|
|
1175
1446
|
["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2", key: "17jyea" }],
|
|
1176
1447
|
["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" }]
|
|
1177
1448
|
];
|
|
1178
|
-
const CopyPlus = createLucideIcon("copy-plus", __iconNode$
|
|
1449
|
+
const CopyPlus = createLucideIcon("copy-plus", __iconNode$m);
|
|
1179
1450
|
/**
|
|
1180
1451
|
* @license lucide-react v1.8.0 - ISC
|
|
1181
1452
|
*
|
|
1182
1453
|
* This source code is licensed under the ISC license.
|
|
1183
1454
|
* See the LICENSE file in the root directory of this source tree.
|
|
1184
1455
|
*/
|
|
1185
|
-
const __iconNode$
|
|
1456
|
+
const __iconNode$l = [
|
|
1186
1457
|
[
|
|
1187
1458
|
"path",
|
|
1188
1459
|
{
|
|
@@ -1192,65 +1463,52 @@ const __iconNode$j = [
|
|
|
1192
1463
|
],
|
|
1193
1464
|
["path", { d: "m5.082 11.09 8.828 8.828", key: "1wx5vj" }]
|
|
1194
1465
|
];
|
|
1195
|
-
const Eraser = createLucideIcon("eraser", __iconNode$
|
|
1466
|
+
const Eraser = createLucideIcon("eraser", __iconNode$l);
|
|
1196
1467
|
/**
|
|
1197
1468
|
* @license lucide-react v1.8.0 - ISC
|
|
1198
1469
|
*
|
|
1199
1470
|
* This source code is licensed under the ISC license.
|
|
1200
1471
|
* See the LICENSE file in the root directory of this source tree.
|
|
1201
1472
|
*/
|
|
1202
|
-
const __iconNode$
|
|
1203
|
-
["line", { x1: "4", x2: "20", y1: "9", y2: "9", key: "4lhtct" }],
|
|
1204
|
-
["line", { x1: "4", x2: "20", y1: "15", y2: "15", key: "vyu0kd" }],
|
|
1205
|
-
["line", { x1: "10", x2: "8", y1: "3", y2: "21", key: "1ggp8o" }],
|
|
1206
|
-
["line", { x1: "16", x2: "14", y1: "3", y2: "21", key: "weycgp" }]
|
|
1207
|
-
];
|
|
1208
|
-
const Hash = createLucideIcon("hash", __iconNode$i);
|
|
1209
|
-
/**
|
|
1210
|
-
* @license lucide-react v1.8.0 - ISC
|
|
1211
|
-
*
|
|
1212
|
-
* This source code is licensed under the ISC license.
|
|
1213
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
1214
|
-
*/
|
|
1215
|
-
const __iconNode$h = [
|
|
1473
|
+
const __iconNode$k = [
|
|
1216
1474
|
["line", { x1: "19", x2: "10", y1: "4", y2: "4", key: "15jd3p" }],
|
|
1217
1475
|
["line", { x1: "14", x2: "5", y1: "20", y2: "20", key: "bu0au3" }],
|
|
1218
1476
|
["line", { x1: "15", x2: "9", y1: "4", y2: "20", key: "uljnxc" }]
|
|
1219
1477
|
];
|
|
1220
|
-
const Italic = createLucideIcon("italic", __iconNode$
|
|
1478
|
+
const Italic = createLucideIcon("italic", __iconNode$k);
|
|
1221
1479
|
/**
|
|
1222
1480
|
* @license lucide-react v1.8.0 - ISC
|
|
1223
1481
|
*
|
|
1224
1482
|
* This source code is licensed under the ISC license.
|
|
1225
1483
|
* See the LICENSE file in the root directory of this source tree.
|
|
1226
1484
|
*/
|
|
1227
|
-
const __iconNode$
|
|
1485
|
+
const __iconNode$j = [
|
|
1228
1486
|
["path", { d: "M21 5H11", key: "us1j55" }],
|
|
1229
1487
|
["path", { d: "M21 12H11", key: "wd7e0v" }],
|
|
1230
1488
|
["path", { d: "M21 19H11", key: "saa85w" }],
|
|
1231
1489
|
["path", { d: "m7 8-4 4 4 4", key: "o5hrat" }]
|
|
1232
1490
|
];
|
|
1233
|
-
const ListIndentDecrease = createLucideIcon("list-indent-decrease", __iconNode$
|
|
1491
|
+
const ListIndentDecrease = createLucideIcon("list-indent-decrease", __iconNode$j);
|
|
1234
1492
|
/**
|
|
1235
1493
|
* @license lucide-react v1.8.0 - ISC
|
|
1236
1494
|
*
|
|
1237
1495
|
* This source code is licensed under the ISC license.
|
|
1238
1496
|
* See the LICENSE file in the root directory of this source tree.
|
|
1239
1497
|
*/
|
|
1240
|
-
const __iconNode$
|
|
1498
|
+
const __iconNode$i = [
|
|
1241
1499
|
["path", { d: "M21 5H11", key: "us1j55" }],
|
|
1242
1500
|
["path", { d: "M21 12H11", key: "wd7e0v" }],
|
|
1243
1501
|
["path", { d: "M21 19H11", key: "saa85w" }],
|
|
1244
1502
|
["path", { d: "m3 8 4 4-4 4", key: "1a3j6y" }]
|
|
1245
1503
|
];
|
|
1246
|
-
const ListIndentIncrease = createLucideIcon("list-indent-increase", __iconNode$
|
|
1504
|
+
const ListIndentIncrease = createLucideIcon("list-indent-increase", __iconNode$i);
|
|
1247
1505
|
/**
|
|
1248
1506
|
* @license lucide-react v1.8.0 - ISC
|
|
1249
1507
|
*
|
|
1250
1508
|
* This source code is licensed under the ISC license.
|
|
1251
1509
|
* See the LICENSE file in the root directory of this source tree.
|
|
1252
1510
|
*/
|
|
1253
|
-
const __iconNode$
|
|
1511
|
+
const __iconNode$h = [
|
|
1254
1512
|
["path", { d: "M11 5h10", key: "1cz7ny" }],
|
|
1255
1513
|
["path", { d: "M11 12h10", key: "1438ji" }],
|
|
1256
1514
|
["path", { d: "M11 19h10", key: "11t30w" }],
|
|
@@ -1258,14 +1516,14 @@ const __iconNode$e = [
|
|
|
1258
1516
|
["path", { d: "M4 9h2", key: "r1h2o0" }],
|
|
1259
1517
|
["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" }]
|
|
1260
1518
|
];
|
|
1261
|
-
const ListOrdered = createLucideIcon("list-ordered", __iconNode$
|
|
1519
|
+
const ListOrdered = createLucideIcon("list-ordered", __iconNode$h);
|
|
1262
1520
|
/**
|
|
1263
1521
|
* @license lucide-react v1.8.0 - ISC
|
|
1264
1522
|
*
|
|
1265
1523
|
* This source code is licensed under the ISC license.
|
|
1266
1524
|
* See the LICENSE file in the root directory of this source tree.
|
|
1267
1525
|
*/
|
|
1268
|
-
const __iconNode$
|
|
1526
|
+
const __iconNode$g = [
|
|
1269
1527
|
["path", { d: "M3 5h.01", key: "18ugdj" }],
|
|
1270
1528
|
["path", { d: "M3 12h.01", key: "nlz23k" }],
|
|
1271
1529
|
["path", { d: "M3 19h.01", key: "noohij" }],
|
|
@@ -1273,127 +1531,168 @@ const __iconNode$d = [
|
|
|
1273
1531
|
["path", { d: "M8 12h13", key: "1za7za" }],
|
|
1274
1532
|
["path", { d: "M8 19h13", key: "m83p4d" }]
|
|
1275
1533
|
];
|
|
1276
|
-
const List = createLucideIcon("list", __iconNode$
|
|
1534
|
+
const List = createLucideIcon("list", __iconNode$g);
|
|
1277
1535
|
/**
|
|
1278
1536
|
* @license lucide-react v1.8.0 - ISC
|
|
1279
1537
|
*
|
|
1280
1538
|
* This source code is licensed under the ISC license.
|
|
1281
1539
|
* See the LICENSE file in the root directory of this source tree.
|
|
1282
1540
|
*/
|
|
1283
|
-
const __iconNode$
|
|
1541
|
+
const __iconNode$f = [
|
|
1284
1542
|
["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
|
|
1285
1543
|
["path", { d: "M15 3v18", key: "14nvp0" }]
|
|
1286
1544
|
];
|
|
1287
|
-
const PanelRight = createLucideIcon("panel-right", __iconNode$
|
|
1545
|
+
const PanelRight = createLucideIcon("panel-right", __iconNode$f);
|
|
1288
1546
|
/**
|
|
1289
1547
|
* @license lucide-react v1.8.0 - ISC
|
|
1290
1548
|
*
|
|
1291
1549
|
* This source code is licensed under the ISC license.
|
|
1292
1550
|
* See the LICENSE file in the root directory of this source tree.
|
|
1293
1551
|
*/
|
|
1294
|
-
const __iconNode$
|
|
1552
|
+
const __iconNode$e = [
|
|
1295
1553
|
["path", { d: "m15 14 5-5-5-5", key: "12vg1m" }],
|
|
1296
1554
|
["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" }]
|
|
1297
1555
|
];
|
|
1298
|
-
const Redo2 = createLucideIcon("redo-2", __iconNode$
|
|
1556
|
+
const Redo2 = createLucideIcon("redo-2", __iconNode$e);
|
|
1299
1557
|
/**
|
|
1300
1558
|
* @license lucide-react v1.8.0 - ISC
|
|
1301
1559
|
*
|
|
1302
1560
|
* This source code is licensed under the ISC license.
|
|
1303
1561
|
* See the LICENSE file in the root directory of this source tree.
|
|
1304
1562
|
*/
|
|
1305
|
-
const __iconNode$
|
|
1563
|
+
const __iconNode$d = [
|
|
1306
1564
|
["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
|
|
1307
1565
|
["path", { d: "M21 3v5h-5", key: "1q7to0" }],
|
|
1308
1566
|
["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
|
|
1309
1567
|
["path", { d: "M8 16H3v5", key: "1cv678" }]
|
|
1310
1568
|
];
|
|
1311
|
-
const RefreshCw = createLucideIcon("refresh-cw", __iconNode$
|
|
1569
|
+
const RefreshCw = createLucideIcon("refresh-cw", __iconNode$d);
|
|
1312
1570
|
/**
|
|
1313
1571
|
* @license lucide-react v1.8.0 - ISC
|
|
1314
1572
|
*
|
|
1315
1573
|
* This source code is licensed under the ISC license.
|
|
1316
1574
|
* See the LICENSE file in the root directory of this source tree.
|
|
1317
1575
|
*/
|
|
1318
|
-
const __iconNode$
|
|
1576
|
+
const __iconNode$c = [
|
|
1577
|
+
["rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", key: "afitv7" }],
|
|
1578
|
+
["path", { d: "M21 9H3", key: "1338ky" }],
|
|
1579
|
+
["path", { d: "M21 15H3", key: "9uk58r" }]
|
|
1580
|
+
];
|
|
1581
|
+
const Rows3 = createLucideIcon("rows-3", __iconNode$c);
|
|
1582
|
+
/**
|
|
1583
|
+
* @license lucide-react v1.8.0 - ISC
|
|
1584
|
+
*
|
|
1585
|
+
* This source code is licensed under the ISC license.
|
|
1586
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1587
|
+
*/
|
|
1588
|
+
const __iconNode$b = [
|
|
1319
1589
|
["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
|
|
1320
1590
|
["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
|
|
1321
1591
|
];
|
|
1322
|
-
const Search = createLucideIcon("search", __iconNode$
|
|
1592
|
+
const Search = createLucideIcon("search", __iconNode$b);
|
|
1323
1593
|
/**
|
|
1324
1594
|
* @license lucide-react v1.8.0 - ISC
|
|
1325
1595
|
*
|
|
1326
1596
|
* This source code is licensed under the ISC license.
|
|
1327
1597
|
* See the LICENSE file in the root directory of this source tree.
|
|
1328
1598
|
*/
|
|
1329
|
-
const __iconNode$
|
|
1599
|
+
const __iconNode$a = [
|
|
1600
|
+
[
|
|
1601
|
+
"path",
|
|
1602
|
+
{
|
|
1603
|
+
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",
|
|
1604
|
+
key: "1i5ecw"
|
|
1605
|
+
}
|
|
1606
|
+
],
|
|
1607
|
+
["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
|
|
1608
|
+
];
|
|
1609
|
+
const Settings = createLucideIcon("settings", __iconNode$a);
|
|
1610
|
+
/**
|
|
1611
|
+
* @license lucide-react v1.8.0 - ISC
|
|
1612
|
+
*
|
|
1613
|
+
* This source code is licensed under the ISC license.
|
|
1614
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1615
|
+
*/
|
|
1616
|
+
const __iconNode$9 = [
|
|
1330
1617
|
["path", { d: "M16 4H9a3 3 0 0 0-2.83 4", key: "43sutm" }],
|
|
1331
1618
|
["path", { d: "M14 12a4 4 0 0 1 0 8H6", key: "nlfj13" }],
|
|
1332
1619
|
["line", { x1: "4", x2: "20", y1: "12", y2: "12", key: "1e0a9i" }]
|
|
1333
1620
|
];
|
|
1334
|
-
const Strikethrough = createLucideIcon("strikethrough", __iconNode$
|
|
1621
|
+
const Strikethrough = createLucideIcon("strikethrough", __iconNode$9);
|
|
1335
1622
|
/**
|
|
1336
1623
|
* @license lucide-react v1.8.0 - ISC
|
|
1337
1624
|
*
|
|
1338
1625
|
* This source code is licensed under the ISC license.
|
|
1339
1626
|
* See the LICENSE file in the root directory of this source tree.
|
|
1340
1627
|
*/
|
|
1341
|
-
const __iconNode$
|
|
1628
|
+
const __iconNode$8 = [
|
|
1342
1629
|
["path", { d: "M21 5H3", key: "1fi0y6" }],
|
|
1343
1630
|
["path", { d: "M17 12H7", key: "16if0g" }],
|
|
1344
1631
|
["path", { d: "M19 19H5", key: "vjpgq2" }]
|
|
1345
1632
|
];
|
|
1346
|
-
const TextAlignCenter = createLucideIcon("text-align-center", __iconNode$
|
|
1633
|
+
const TextAlignCenter = createLucideIcon("text-align-center", __iconNode$8);
|
|
1347
1634
|
/**
|
|
1348
1635
|
* @license lucide-react v1.8.0 - ISC
|
|
1349
1636
|
*
|
|
1350
1637
|
* This source code is licensed under the ISC license.
|
|
1351
1638
|
* See the LICENSE file in the root directory of this source tree.
|
|
1352
1639
|
*/
|
|
1353
|
-
const __iconNode$
|
|
1640
|
+
const __iconNode$7 = [
|
|
1354
1641
|
["path", { d: "M21 5H3", key: "1fi0y6" }],
|
|
1355
1642
|
["path", { d: "M21 12H9", key: "dn1m92" }],
|
|
1356
1643
|
["path", { d: "M21 19H7", key: "4cu937" }]
|
|
1357
1644
|
];
|
|
1358
|
-
const TextAlignEnd = createLucideIcon("text-align-end", __iconNode$
|
|
1645
|
+
const TextAlignEnd = createLucideIcon("text-align-end", __iconNode$7);
|
|
1359
1646
|
/**
|
|
1360
1647
|
* @license lucide-react v1.8.0 - ISC
|
|
1361
1648
|
*
|
|
1362
1649
|
* This source code is licensed under the ISC license.
|
|
1363
1650
|
* See the LICENSE file in the root directory of this source tree.
|
|
1364
1651
|
*/
|
|
1365
|
-
const __iconNode$
|
|
1652
|
+
const __iconNode$6 = [
|
|
1366
1653
|
["path", { d: "M3 5h18", key: "1u36vt" }],
|
|
1367
1654
|
["path", { d: "M3 12h18", key: "1i2n21" }],
|
|
1368
1655
|
["path", { d: "M3 19h18", key: "awlh7x" }]
|
|
1369
1656
|
];
|
|
1370
|
-
const TextAlignJustify = createLucideIcon("text-align-justify", __iconNode$
|
|
1657
|
+
const TextAlignJustify = createLucideIcon("text-align-justify", __iconNode$6);
|
|
1371
1658
|
/**
|
|
1372
1659
|
* @license lucide-react v1.8.0 - ISC
|
|
1373
1660
|
*
|
|
1374
1661
|
* This source code is licensed under the ISC license.
|
|
1375
1662
|
* See the LICENSE file in the root directory of this source tree.
|
|
1376
1663
|
*/
|
|
1377
|
-
const __iconNode$
|
|
1664
|
+
const __iconNode$5 = [
|
|
1378
1665
|
["path", { d: "M21 5H3", key: "1fi0y6" }],
|
|
1379
1666
|
["path", { d: "M15 12H3", key: "6jk70r" }],
|
|
1380
1667
|
["path", { d: "M17 19H3", key: "z6ezky" }]
|
|
1381
1668
|
];
|
|
1382
|
-
const TextAlignStart = createLucideIcon("text-align-start", __iconNode$
|
|
1669
|
+
const TextAlignStart = createLucideIcon("text-align-start", __iconNode$5);
|
|
1383
1670
|
/**
|
|
1384
1671
|
* @license lucide-react v1.8.0 - ISC
|
|
1385
1672
|
*
|
|
1386
1673
|
* This source code is licensed under the ISC license.
|
|
1387
1674
|
* See the LICENSE file in the root directory of this source tree.
|
|
1388
1675
|
*/
|
|
1389
|
-
const __iconNode$
|
|
1676
|
+
const __iconNode$4 = [
|
|
1390
1677
|
["path", { d: "M10 11v6", key: "nco0om" }],
|
|
1391
1678
|
["path", { d: "M14 11v6", key: "outv1u" }],
|
|
1392
1679
|
["path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6", key: "miytrc" }],
|
|
1393
1680
|
["path", { d: "M3 6h18", key: "d0wm0j" }],
|
|
1394
1681
|
["path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2", key: "e791ji" }]
|
|
1395
1682
|
];
|
|
1396
|
-
const Trash2 = createLucideIcon("trash-2", __iconNode$
|
|
1683
|
+
const Trash2 = createLucideIcon("trash-2", __iconNode$4);
|
|
1684
|
+
/**
|
|
1685
|
+
* @license lucide-react v1.8.0 - ISC
|
|
1686
|
+
*
|
|
1687
|
+
* This source code is licensed under the ISC license.
|
|
1688
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1689
|
+
*/
|
|
1690
|
+
const __iconNode$3 = [
|
|
1691
|
+
["path", { d: "M12 4v16", key: "1654pz" }],
|
|
1692
|
+
["path", { d: "M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2", key: "e0r10z" }],
|
|
1693
|
+
["path", { d: "M9 20h6", key: "s66wpe" }]
|
|
1694
|
+
];
|
|
1695
|
+
const Type = createLucideIcon("type", __iconNode$3);
|
|
1397
1696
|
/**
|
|
1398
1697
|
* @license lucide-react v1.8.0 - ISC
|
|
1399
1698
|
*
|
|
@@ -1416,123 +1715,17 @@ const __iconNode$1 = [
|
|
|
1416
1715
|
["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" }]
|
|
1417
1716
|
];
|
|
1418
1717
|
const Undo2 = createLucideIcon("undo-2", __iconNode$1);
|
|
1419
|
-
/**
|
|
1420
|
-
* @license lucide-react v1.8.0 - ISC
|
|
1421
|
-
*
|
|
1422
|
-
* This source code is licensed under the ISC license.
|
|
1423
|
-
* See the LICENSE file in the root directory of this source tree.
|
|
1424
|
-
*/
|
|
1425
|
-
const __iconNode = [
|
|
1426
|
-
["path", { d: "M18 6 6 18", key: "1bl5f8" }],
|
|
1427
|
-
["path", { d: "m6 6 12 12", key: "d8bk6v" }]
|
|
1428
|
-
];
|
|
1429
|
-
const X = createLucideIcon("x", __iconNode);
|
|
1430
|
-
const DEFAULT_TRANSLATIONS = {
|
|
1431
|
-
toolbar: {
|
|
1432
|
-
undo: "Undo",
|
|
1433
|
-
redo: "Redo",
|
|
1434
|
-
bold: "Bold (Ctrl+B)",
|
|
1435
|
-
italic: "Italic (Ctrl+I)",
|
|
1436
|
-
underline: "Underline (Ctrl+U)",
|
|
1437
|
-
strikethrough: "Strikethrough",
|
|
1438
|
-
alignLeft: "Align Left",
|
|
1439
|
-
alignCenter: "Align Center",
|
|
1440
|
-
alignRight: "Align Right",
|
|
1441
|
-
justify: "Justify",
|
|
1442
|
-
numberedList: "Numbered List",
|
|
1443
|
-
bulletList: "Bullet List",
|
|
1444
|
-
indent: "Indent",
|
|
1445
|
-
outdent: "Outdent",
|
|
1446
|
-
openHistory: "Open History",
|
|
1447
|
-
closeHistory: "Close History"
|
|
1448
|
-
},
|
|
1449
|
-
history: {
|
|
1450
|
-
title: "History",
|
|
1451
|
-
subtitle: "Word-style session history (last 100 actions)",
|
|
1452
|
-
empty: "No history yet.",
|
|
1453
|
-
clearHistory: "Clear History",
|
|
1454
|
-
actions: {
|
|
1455
|
-
enabledHeadersFooters: "Enabled headers and footers",
|
|
1456
|
-
disabledHeadersFooters: "Disabled headers and footers",
|
|
1457
|
-
copiedHeaderToAll: "Copied header to all pages",
|
|
1458
|
-
copiedFooterToAll: "Copied footer to all pages",
|
|
1459
|
-
clearedHeader: "Cleared header",
|
|
1460
|
-
clearedFooter: "Cleared footer",
|
|
1461
|
-
clearedAllHeaders: "Cleared all headers",
|
|
1462
|
-
clearedAllFooters: "Cleared all footers",
|
|
1463
|
-
pageCounterSet: "Page counter set to {{value}}",
|
|
1464
|
-
boldApplied: "Bold applied",
|
|
1465
|
-
italicApplied: "Italic applied",
|
|
1466
|
-
underlineApplied: "Underline applied",
|
|
1467
|
-
strikethroughApplied: "Strikethrough applied",
|
|
1468
|
-
alignedLeft: "Aligned left",
|
|
1469
|
-
alignedCenter: "Aligned center",
|
|
1470
|
-
alignedRight: "Aligned right",
|
|
1471
|
-
justifiedText: "Justified text",
|
|
1472
|
-
insertedNumberedList: "Inserted numbered list",
|
|
1473
|
-
insertedBulletList: "Inserted bullet list",
|
|
1474
|
-
indentedContent: "Indented content",
|
|
1475
|
-
outdentedContent: "Outdented content",
|
|
1476
|
-
fontChanged: "Font changed to {{value}}",
|
|
1477
|
-
fontSizeChanged: "Font size changed to {{value}}pt"
|
|
1478
|
-
}
|
|
1479
|
-
},
|
|
1480
|
-
variables: {
|
|
1481
|
-
title: "Variables",
|
|
1482
|
-
available: "{{count}} available",
|
|
1483
|
-
refreshVariables: "Refresh variables",
|
|
1484
|
-
searchPlaceholder: "Search variables...",
|
|
1485
|
-
noVariablesFound: "No variables found",
|
|
1486
|
-
insertVariable: "Insert variable {{key}}",
|
|
1487
|
-
openPanel: "Open Variables",
|
|
1488
|
-
closePanel: "Close Variables"
|
|
1489
|
-
},
|
|
1490
|
-
header: {
|
|
1491
|
-
placeholder: "Header"
|
|
1492
|
-
},
|
|
1493
|
-
footer: {
|
|
1494
|
-
placeholder: "Footer"
|
|
1495
|
-
},
|
|
1496
|
-
sidebar: {
|
|
1497
|
-
close: "Close sidebar"
|
|
1498
|
-
}
|
|
1499
|
-
};
|
|
1500
|
-
function deepMerge(target, source) {
|
|
1501
|
-
if (typeof target !== "object" || target === null) {
|
|
1502
|
-
return source ?? target;
|
|
1503
|
-
}
|
|
1504
|
-
const result = { ...target };
|
|
1505
|
-
for (const key of Object.keys(source)) {
|
|
1506
|
-
const sourceVal = source[key];
|
|
1507
|
-
const targetVal = target[key];
|
|
1508
|
-
if (sourceVal !== void 0 && typeof sourceVal === "object" && sourceVal !== null && !Array.isArray(sourceVal) && typeof targetVal === "object" && targetVal !== null) {
|
|
1509
|
-
result[key] = deepMerge(targetVal, sourceVal);
|
|
1510
|
-
} else if (sourceVal !== void 0) {
|
|
1511
|
-
result[key] = sourceVal;
|
|
1512
|
-
}
|
|
1513
|
-
}
|
|
1514
|
-
return result;
|
|
1515
|
-
}
|
|
1516
|
-
const TranslationsContext = React.createContext(DEFAULT_TRANSLATIONS);
|
|
1517
|
-
function useTranslations() {
|
|
1518
|
-
return React.useContext(TranslationsContext);
|
|
1519
|
-
}
|
|
1520
|
-
function interpolate(template, params) {
|
|
1521
|
-
return template.replace(
|
|
1522
|
-
/\{\{(\w+)\}\}/g,
|
|
1523
|
-
(_, key) => String(params[key] ?? `{{${key}}}`)
|
|
1524
|
-
);
|
|
1525
|
-
}
|
|
1526
|
-
const TranslationsProvider = ({
|
|
1527
|
-
translations,
|
|
1528
|
-
children
|
|
1529
|
-
}) => {
|
|
1530
|
-
const merged = React.useMemo(
|
|
1531
|
-
() => translations ? deepMerge(DEFAULT_TRANSLATIONS, translations) : DEFAULT_TRANSLATIONS,
|
|
1532
|
-
[translations]
|
|
1533
|
-
);
|
|
1534
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TranslationsContext.Provider, { value: merged, children });
|
|
1535
|
-
};
|
|
1718
|
+
/**
|
|
1719
|
+
* @license lucide-react v1.8.0 - ISC
|
|
1720
|
+
*
|
|
1721
|
+
* This source code is licensed under the ISC license.
|
|
1722
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
1723
|
+
*/
|
|
1724
|
+
const __iconNode = [
|
|
1725
|
+
["path", { d: "M18 6 6 18", key: "1bl5f8" }],
|
|
1726
|
+
["path", { d: "m6 6 12 12", key: "d8bk6v" }]
|
|
1727
|
+
];
|
|
1728
|
+
const X = createLucideIcon("x", __iconNode);
|
|
1536
1729
|
const EditorSidebar = ({
|
|
1537
1730
|
title,
|
|
1538
1731
|
subtitle,
|
|
@@ -1639,7 +1832,7 @@ const HistorySidebar = () => {
|
|
|
1639
1832
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
1640
1833
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
1641
1834
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `text-xs ${isCurrent ? "font-semibold text-blue-700" : "text-gray-900"}`, children: entry.label }),
|
|
1642
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-0.5 text-xs text-gray-400", children: entry.source })
|
|
1835
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-0.5 text-xs text-gray-400", children: t.regions[entry.source] ?? entry.source })
|
|
1643
1836
|
] }),
|
|
1644
1837
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 text-xs text-gray-400", children: formatTimestamp(entry.timestamp) })
|
|
1645
1838
|
] })
|
|
@@ -1653,13 +1846,15 @@ const HeaderFooterToggle = ({
|
|
|
1653
1846
|
enabled,
|
|
1654
1847
|
onToggle
|
|
1655
1848
|
}) => {
|
|
1849
|
+
const t = useTranslations();
|
|
1656
1850
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1657
1851
|
"label",
|
|
1658
1852
|
{
|
|
1659
1853
|
className: "flex items-center gap-1.5 cursor-pointer select-none",
|
|
1660
1854
|
"data-testid": "header-footer-toggle",
|
|
1661
1855
|
children: [
|
|
1662
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1856
|
+
/* @__PURE__ */ jsxRuntime.jsx(Rows3, { size: 14, className: "text-gray-500" }),
|
|
1857
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-600", children: t.headerFooter.label }),
|
|
1663
1858
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1664
1859
|
"button",
|
|
1665
1860
|
{
|
|
@@ -1690,6 +1885,12 @@ const HeaderFooterToggle = ({
|
|
|
1690
1885
|
}
|
|
1691
1886
|
);
|
|
1692
1887
|
};
|
|
1888
|
+
const PAGE_COUNTER_OPTIONS = [
|
|
1889
|
+
{ value: "none", label: "None" },
|
|
1890
|
+
{ value: "header", label: "Header" },
|
|
1891
|
+
{ value: "footer", label: "Footer" },
|
|
1892
|
+
{ value: "both", label: "Both" }
|
|
1893
|
+
];
|
|
1693
1894
|
const HeaderFooterActions = ({
|
|
1694
1895
|
activePageId,
|
|
1695
1896
|
pageCounterMode,
|
|
@@ -1701,119 +1902,154 @@ const HeaderFooterActions = ({
|
|
|
1701
1902
|
onClearAllHeaders,
|
|
1702
1903
|
onClearAllFooters
|
|
1703
1904
|
}) => {
|
|
1905
|
+
const [open, setOpen] = React.useState(false);
|
|
1906
|
+
const containerRef = React.useRef(null);
|
|
1704
1907
|
const hasActivePage = activePageId !== null;
|
|
1705
|
-
const
|
|
1706
|
-
|
|
1707
|
-
if (
|
|
1708
|
-
|
|
1709
|
-
|
|
1908
|
+
const close = React.useCallback(() => setOpen(false), []);
|
|
1909
|
+
React.useEffect(() => {
|
|
1910
|
+
if (!open) return;
|
|
1911
|
+
const handleClickOutside = (e) => {
|
|
1912
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
1913
|
+
close();
|
|
1914
|
+
}
|
|
1915
|
+
};
|
|
1916
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1917
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1918
|
+
}, [open, close]);
|
|
1919
|
+
const handleAction = (action) => {
|
|
1920
|
+
action();
|
|
1921
|
+
close();
|
|
1710
1922
|
};
|
|
1711
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1923
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative", "data-testid": "header-footer-actions", children: [
|
|
1924
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1925
|
+
"button",
|
|
1926
|
+
{
|
|
1927
|
+
type: "button",
|
|
1928
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
1929
|
+
onClick: () => setOpen(!open),
|
|
1930
|
+
className: `
|
|
1931
|
+
flex h-7 items-center gap-1 rounded px-1.5 text-xs transition-colors
|
|
1932
|
+
${open ? "bg-blue-50 text-blue-600" : "text-gray-600 hover:bg-gray-100 hover:text-gray-900"}
|
|
1933
|
+
`,
|
|
1934
|
+
"data-testid": "header-footer-menu-trigger",
|
|
1935
|
+
"aria-expanded": open,
|
|
1936
|
+
"aria-haspopup": "true",
|
|
1937
|
+
children: [
|
|
1938
|
+
/* @__PURE__ */ jsxRuntime.jsx(Settings, { size: 14 }),
|
|
1939
|
+
/* @__PURE__ */ jsxRuntime.jsx(ChevronDown, { size: 12 })
|
|
1940
|
+
]
|
|
1941
|
+
}
|
|
1942
|
+
),
|
|
1943
|
+
open && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1944
|
+
"div",
|
|
1945
|
+
{
|
|
1946
|
+
className: "absolute left-0 top-full mt-1 z-50 w-56 rounded-lg border border-gray-200 bg-white py-1 shadow-lg",
|
|
1947
|
+
role: "menu",
|
|
1948
|
+
"data-testid": "header-footer-menu",
|
|
1949
|
+
children: [
|
|
1950
|
+
/* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "Page counter" }),
|
|
1951
|
+
/* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(
|
|
1952
|
+
"button",
|
|
1721
1953
|
{
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
"
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1954
|
+
type: "button",
|
|
1955
|
+
role: "menuitemradio",
|
|
1956
|
+
"aria-checked": pageCounterMode === value,
|
|
1957
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
1958
|
+
onClick: () => onPageCounterModeChange(value),
|
|
1959
|
+
className: `
|
|
1960
|
+
rounded px-2 py-1 text-xs text-left transition-colors
|
|
1961
|
+
${pageCounterMode === value ? "bg-blue-50 text-blue-700 font-medium" : "text-gray-600 hover:bg-gray-100"}
|
|
1962
|
+
`,
|
|
1963
|
+
"data-testid": `page-counter-${value}`,
|
|
1964
|
+
children: label
|
|
1965
|
+
},
|
|
1966
|
+
value
|
|
1967
|
+
)) }),
|
|
1968
|
+
/* @__PURE__ */ jsxRuntime.jsx(MenuDivider, {}),
|
|
1969
|
+
/* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "Header" }),
|
|
1970
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1971
|
+
MenuItem,
|
|
1972
|
+
{
|
|
1973
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(CopyPlus, { size: 14 }),
|
|
1974
|
+
label: "Copy to all pages",
|
|
1975
|
+
onClick: () => handleAction(onCopyHeaderToAll),
|
|
1976
|
+
disabled: !hasActivePage,
|
|
1977
|
+
testId: "copy-header-all"
|
|
1978
|
+
}
|
|
1979
|
+
),
|
|
1980
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1981
|
+
MenuItem,
|
|
1982
|
+
{
|
|
1983
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Eraser, { size: 14 }),
|
|
1984
|
+
label: "Clear this page",
|
|
1985
|
+
onClick: () => handleAction(onClearHeader),
|
|
1986
|
+
disabled: !hasActivePage,
|
|
1987
|
+
testId: "clear-header"
|
|
1988
|
+
}
|
|
1989
|
+
),
|
|
1990
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1991
|
+
MenuItem,
|
|
1992
|
+
{
|
|
1993
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Trash2, { size: 14 }),
|
|
1994
|
+
label: "Clear all",
|
|
1995
|
+
onClick: () => handleAction(onClearAllHeaders),
|
|
1996
|
+
testId: "clear-all-headers"
|
|
1997
|
+
}
|
|
1998
|
+
),
|
|
1999
|
+
/* @__PURE__ */ jsxRuntime.jsx(MenuDivider, {}),
|
|
2000
|
+
/* @__PURE__ */ jsxRuntime.jsx(SectionLabel, { children: "Footer" }),
|
|
2001
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2002
|
+
MenuItem,
|
|
2003
|
+
{
|
|
2004
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(CopyPlus, { size: 14 }),
|
|
2005
|
+
label: "Copy to all pages",
|
|
2006
|
+
onClick: () => handleAction(onCopyFooterToAll),
|
|
2007
|
+
disabled: !hasActivePage,
|
|
2008
|
+
testId: "copy-footer-all"
|
|
2009
|
+
}
|
|
2010
|
+
),
|
|
2011
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2012
|
+
MenuItem,
|
|
2013
|
+
{
|
|
2014
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Eraser, { size: 14 }),
|
|
2015
|
+
label: "Clear this page",
|
|
2016
|
+
onClick: () => handleAction(onClearFooter),
|
|
2017
|
+
disabled: !hasActivePage,
|
|
2018
|
+
testId: "clear-footer"
|
|
2019
|
+
}
|
|
2020
|
+
),
|
|
2021
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2022
|
+
MenuItem,
|
|
2023
|
+
{
|
|
2024
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(Trash2, { size: 14 }),
|
|
2025
|
+
label: "Clear all",
|
|
2026
|
+
onClick: () => handleAction(onClearAllFooters),
|
|
2027
|
+
testId: "clear-all-footers"
|
|
1733
2028
|
}
|
|
1734
2029
|
)
|
|
1735
|
-
]
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
ActionIconButton,
|
|
1740
|
-
{
|
|
1741
|
-
title: "Copy header to all pages",
|
|
1742
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(CopyPlus, { size: 13 }),
|
|
1743
|
-
onClick: onCopyHeaderToAll,
|
|
1744
|
-
disabled: !hasActivePage,
|
|
1745
|
-
testId: "copy-header-all"
|
|
1746
|
-
}
|
|
1747
|
-
),
|
|
1748
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1749
|
-
ActionIconButton,
|
|
1750
|
-
{
|
|
1751
|
-
title: "Clear header on this page",
|
|
1752
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Eraser, { size: 13 }),
|
|
1753
|
-
onClick: onClearHeader,
|
|
1754
|
-
disabled: !hasActivePage,
|
|
1755
|
-
testId: "clear-header"
|
|
1756
|
-
}
|
|
1757
|
-
),
|
|
1758
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1759
|
-
ActionIconButton,
|
|
1760
|
-
{
|
|
1761
|
-
title: "Clear all headers",
|
|
1762
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Trash2, { size: 13 }),
|
|
1763
|
-
onClick: onClearAllHeaders,
|
|
1764
|
-
testId: "clear-all-headers"
|
|
1765
|
-
}
|
|
1766
|
-
),
|
|
1767
|
-
/* @__PURE__ */ jsxRuntime.jsx(ActionDivider, {}),
|
|
1768
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-400 font-medium", children: "Footer" }),
|
|
1769
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1770
|
-
ActionIconButton,
|
|
1771
|
-
{
|
|
1772
|
-
title: "Copy footer to all pages",
|
|
1773
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(CopyPlus, { size: 13 }),
|
|
1774
|
-
onClick: onCopyFooterToAll,
|
|
1775
|
-
disabled: !hasActivePage,
|
|
1776
|
-
testId: "copy-footer-all"
|
|
1777
|
-
}
|
|
1778
|
-
),
|
|
1779
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1780
|
-
ActionIconButton,
|
|
1781
|
-
{
|
|
1782
|
-
title: "Clear footer on this page",
|
|
1783
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Eraser, { size: 13 }),
|
|
1784
|
-
onClick: onClearFooter,
|
|
1785
|
-
disabled: !hasActivePage,
|
|
1786
|
-
testId: "clear-footer"
|
|
1787
|
-
}
|
|
1788
|
-
),
|
|
1789
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1790
|
-
ActionIconButton,
|
|
1791
|
-
{
|
|
1792
|
-
title: "Clear all footers",
|
|
1793
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(Trash2, { size: 13 }),
|
|
1794
|
-
onClick: onClearAllFooters,
|
|
1795
|
-
testId: "clear-all-footers"
|
|
1796
|
-
}
|
|
1797
|
-
)
|
|
1798
|
-
]
|
|
1799
|
-
}
|
|
1800
|
-
);
|
|
2030
|
+
]
|
|
2031
|
+
}
|
|
2032
|
+
)
|
|
2033
|
+
] });
|
|
1801
2034
|
};
|
|
1802
|
-
const
|
|
2035
|
+
const SectionLabel = ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 pt-2 pb-1 text-[10px] font-semibold uppercase tracking-wider text-gray-400", children });
|
|
2036
|
+
const MenuItem = ({ icon, label, onClick, disabled, testId }) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1803
2037
|
"button",
|
|
1804
2038
|
{
|
|
1805
2039
|
type: "button",
|
|
1806
|
-
|
|
1807
|
-
"aria-label": title,
|
|
2040
|
+
role: "menuitem",
|
|
1808
2041
|
onMouseDown: (e) => e.preventDefault(),
|
|
1809
2042
|
onClick,
|
|
1810
2043
|
disabled,
|
|
1811
|
-
className: "flex
|
|
2044
|
+
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",
|
|
1812
2045
|
"data-testid": testId,
|
|
1813
|
-
children:
|
|
2046
|
+
children: [
|
|
2047
|
+
icon,
|
|
2048
|
+
label
|
|
2049
|
+
]
|
|
1814
2050
|
}
|
|
1815
2051
|
);
|
|
1816
|
-
const
|
|
2052
|
+
const MenuDivider = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-1 h-px bg-gray-100" });
|
|
1817
2053
|
function resolveExtensions(extensions) {
|
|
1818
2054
|
const resolved = {
|
|
1819
2055
|
nodes: [],
|
|
@@ -1888,10 +2124,10 @@ function useExtensionContext(getDocument, getActiveEditor) {
|
|
|
1888
2124
|
}), [getDocument, getActiveEditor, stateRef]);
|
|
1889
2125
|
}
|
|
1890
2126
|
const SUPPORTED_FONTS = [
|
|
2127
|
+
"Calibri",
|
|
1891
2128
|
"Inter",
|
|
1892
2129
|
"Times New Roman",
|
|
1893
2130
|
"Arial",
|
|
1894
|
-
"Calibri",
|
|
1895
2131
|
"Georgia",
|
|
1896
2132
|
"Courier New"
|
|
1897
2133
|
];
|
|
@@ -2155,87 +2391,107 @@ const Toolbar = () => {
|
|
|
2155
2391
|
},
|
|
2156
2392
|
[applyToBodyEditors, runToolbarAction, t.history.actions.fontSizeChanged]
|
|
2157
2393
|
);
|
|
2158
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
2394
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2159
2395
|
"div",
|
|
2160
2396
|
{
|
|
2161
2397
|
className: "lex4-toolbar sticky top-0 z-10 bg-white border-b border-gray-200",
|
|
2162
2398
|
"data-testid": "toolbar",
|
|
2163
|
-
children:
|
|
2164
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-
|
|
2165
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2399
|
+
children: [
|
|
2400
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5", children: [
|
|
2401
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "history-controls", children: [
|
|
2402
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2403
|
+
ToolbarIconButton,
|
|
2404
|
+
{
|
|
2405
|
+
title: t.toolbar.undo,
|
|
2406
|
+
testId: "btn-undo",
|
|
2407
|
+
disabled: !canUndo,
|
|
2408
|
+
onClick: undo,
|
|
2409
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Undo2, { size: 15 })
|
|
2410
|
+
}
|
|
2411
|
+
),
|
|
2412
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2413
|
+
ToolbarIconButton,
|
|
2414
|
+
{
|
|
2415
|
+
title: t.toolbar.redo,
|
|
2416
|
+
testId: "btn-redo",
|
|
2417
|
+
disabled: !canRedo,
|
|
2418
|
+
onClick: redo,
|
|
2419
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(Redo2, { size: 15 })
|
|
2420
|
+
}
|
|
2421
|
+
)
|
|
2422
|
+
] }),
|
|
2423
|
+
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2424
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
2425
|
+
/* @__PURE__ */ jsxRuntime.jsx(Type, { size: 14, className: "text-gray-500" }),
|
|
2426
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2427
|
+
"select",
|
|
2428
|
+
{
|
|
2429
|
+
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",
|
|
2430
|
+
"data-testid": "font-selector",
|
|
2431
|
+
defaultValue: "Calibri",
|
|
2432
|
+
onChange: handleFontChange,
|
|
2433
|
+
children: SUPPORTED_FONTS.map((font) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: font, style: { fontFamily: font }, children: font }, font))
|
|
2434
|
+
}
|
|
2435
|
+
)
|
|
2436
|
+
] }),
|
|
2437
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
2438
|
+
/* @__PURE__ */ jsxRuntime.jsx(ALargeSmall, { size: 14, className: "text-gray-500" }),
|
|
2439
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2440
|
+
"select",
|
|
2441
|
+
{
|
|
2442
|
+
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",
|
|
2443
|
+
"data-testid": "font-size-selector",
|
|
2444
|
+
defaultValue: "12",
|
|
2445
|
+
onChange: handleFontSizeChange,
|
|
2446
|
+
children: SUPPORTED_FONT_SIZES.map((size) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: size, children: size }, size))
|
|
2447
|
+
}
|
|
2448
|
+
)
|
|
2449
|
+
] }),
|
|
2450
|
+
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2451
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "format-group", children: [
|
|
2452
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.bold, testId: "btn-bold", onClick: handleBold, children: /* @__PURE__ */ jsxRuntime.jsx(Bold, { size: 15 }) }),
|
|
2453
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.italic, testId: "btn-italic", onClick: handleItalic, children: /* @__PURE__ */ jsxRuntime.jsx(Italic, { size: 15 }) }),
|
|
2454
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.underline, testId: "btn-underline", onClick: handleUnderline, children: /* @__PURE__ */ jsxRuntime.jsx(Underline, { size: 15 }) }),
|
|
2455
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.strikethrough, testId: "btn-strike", onClick: handleStrikethrough, children: /* @__PURE__ */ jsxRuntime.jsx(Strikethrough, { size: 15 }) })
|
|
2456
|
+
] }),
|
|
2457
|
+
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2458
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "align-group", children: [
|
|
2459
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignLeft, testId: "btn-align-left", onClick: handleAlignLeft, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignStart, { size: 15 }) }),
|
|
2460
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignCenter, testId: "btn-align-center", onClick: handleAlignCenter, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignCenter, { size: 15 }) }),
|
|
2461
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignRight, testId: "btn-align-right", onClick: handleAlignRight, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignEnd, { size: 15 }) }),
|
|
2462
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.justify, testId: "btn-align-justify", onClick: handleAlignJustify, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignJustify, { size: 15 }) })
|
|
2463
|
+
] }),
|
|
2464
|
+
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2465
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "list-group", children: [
|
|
2466
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.numberedList, testId: "btn-list-number", onClick: handleListNumber, children: /* @__PURE__ */ jsxRuntime.jsx(ListOrdered, { size: 15 }) }),
|
|
2467
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.bulletList, testId: "btn-list-bullet", onClick: handleListBullet, children: /* @__PURE__ */ jsxRuntime.jsx(List, { size: 15 }) }),
|
|
2468
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.indent, testId: "btn-indent", onClick: handleIndent, children: /* @__PURE__ */ jsxRuntime.jsx(ListIndentIncrease, { size: 15 }) }),
|
|
2469
|
+
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.outdent, testId: "btn-outdent", onClick: handleOutdent, children: /* @__PURE__ */ jsxRuntime.jsx(ListIndentDecrease, { size: 15 }) })
|
|
2470
|
+
] }),
|
|
2471
|
+
toolbarItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2472
|
+
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2473
|
+
toolbarItems.map((ToolbarItem, idx) => /* @__PURE__ */ jsxRuntime.jsx(ToolbarItem, {}, idx))
|
|
2474
|
+
] }),
|
|
2475
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2166
2476
|
ToolbarIconButton,
|
|
2167
2477
|
{
|
|
2168
|
-
title: t.toolbar.
|
|
2169
|
-
testId: "
|
|
2170
|
-
|
|
2171
|
-
onClick:
|
|
2172
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2478
|
+
title: historySidebarOpen ? t.toolbar.closeHistory : t.toolbar.openHistory,
|
|
2479
|
+
testId: "toggle-history-sidebar",
|
|
2480
|
+
active: historySidebarOpen,
|
|
2481
|
+
onClick: () => setHistorySidebarOpen(!historySidebarOpen),
|
|
2482
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(PanelRight, { size: 15 })
|
|
2173
2483
|
}
|
|
2174
|
-
)
|
|
2484
|
+
) })
|
|
2485
|
+
] }),
|
|
2486
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 px-2 py-1 border-t border-gray-100", children: [
|
|
2175
2487
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2176
|
-
|
|
2488
|
+
HeaderFooterToggle,
|
|
2177
2489
|
{
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
disabled: !canRedo,
|
|
2181
|
-
onClick: redo,
|
|
2182
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(Redo2, { size: 15 })
|
|
2490
|
+
enabled: document2.headerFooterEnabled,
|
|
2491
|
+
onToggle: handleToggle
|
|
2183
2492
|
}
|
|
2184
|
-
)
|
|
2185
|
-
|
|
2186
|
-
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2187
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2188
|
-
"select",
|
|
2189
|
-
{
|
|
2190
|
-
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",
|
|
2191
|
-
"data-testid": "font-selector",
|
|
2192
|
-
defaultValue: "Inter",
|
|
2193
|
-
onChange: handleFontChange,
|
|
2194
|
-
children: SUPPORTED_FONTS.map((font) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: font, style: { fontFamily: font }, children: font }, font))
|
|
2195
|
-
}
|
|
2196
|
-
),
|
|
2197
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2198
|
-
"select",
|
|
2199
|
-
{
|
|
2200
|
-
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",
|
|
2201
|
-
"data-testid": "font-size-selector",
|
|
2202
|
-
defaultValue: "12",
|
|
2203
|
-
onChange: handleFontSizeChange,
|
|
2204
|
-
children: SUPPORTED_FONT_SIZES.map((size) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: size, children: size }, size))
|
|
2205
|
-
}
|
|
2206
|
-
),
|
|
2207
|
-
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2208
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "format-group", children: [
|
|
2209
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.bold, testId: "btn-bold", onClick: handleBold, children: /* @__PURE__ */ jsxRuntime.jsx(Bold, { size: 15 }) }),
|
|
2210
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.italic, testId: "btn-italic", onClick: handleItalic, children: /* @__PURE__ */ jsxRuntime.jsx(Italic, { size: 15 }) }),
|
|
2211
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.underline, testId: "btn-underline", onClick: handleUnderline, children: /* @__PURE__ */ jsxRuntime.jsx(Underline, { size: 15 }) }),
|
|
2212
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.strikethrough, testId: "btn-strike", onClick: handleStrikethrough, children: /* @__PURE__ */ jsxRuntime.jsx(Strikethrough, { size: 15 }) })
|
|
2213
|
-
] }),
|
|
2214
|
-
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2215
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "align-group", children: [
|
|
2216
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignLeft, testId: "btn-align-left", onClick: handleAlignLeft, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignStart, { size: 15 }) }),
|
|
2217
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignCenter, testId: "btn-align-center", onClick: handleAlignCenter, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignCenter, { size: 15 }) }),
|
|
2218
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.alignRight, testId: "btn-align-right", onClick: handleAlignRight, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignEnd, { size: 15 }) }),
|
|
2219
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.justify, testId: "btn-align-justify", onClick: handleAlignJustify, children: /* @__PURE__ */ jsxRuntime.jsx(TextAlignJustify, { size: 15 }) })
|
|
2220
|
-
] }),
|
|
2221
|
-
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2222
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-0.5", "data-testid": "list-group", children: [
|
|
2223
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.numberedList, testId: "btn-list-number", onClick: handleListNumber, children: /* @__PURE__ */ jsxRuntime.jsx(ListOrdered, { size: 15 }) }),
|
|
2224
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.bulletList, testId: "btn-list-bullet", onClick: handleListBullet, children: /* @__PURE__ */ jsxRuntime.jsx(List, { size: 15 }) }),
|
|
2225
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.indent, testId: "btn-indent", onClick: handleIndent, children: /* @__PURE__ */ jsxRuntime.jsx(ListIndentIncrease, { size: 15 }) }),
|
|
2226
|
-
/* @__PURE__ */ jsxRuntime.jsx(ToolbarIconButton, { title: t.toolbar.outdent, testId: "btn-outdent", onClick: handleOutdent, children: /* @__PURE__ */ jsxRuntime.jsx(ListIndentDecrease, { size: 15 }) })
|
|
2227
|
-
] }),
|
|
2228
|
-
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2229
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2230
|
-
HeaderFooterToggle,
|
|
2231
|
-
{
|
|
2232
|
-
enabled: document2.headerFooterEnabled,
|
|
2233
|
-
onToggle: handleToggle
|
|
2234
|
-
}
|
|
2235
|
-
),
|
|
2236
|
-
document2.headerFooterEnabled && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2237
|
-
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2238
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2493
|
+
),
|
|
2494
|
+
document2.headerFooterEnabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2239
2495
|
HeaderFooterActions,
|
|
2240
2496
|
{
|
|
2241
2497
|
activePageId,
|
|
@@ -2249,22 +2505,8 @@ const Toolbar = () => {
|
|
|
2249
2505
|
onClearAllFooters: handleClearAllFooters
|
|
2250
2506
|
}
|
|
2251
2507
|
)
|
|
2252
|
-
] })
|
|
2253
|
-
|
|
2254
|
-
/* @__PURE__ */ jsxRuntime.jsx(Divider, {}),
|
|
2255
|
-
toolbarItems.map((ToolbarItem, idx) => /* @__PURE__ */ jsxRuntime.jsx(ToolbarItem, {}, idx))
|
|
2256
|
-
] }),
|
|
2257
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2258
|
-
ToolbarIconButton,
|
|
2259
|
-
{
|
|
2260
|
-
title: historySidebarOpen ? t.toolbar.closeHistory : t.toolbar.openHistory,
|
|
2261
|
-
testId: "toggle-history-sidebar",
|
|
2262
|
-
active: historySidebarOpen,
|
|
2263
|
-
onClick: () => setHistorySidebarOpen(!historySidebarOpen),
|
|
2264
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(PanelRight, { size: 15 })
|
|
2265
|
-
}
|
|
2266
|
-
) })
|
|
2267
|
-
] })
|
|
2508
|
+
] })
|
|
2509
|
+
]
|
|
2268
2510
|
}
|
|
2269
2511
|
);
|
|
2270
2512
|
};
|
|
@@ -2335,6 +2577,19 @@ function mergeEditorStates(stateA, stateB) {
|
|
|
2335
2577
|
if (all.length === 0) return null;
|
|
2336
2578
|
return createEditorStateFromNodes(all);
|
|
2337
2579
|
}
|
|
2580
|
+
function splitBlockNode(block, childOffset) {
|
|
2581
|
+
const children = block.children ?? [];
|
|
2582
|
+
if (childOffset <= 0) return [null, structuredClone(block)];
|
|
2583
|
+
if (childOffset >= children.length) return [structuredClone(block), null];
|
|
2584
|
+
const before = children.slice(0, childOffset);
|
|
2585
|
+
const after = children.slice(childOffset);
|
|
2586
|
+
const makeCopy = (kids) => {
|
|
2587
|
+
const copy = structuredClone(block);
|
|
2588
|
+
copy.children = kids;
|
|
2589
|
+
return copy;
|
|
2590
|
+
};
|
|
2591
|
+
return [makeCopy(before), makeCopy(after)];
|
|
2592
|
+
}
|
|
2338
2593
|
function usePagination(document2, dispatch) {
|
|
2339
2594
|
const reflowingRef = React.useRef(false);
|
|
2340
2595
|
const pendingReflowRef = React.useRef(false);
|
|
@@ -2369,7 +2624,61 @@ function usePagination(document2, dispatch) {
|
|
|
2369
2624
|
const footerH = document2.headerFooterEnabled ? page.footerHeight : 0;
|
|
2370
2625
|
const bodyHeight = computeBodyHeight(headerH, footerH);
|
|
2371
2626
|
const nodes = getTopLevelNodes(page.bodyState);
|
|
2372
|
-
if (nodes.length <= 1)
|
|
2627
|
+
if (nodes.length <= 1) {
|
|
2628
|
+
if (nodes.length === 1) {
|
|
2629
|
+
const singleNode = nodes[0];
|
|
2630
|
+
const children = singleNode.children;
|
|
2631
|
+
if (children && children.length > 1) {
|
|
2632
|
+
const estimatedLineHeight = 24;
|
|
2633
|
+
const maxChildren = Math.max(1, Math.floor(bodyHeight / estimatedLineHeight));
|
|
2634
|
+
if (maxChildren < children.length) {
|
|
2635
|
+
const [keepBlock, overflowBlock] = splitBlockNode(singleNode, maxChildren);
|
|
2636
|
+
if (keepBlock && overflowBlock) {
|
|
2637
|
+
const keepState2 = createEditorStateFromNodes([keepBlock]);
|
|
2638
|
+
const overflowState2 = createEditorStateFromNodes([overflowBlock]);
|
|
2639
|
+
const nextPage2 = pages[pageIndex + 1];
|
|
2640
|
+
if (nextPage2) {
|
|
2641
|
+
const mergedBody = mergeEditorStates(overflowState2, nextPage2.bodyState);
|
|
2642
|
+
dispatch({
|
|
2643
|
+
type: "SET_DOCUMENT",
|
|
2644
|
+
document: {
|
|
2645
|
+
...document2,
|
|
2646
|
+
pages: pages.map((p, i) => {
|
|
2647
|
+
if (i === pageIndex) return { ...p, bodyState: keepState2 };
|
|
2648
|
+
if (i === pageIndex + 1) return { ...p, bodyState: mergedBody };
|
|
2649
|
+
return p;
|
|
2650
|
+
})
|
|
2651
|
+
}
|
|
2652
|
+
});
|
|
2653
|
+
} else {
|
|
2654
|
+
const newPage = {
|
|
2655
|
+
...createPageFromTemplate({
|
|
2656
|
+
headerState: document2.defaultHeaderState,
|
|
2657
|
+
footerState: document2.defaultFooterState,
|
|
2658
|
+
headerHeight: document2.defaultHeaderHeight,
|
|
2659
|
+
footerHeight: document2.defaultFooterHeight
|
|
2660
|
+
}),
|
|
2661
|
+
bodyState: overflowState2
|
|
2662
|
+
};
|
|
2663
|
+
dispatch({
|
|
2664
|
+
type: "SET_DOCUMENT",
|
|
2665
|
+
document: {
|
|
2666
|
+
...document2,
|
|
2667
|
+
pages: [
|
|
2668
|
+
...pages.map(
|
|
2669
|
+
(p, i) => i === pageIndex ? { ...p, bodyState: keepState2 } : p
|
|
2670
|
+
),
|
|
2671
|
+
newPage
|
|
2672
|
+
]
|
|
2673
|
+
}
|
|
2674
|
+
});
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
return;
|
|
2681
|
+
}
|
|
2373
2682
|
const fitCount = estimateNodesFitting(page.bodyState, bodyHeight);
|
|
2374
2683
|
if (fitCount >= nodes.length) return;
|
|
2375
2684
|
const [keepState, overflowState] = splitEditorState(page.bodyState, fitCount);
|
|
@@ -2533,7 +2842,7 @@ function usePagination(document2, dispatch) {
|
|
|
2533
2842
|
}
|
|
2534
2843
|
const lexicalTheme = {
|
|
2535
2844
|
root: "lex4-root outline-none",
|
|
2536
|
-
paragraph: "lex4-paragraph
|
|
2845
|
+
paragraph: "lex4-paragraph text-justify",
|
|
2537
2846
|
heading: {
|
|
2538
2847
|
h1: "text-3xl font-bold mb-2",
|
|
2539
2848
|
h2: "text-2xl font-bold mb-2",
|
|
@@ -2739,6 +3048,213 @@ const ActiveEditorPlugin = ({
|
|
|
2739
3048
|
}, [editor, onFocus, pageId, region, setActiveEditor, setActivePageId]);
|
|
2740
3049
|
return null;
|
|
2741
3050
|
};
|
|
3051
|
+
function findMidBlockSplitPoint(blockElement, availableHeight) {
|
|
3052
|
+
const blockRect = blockElement.getBoundingClientRect();
|
|
3053
|
+
const maxBottom = blockRect.top + availableHeight;
|
|
3054
|
+
const textNodes = [];
|
|
3055
|
+
const walker = document.createTreeWalker(blockElement, NodeFilter.SHOW_TEXT);
|
|
3056
|
+
let walkNode;
|
|
3057
|
+
while (walkNode = walker.nextNode()) {
|
|
3058
|
+
if (walkNode.length > 0) {
|
|
3059
|
+
textNodes.push(walkNode);
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
if (textNodes.length === 0) return null;
|
|
3063
|
+
const range = document.createRange();
|
|
3064
|
+
for (const textNode of textNodes) {
|
|
3065
|
+
range.selectNodeContents(textNode);
|
|
3066
|
+
const nodeRect = range.getBoundingClientRect();
|
|
3067
|
+
if (nodeRect.bottom <= maxBottom) {
|
|
3068
|
+
continue;
|
|
3069
|
+
}
|
|
3070
|
+
if (nodeRect.top >= maxBottom) {
|
|
3071
|
+
return backupToWordBoundary(textNode, 0);
|
|
3072
|
+
}
|
|
3073
|
+
let low = 0;
|
|
3074
|
+
let high = textNode.length;
|
|
3075
|
+
while (low < high) {
|
|
3076
|
+
const mid = Math.floor((low + high) / 2);
|
|
3077
|
+
range.setStart(textNode, 0);
|
|
3078
|
+
range.setEnd(textNode, mid + 1);
|
|
3079
|
+
const testRect = range.getBoundingClientRect();
|
|
3080
|
+
if (testRect.bottom > maxBottom) {
|
|
3081
|
+
high = mid;
|
|
3082
|
+
} else {
|
|
3083
|
+
low = mid + 1;
|
|
3084
|
+
}
|
|
3085
|
+
}
|
|
3086
|
+
return backupToWordBoundary(textNode, low);
|
|
3087
|
+
}
|
|
3088
|
+
return null;
|
|
3089
|
+
}
|
|
3090
|
+
function backupToWordBoundary(textNode, offset) {
|
|
3091
|
+
const text = textNode.textContent || "";
|
|
3092
|
+
if (offset <= 0 || offset >= text.length) {
|
|
3093
|
+
if (offset > 0 && offset < text.length) {
|
|
3094
|
+
return { textNode, offset };
|
|
3095
|
+
}
|
|
3096
|
+
if (offset > 0) return { textNode, offset };
|
|
3097
|
+
return null;
|
|
3098
|
+
}
|
|
3099
|
+
let adjusted = offset;
|
|
3100
|
+
while (adjusted > 0 && !/\s/.test(text[adjusted - 1])) {
|
|
3101
|
+
adjusted--;
|
|
3102
|
+
}
|
|
3103
|
+
if (adjusted <= 0) {
|
|
3104
|
+
adjusted = offset;
|
|
3105
|
+
}
|
|
3106
|
+
return { textNode, offset: adjusted };
|
|
3107
|
+
}
|
|
3108
|
+
function serializeNodeTree$1(node) {
|
|
3109
|
+
const json = node.exportJSON();
|
|
3110
|
+
if (lexical.$isElementNode(node)) {
|
|
3111
|
+
json.children = node.getChildren().map(serializeNodeTree$1);
|
|
3112
|
+
}
|
|
3113
|
+
return json;
|
|
3114
|
+
}
|
|
3115
|
+
function findListSplitIndex(listElement, availableHeight) {
|
|
3116
|
+
const listRect = listElement.getBoundingClientRect();
|
|
3117
|
+
const maxBottom = listRect.top + availableHeight;
|
|
3118
|
+
const children = Array.from(listElement.children);
|
|
3119
|
+
for (let i = 0; i < children.length; i++) {
|
|
3120
|
+
const child = children[i];
|
|
3121
|
+
const childRect = child.getBoundingClientRect();
|
|
3122
|
+
if (childRect.bottom > maxBottom && i > 0) {
|
|
3123
|
+
return i;
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
return -1;
|
|
3127
|
+
}
|
|
3128
|
+
function performMidBlockSplit(rootElement, availableHeight, overflowBlockIndex) {
|
|
3129
|
+
const root = lexical.$getRoot();
|
|
3130
|
+
const allChildren = root.getChildren();
|
|
3131
|
+
const blockNode = allChildren[overflowBlockIndex];
|
|
3132
|
+
if (!blockNode || !lexical.$isElementNode(blockNode)) {
|
|
3133
|
+
debugWarn("overflow", "target node is not an ElementNode");
|
|
3134
|
+
return null;
|
|
3135
|
+
}
|
|
3136
|
+
const blockElements = Array.from(rootElement.children);
|
|
3137
|
+
const blockElement = blockElements[overflowBlockIndex];
|
|
3138
|
+
if (!blockElement) {
|
|
3139
|
+
debugWarn("overflow", "no DOM element for block index");
|
|
3140
|
+
return null;
|
|
3141
|
+
}
|
|
3142
|
+
const blockTop = blockElement.offsetTop;
|
|
3143
|
+
const heightForBlock = availableHeight - blockTop;
|
|
3144
|
+
if (heightForBlock <= 0) {
|
|
3145
|
+
debugWarn("overflow", "no space for block");
|
|
3146
|
+
return null;
|
|
3147
|
+
}
|
|
3148
|
+
if (list.$isListNode(blockNode)) {
|
|
3149
|
+
return splitListNode(blockNode, blockElement, heightForBlock);
|
|
3150
|
+
}
|
|
3151
|
+
return splitParagraphNode(blockNode, blockElement, heightForBlock);
|
|
3152
|
+
}
|
|
3153
|
+
function splitListNode(listNode, listElement, availableHeight) {
|
|
3154
|
+
const splitIndex = findListSplitIndex(listElement, availableHeight);
|
|
3155
|
+
if (splitIndex <= 0) {
|
|
3156
|
+
debug("overflow", "cannot split list — first item exceeds height");
|
|
3157
|
+
return null;
|
|
3158
|
+
}
|
|
3159
|
+
const [, overflowList] = lexical.$splitNode(listNode, splitIndex);
|
|
3160
|
+
const overflowNodes = [];
|
|
3161
|
+
const toRemove = [];
|
|
3162
|
+
overflowNodes.push(serializeNodeTree$1(overflowList));
|
|
3163
|
+
toRemove.push(overflowList);
|
|
3164
|
+
let nextSibling = overflowList.getNextSibling();
|
|
3165
|
+
while (nextSibling) {
|
|
3166
|
+
overflowNodes.push(serializeNodeTree$1(nextSibling));
|
|
3167
|
+
toRemove.push(nextSibling);
|
|
3168
|
+
nextSibling = nextSibling.getNextSibling();
|
|
3169
|
+
}
|
|
3170
|
+
for (const node of toRemove) {
|
|
3171
|
+
node.remove();
|
|
3172
|
+
}
|
|
3173
|
+
debug("overflow", `split list at item ${splitIndex}, extracted ${overflowNodes.length} overflow nodes`);
|
|
3174
|
+
return overflowNodes;
|
|
3175
|
+
}
|
|
3176
|
+
function splitParagraphNode(blockNode, blockElement, availableHeight) {
|
|
3177
|
+
const splitPoint = findMidBlockSplitPoint(blockElement, availableHeight);
|
|
3178
|
+
if (!splitPoint) {
|
|
3179
|
+
debug("overflow", "no valid split point found in paragraph");
|
|
3180
|
+
return null;
|
|
3181
|
+
}
|
|
3182
|
+
const lexicalNode = lexical.$getNearestNodeFromDOMNode(splitPoint.textNode);
|
|
3183
|
+
if (!lexicalNode || !lexical.$isTextNode(lexicalNode)) {
|
|
3184
|
+
debugWarn("overflow", "could not map DOM text node to Lexical TextNode");
|
|
3185
|
+
return null;
|
|
3186
|
+
}
|
|
3187
|
+
const [, afterText] = lexicalNode.splitText(splitPoint.offset);
|
|
3188
|
+
if (!afterText) {
|
|
3189
|
+
debugWarn("overflow", "splitText returned no second half");
|
|
3190
|
+
return null;
|
|
3191
|
+
}
|
|
3192
|
+
const parent = afterText.getParent();
|
|
3193
|
+
if (!parent || !lexical.$isElementNode(parent)) {
|
|
3194
|
+
debugWarn("overflow", "split text has no element parent");
|
|
3195
|
+
return null;
|
|
3196
|
+
}
|
|
3197
|
+
let directChild = afterText;
|
|
3198
|
+
let directChildParent = parent;
|
|
3199
|
+
while (directChildParent && directChildParent.getKey() !== blockNode.getKey()) {
|
|
3200
|
+
directChild = directChildParent;
|
|
3201
|
+
const next = directChildParent.getParent();
|
|
3202
|
+
if (!next || !lexical.$isElementNode(next)) {
|
|
3203
|
+
debugWarn("overflow", "could not find block node in parent chain");
|
|
3204
|
+
return null;
|
|
3205
|
+
}
|
|
3206
|
+
directChildParent = next;
|
|
3207
|
+
}
|
|
3208
|
+
const splitChildIndex = blockNode.getChildren().indexOf(directChild);
|
|
3209
|
+
if (splitChildIndex <= 0) {
|
|
3210
|
+
debug("overflow", "split index is 0 or not found — nothing to keep on this page");
|
|
3211
|
+
return null;
|
|
3212
|
+
}
|
|
3213
|
+
if (directChild !== afterText) {
|
|
3214
|
+
let current = parent;
|
|
3215
|
+
let childToSplitAt = afterText;
|
|
3216
|
+
while (current.getKey() !== blockNode.getKey()) {
|
|
3217
|
+
const childIdx = current.getChildren().indexOf(childToSplitAt);
|
|
3218
|
+
if (childIdx > 0) {
|
|
3219
|
+
lexical.$splitNode(current, childIdx);
|
|
3220
|
+
}
|
|
3221
|
+
childToSplitAt = current;
|
|
3222
|
+
const next = current.getParent();
|
|
3223
|
+
if (!next || !lexical.$isElementNode(next)) break;
|
|
3224
|
+
current = next;
|
|
3225
|
+
}
|
|
3226
|
+
}
|
|
3227
|
+
let finalSplitChild = afterText;
|
|
3228
|
+
let p = afterText.getParent();
|
|
3229
|
+
while (p && p.getKey() !== blockNode.getKey()) {
|
|
3230
|
+
finalSplitChild = p;
|
|
3231
|
+
p = p.getParent();
|
|
3232
|
+
}
|
|
3233
|
+
const finalSplitIndex = blockNode.getChildren().indexOf(finalSplitChild);
|
|
3234
|
+
if (finalSplitIndex <= 0) {
|
|
3235
|
+
debug("overflow", "final split index is 0 or not found — nothing to keep on this page");
|
|
3236
|
+
return null;
|
|
3237
|
+
}
|
|
3238
|
+
const [, overflowBlock] = lexical.$splitNode(blockNode, finalSplitIndex);
|
|
3239
|
+
const overflowNodes = [];
|
|
3240
|
+
const toRemove = [];
|
|
3241
|
+
overflowNodes.push(serializeNodeTree$1(overflowBlock));
|
|
3242
|
+
toRemove.push(overflowBlock);
|
|
3243
|
+
let nextSibling = overflowBlock.getNextSibling();
|
|
3244
|
+
while (nextSibling) {
|
|
3245
|
+
overflowNodes.push(serializeNodeTree$1(nextSibling));
|
|
3246
|
+
toRemove.push(nextSibling);
|
|
3247
|
+
nextSibling = nextSibling.getNextSibling();
|
|
3248
|
+
}
|
|
3249
|
+
for (const node of toRemove) {
|
|
3250
|
+
node.remove();
|
|
3251
|
+
}
|
|
3252
|
+
debug(
|
|
3253
|
+
"overflow",
|
|
3254
|
+
`split paragraph at offset ${splitPoint.offset}, extracted ${overflowNodes.length} overflow nodes`
|
|
3255
|
+
);
|
|
3256
|
+
return overflowNodes;
|
|
3257
|
+
}
|
|
2742
3258
|
function serializeNodeTree(node) {
|
|
2743
3259
|
const json = node.exportJSON();
|
|
2744
3260
|
if (lexical.$isElementNode(node)) {
|
|
@@ -2767,18 +3283,51 @@ const OverflowPlugin = ({
|
|
|
2767
3283
|
const children = Array.from(rootElement.children);
|
|
2768
3284
|
if (children.length === 0) return;
|
|
2769
3285
|
if (children.length <= 1) {
|
|
2770
|
-
debug("overflow", `single block overflows (content=${contentHeight}px > available=${availableHeight}px) —
|
|
3286
|
+
debug("overflow", `single block overflows (content=${contentHeight}px > available=${availableHeight}px) — attempting mid-block split`);
|
|
3287
|
+
processingRef.current = true;
|
|
3288
|
+
editor.update(
|
|
3289
|
+
() => {
|
|
3290
|
+
const overflowNodes = performMidBlockSplit(rootElement, availableHeight, 0);
|
|
3291
|
+
if (!overflowNodes || overflowNodes.length === 0) {
|
|
3292
|
+
debug("overflow", "mid-block split not possible for single block");
|
|
3293
|
+
processingRef.current = false;
|
|
3294
|
+
return;
|
|
3295
|
+
}
|
|
3296
|
+
const overflowState = {
|
|
3297
|
+
root: {
|
|
3298
|
+
children: overflowNodes,
|
|
3299
|
+
direction: null,
|
|
3300
|
+
format: "",
|
|
3301
|
+
indent: 0,
|
|
3302
|
+
type: "root",
|
|
3303
|
+
version: 1
|
|
3304
|
+
}
|
|
3305
|
+
};
|
|
3306
|
+
debug("overflow", `mid-block split extracted ${overflowNodes.length} overflow nodes from single block`);
|
|
3307
|
+
setTimeout(() => {
|
|
3308
|
+
onOverflowRef.current(overflowState, cause);
|
|
3309
|
+
processingRef.current = false;
|
|
3310
|
+
}, 0);
|
|
3311
|
+
},
|
|
3312
|
+
{ tag: "overflow-split" }
|
|
3313
|
+
);
|
|
2771
3314
|
return;
|
|
2772
3315
|
}
|
|
2773
3316
|
processingRef.current = true;
|
|
2774
3317
|
debug("overflow", `OVERFLOW detected: content=${contentHeight}px available=${availableHeight}px children=${children.length}`);
|
|
2775
3318
|
let splitIndex = children.length;
|
|
3319
|
+
let firstBlockOverflows = false;
|
|
2776
3320
|
for (let i = 0; i < children.length; i++) {
|
|
2777
3321
|
const child = children[i];
|
|
2778
3322
|
const childBottom = child.offsetTop + child.offsetHeight;
|
|
2779
|
-
if (childBottom > availableHeight
|
|
2780
|
-
|
|
2781
|
-
|
|
3323
|
+
if (childBottom > availableHeight) {
|
|
3324
|
+
if (i === 0) {
|
|
3325
|
+
firstBlockOverflows = true;
|
|
3326
|
+
splitIndex = 1;
|
|
3327
|
+
} else {
|
|
3328
|
+
splitIndex = i;
|
|
3329
|
+
}
|
|
3330
|
+
debug("overflow", `split at index ${i === 0 ? "0 (mid-block)" : i} (childBottom=${childBottom}px > ${availableHeight}px)`);
|
|
2782
3331
|
break;
|
|
2783
3332
|
}
|
|
2784
3333
|
}
|
|
@@ -2796,15 +3345,37 @@ const OverflowPlugin = ({
|
|
|
2796
3345
|
processingRef.current = false;
|
|
2797
3346
|
return;
|
|
2798
3347
|
}
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
3348
|
+
let overflowNodes = [];
|
|
3349
|
+
if (firstBlockOverflows) {
|
|
3350
|
+
const midBlockOverflow = performMidBlockSplit(rootElement, availableHeight, 0);
|
|
3351
|
+
if (midBlockOverflow && midBlockOverflow.length > 0) {
|
|
3352
|
+
overflowNodes.push(...midBlockOverflow);
|
|
3353
|
+
debug("overflow", `mid-block split on first block extracted ${midBlockOverflow.length} nodes`);
|
|
3354
|
+
} else {
|
|
3355
|
+
debug("overflow", "mid-block split failed on first block — keeping it whole");
|
|
3356
|
+
}
|
|
3357
|
+
const freshChildren = root.getChildren();
|
|
3358
|
+
const toRemove = freshChildren.slice(1);
|
|
3359
|
+
for (const node of toRemove) {
|
|
3360
|
+
overflowNodes.push(serializeNodeTree(node));
|
|
3361
|
+
}
|
|
3362
|
+
for (const node of toRemove) {
|
|
3363
|
+
node.remove();
|
|
3364
|
+
}
|
|
3365
|
+
} else {
|
|
3366
|
+
const toRemove = allChildren.slice(splitIndex);
|
|
3367
|
+
for (const node of toRemove) {
|
|
3368
|
+
overflowNodes.push(serializeNodeTree(node));
|
|
3369
|
+
}
|
|
3370
|
+
for (const node of toRemove) {
|
|
3371
|
+
node.remove();
|
|
3372
|
+
}
|
|
2803
3373
|
}
|
|
2804
|
-
|
|
2805
|
-
|
|
3374
|
+
if (overflowNodes.length === 0) {
|
|
3375
|
+
processingRef.current = false;
|
|
3376
|
+
return;
|
|
2806
3377
|
}
|
|
2807
|
-
debug("overflow", `extracted ${overflowNodes.length} overflow nodes
|
|
3378
|
+
debug("overflow", `extracted ${overflowNodes.length} overflow nodes total`);
|
|
2808
3379
|
const overflowState = {
|
|
2809
3380
|
root: {
|
|
2810
3381
|
children: overflowNodes,
|
|
@@ -2885,16 +3456,10 @@ const OverflowPlugin = ({
|
|
|
2885
3456
|
}, [editor]);
|
|
2886
3457
|
return null;
|
|
2887
3458
|
};
|
|
2888
|
-
function createPageLabel(region, pageNumber) {
|
|
2889
|
-
if (region === "body") {
|
|
2890
|
-
return pageNumber ? `Page ${pageNumber}` : "Body";
|
|
2891
|
-
}
|
|
2892
|
-
const regionLabel = region.charAt(0).toUpperCase() + region.slice(1);
|
|
2893
|
-
return pageNumber ? `${regionLabel} Page ${pageNumber}` : regionLabel;
|
|
2894
|
-
}
|
|
2895
3459
|
const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
2896
3460
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
2897
3461
|
const { document: document2, queueHistoryAction } = useDocument();
|
|
3462
|
+
const t = useTranslations();
|
|
2898
3463
|
const context = React.useMemo(() => {
|
|
2899
3464
|
const pageNumber = document2.pages.findIndex((page) => page.id === pageId);
|
|
2900
3465
|
return {
|
|
@@ -2902,9 +3467,18 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
2902
3467
|
source: region
|
|
2903
3468
|
};
|
|
2904
3469
|
}, [document2.pages, pageId, region]);
|
|
3470
|
+
const createPageLabel = React.useMemo(() => {
|
|
3471
|
+
return (r, pageNumber) => {
|
|
3472
|
+
if (r === "body") {
|
|
3473
|
+
return pageNumber ? interpolate(t.regions.page, { page: pageNumber }) : t.regions.body;
|
|
3474
|
+
}
|
|
3475
|
+
const regionLabel = r === "header" ? t.regions.header : t.regions.footer;
|
|
3476
|
+
return pageNumber ? `${regionLabel} ${interpolate(t.regions.page, { page: pageNumber })}` : regionLabel;
|
|
3477
|
+
};
|
|
3478
|
+
}, [t]);
|
|
2905
3479
|
React.useEffect(() => {
|
|
2906
|
-
const buildDescriptor = (
|
|
2907
|
-
label: `${
|
|
3480
|
+
const buildDescriptor = (label) => ({
|
|
3481
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
2908
3482
|
source: context.source,
|
|
2909
3483
|
pageId,
|
|
2910
3484
|
region
|
|
@@ -2912,15 +3486,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
2912
3486
|
return editor.registerCommand(
|
|
2913
3487
|
lexical.CONTROLLED_TEXT_INSERTION_COMMAND,
|
|
2914
3488
|
() => {
|
|
2915
|
-
queueHistoryAction(buildDescriptor(
|
|
3489
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.typedText));
|
|
2916
3490
|
return false;
|
|
2917
3491
|
},
|
|
2918
3492
|
lexical.COMMAND_PRIORITY_LOW
|
|
2919
3493
|
);
|
|
2920
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3494
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
2921
3495
|
React.useEffect(() => {
|
|
2922
|
-
const buildDescriptor = (
|
|
2923
|
-
label: `${
|
|
3496
|
+
const buildDescriptor = (label) => ({
|
|
3497
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
2924
3498
|
source: context.source,
|
|
2925
3499
|
pageId,
|
|
2926
3500
|
region
|
|
@@ -2934,15 +3508,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
2934
3508
|
if (event.key.length !== 1) {
|
|
2935
3509
|
return false;
|
|
2936
3510
|
}
|
|
2937
|
-
queueHistoryAction(buildDescriptor(
|
|
3511
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.typedText));
|
|
2938
3512
|
return false;
|
|
2939
3513
|
},
|
|
2940
3514
|
lexical.COMMAND_PRIORITY_LOW
|
|
2941
3515
|
);
|
|
2942
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3516
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
2943
3517
|
React.useEffect(() => {
|
|
2944
|
-
const buildDescriptor = (
|
|
2945
|
-
label: `${
|
|
3518
|
+
const buildDescriptor = (label) => ({
|
|
3519
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
2946
3520
|
source: context.source,
|
|
2947
3521
|
pageId,
|
|
2948
3522
|
region
|
|
@@ -2955,15 +3529,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
2955
3529
|
if (text.trim().length === 0) {
|
|
2956
3530
|
return false;
|
|
2957
3531
|
}
|
|
2958
|
-
queueHistoryAction(buildDescriptor(
|
|
3532
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.pastedContent));
|
|
2959
3533
|
return false;
|
|
2960
3534
|
},
|
|
2961
3535
|
lexical.COMMAND_PRIORITY_LOW
|
|
2962
3536
|
);
|
|
2963
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3537
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
2964
3538
|
React.useEffect(() => {
|
|
2965
|
-
const buildDescriptor = (
|
|
2966
|
-
label: `${
|
|
3539
|
+
const buildDescriptor = (label) => ({
|
|
3540
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
2967
3541
|
source: context.source,
|
|
2968
3542
|
pageId,
|
|
2969
3543
|
region
|
|
@@ -2971,15 +3545,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
2971
3545
|
return editor.registerCommand(
|
|
2972
3546
|
lexical.KEY_ENTER_COMMAND,
|
|
2973
3547
|
() => {
|
|
2974
|
-
queueHistoryAction(buildDescriptor(
|
|
3548
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.insertedLineBreak));
|
|
2975
3549
|
return false;
|
|
2976
3550
|
},
|
|
2977
3551
|
lexical.COMMAND_PRIORITY_LOW
|
|
2978
3552
|
);
|
|
2979
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3553
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
2980
3554
|
React.useEffect(() => {
|
|
2981
|
-
const buildDescriptor = (
|
|
2982
|
-
label: `${
|
|
3555
|
+
const buildDescriptor = (label) => ({
|
|
3556
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
2983
3557
|
source: context.source,
|
|
2984
3558
|
pageId,
|
|
2985
3559
|
region
|
|
@@ -2987,15 +3561,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
2987
3561
|
return editor.registerCommand(
|
|
2988
3562
|
lexical.KEY_BACKSPACE_COMMAND,
|
|
2989
3563
|
() => {
|
|
2990
|
-
queueHistoryAction(buildDescriptor(
|
|
3564
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.deletedBackward));
|
|
2991
3565
|
return false;
|
|
2992
3566
|
},
|
|
2993
3567
|
lexical.COMMAND_PRIORITY_LOW
|
|
2994
3568
|
);
|
|
2995
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3569
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
2996
3570
|
React.useEffect(() => {
|
|
2997
|
-
const buildDescriptor = (
|
|
2998
|
-
label: `${
|
|
3571
|
+
const buildDescriptor = (label) => ({
|
|
3572
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
2999
3573
|
source: context.source,
|
|
3000
3574
|
pageId,
|
|
3001
3575
|
region
|
|
@@ -3003,15 +3577,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3003
3577
|
return editor.registerCommand(
|
|
3004
3578
|
lexical.KEY_DELETE_COMMAND,
|
|
3005
3579
|
() => {
|
|
3006
|
-
queueHistoryAction(buildDescriptor(
|
|
3580
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.deletedForward));
|
|
3007
3581
|
return false;
|
|
3008
3582
|
},
|
|
3009
3583
|
lexical.COMMAND_PRIORITY_LOW
|
|
3010
3584
|
);
|
|
3011
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3585
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3012
3586
|
React.useEffect(() => {
|
|
3013
|
-
const buildDescriptor = (
|
|
3014
|
-
label: `${
|
|
3587
|
+
const buildDescriptor = (label) => ({
|
|
3588
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
3015
3589
|
source: context.source,
|
|
3016
3590
|
pageId,
|
|
3017
3591
|
region
|
|
@@ -3019,15 +3593,15 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3019
3593
|
return editor.registerCommand(
|
|
3020
3594
|
lexical.FORMAT_TEXT_COMMAND,
|
|
3021
3595
|
() => {
|
|
3022
|
-
queueHistoryAction(buildDescriptor(
|
|
3596
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.formattedText));
|
|
3023
3597
|
return false;
|
|
3024
3598
|
},
|
|
3025
3599
|
lexical.COMMAND_PRIORITY_LOW
|
|
3026
3600
|
);
|
|
3027
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3601
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3028
3602
|
React.useEffect(() => {
|
|
3029
|
-
const buildDescriptor = (
|
|
3030
|
-
label: `${
|
|
3603
|
+
const buildDescriptor = (label) => ({
|
|
3604
|
+
label: `${label} - ${createPageLabel(region, context.pageNumber)}`,
|
|
3031
3605
|
source: context.source,
|
|
3032
3606
|
pageId,
|
|
3033
3607
|
region
|
|
@@ -3035,12 +3609,12 @@ const HistoryCapturePlugin = ({ pageId, region }) => {
|
|
|
3035
3609
|
return editor.registerCommand(
|
|
3036
3610
|
lexical.FORMAT_ELEMENT_COMMAND,
|
|
3037
3611
|
() => {
|
|
3038
|
-
queueHistoryAction(buildDescriptor(
|
|
3612
|
+
queueHistoryAction(buildDescriptor(t.historyLabels.formattedParagraph));
|
|
3039
3613
|
return false;
|
|
3040
3614
|
},
|
|
3041
3615
|
lexical.COMMAND_PRIORITY_LOW
|
|
3042
3616
|
);
|
|
3043
|
-
}, [context.pageNumber, context.source, editor, pageId, queueHistoryAction, region]);
|
|
3617
|
+
}, [context.pageNumber, context.source, createPageLabel, editor, pageId, queueHistoryAction, region, t]);
|
|
3044
3618
|
return null;
|
|
3045
3619
|
};
|
|
3046
3620
|
function getCollapsedTextPosition(rootElement) {
|
|
@@ -3145,6 +3719,7 @@ const PageBody = ({
|
|
|
3145
3719
|
readOnly = false
|
|
3146
3720
|
}) => {
|
|
3147
3721
|
const { nodes, bodyPlugins, themeOverrides } = useExtensions();
|
|
3722
|
+
const t = useTranslations();
|
|
3148
3723
|
const config = React.useMemo(
|
|
3149
3724
|
() => {
|
|
3150
3725
|
var _a, _b;
|
|
@@ -3198,7 +3773,7 @@ const PageBody = ({
|
|
|
3198
3773
|
style: { overflow: "visible" }
|
|
3199
3774
|
}
|
|
3200
3775
|
),
|
|
3201
|
-
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-0 left-0 text-gray-400 pointer-events-none select-none", children:
|
|
3776
|
+
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-0 left-0 text-gray-400 pointer-events-none select-none", children: t.body.placeholder }),
|
|
3202
3777
|
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary
|
|
3203
3778
|
}
|
|
3204
3779
|
),
|
|
@@ -3338,10 +3913,10 @@ const PageHeader = ({
|
|
|
3338
3913
|
LexicalContentEditable.ContentEditable,
|
|
3339
3914
|
{
|
|
3340
3915
|
ref: contentRef,
|
|
3341
|
-
className: `outline-none p-2 text-
|
|
3916
|
+
className: `outline-none p-2 text-gray-600 min-h-[24px] ${hasPageCounter ? "pr-24" : ""}`
|
|
3342
3917
|
}
|
|
3343
3918
|
),
|
|
3344
|
-
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `absolute top-0 left-0 text-gray-400 pointer-events-none select-none p-2
|
|
3919
|
+
placeholder: /* @__PURE__ */ jsxRuntime.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 }),
|
|
3345
3920
|
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary
|
|
3346
3921
|
}
|
|
3347
3922
|
),
|
|
@@ -3418,10 +3993,10 @@ const PageFooter = ({
|
|
|
3418
3993
|
LexicalContentEditable.ContentEditable,
|
|
3419
3994
|
{
|
|
3420
3995
|
ref: contentRef,
|
|
3421
|
-
className: `outline-none p-2 text-
|
|
3996
|
+
className: `outline-none p-2 text-gray-600 min-h-[24px] ${hasPageCounter ? "pr-24" : ""}`
|
|
3422
3997
|
}
|
|
3423
3998
|
),
|
|
3424
|
-
placeholder: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `absolute top-0 left-0 text-gray-400 pointer-events-none select-none p-2
|
|
3999
|
+
placeholder: /* @__PURE__ */ jsxRuntime.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 }),
|
|
3425
4000
|
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary
|
|
3426
4001
|
}
|
|
3427
4002
|
),
|
|
@@ -3452,10 +4027,14 @@ const PageView = React.memo(({
|
|
|
3452
4027
|
onMoveToNextPage
|
|
3453
4028
|
}) => {
|
|
3454
4029
|
const { document: document2, dispatch, setActivePageId } = useDocument();
|
|
4030
|
+
const t = useTranslations();
|
|
3455
4031
|
const page = document2.pages.find((p) => p.id === pageId);
|
|
3456
4032
|
const showHeaderFooter = document2.headerFooterEnabled;
|
|
3457
4033
|
const pageCounterMode = document2.pageCounterMode;
|
|
3458
|
-
const pageCounterLabel =
|
|
4034
|
+
const pageCounterLabel = interpolate(t.pageCounter.format, {
|
|
4035
|
+
current: pageIndex + 1,
|
|
4036
|
+
total: document2.pages.length
|
|
4037
|
+
});
|
|
3459
4038
|
if (!page) return null;
|
|
3460
4039
|
const handleBodyChange = React.useCallback(
|
|
3461
4040
|
(bodyState) => {
|
|
@@ -3546,6 +4125,7 @@ const DocumentView = () => {
|
|
|
3546
4125
|
setActiveEditor,
|
|
3547
4126
|
setActivePageId
|
|
3548
4127
|
} = useDocument();
|
|
4128
|
+
const t = useTranslations();
|
|
3549
4129
|
const { handlePageUnderflow, reflowAll } = usePagination(document2, dispatch);
|
|
3550
4130
|
const previousBodyHeightsRef = React.useRef(null);
|
|
3551
4131
|
const pasteOverflowSequenceRef = React.useRef(false);
|
|
@@ -3710,7 +4290,7 @@ const DocumentView = () => {
|
|
|
3710
4290
|
}
|
|
3711
4291
|
runHistoryAction(
|
|
3712
4292
|
{
|
|
3713
|
-
label:
|
|
4293
|
+
label: `${t.historyLabels.deletedBackward} - ${interpolate(t.regions.page, { page: pageIndex + 1 })}`,
|
|
3714
4294
|
source: "body",
|
|
3715
4295
|
pageId,
|
|
3716
4296
|
region: "body"
|
|
@@ -3732,7 +4312,7 @@ const DocumentView = () => {
|
|
|
3732
4312
|
}
|
|
3733
4313
|
runHistoryAction(
|
|
3734
4314
|
{
|
|
3735
|
-
label:
|
|
4315
|
+
label: `${t.historyLabels.deletedForward} - ${interpolate(t.regions.page, { page: pageIndex + 1 })}`,
|
|
3736
4316
|
source: "body",
|
|
3737
4317
|
pageId,
|
|
3738
4318
|
region: "body"
|
|
@@ -3965,7 +4545,7 @@ const EditorChrome = ({
|
|
|
3965
4545
|
}
|
|
3966
4546
|
),
|
|
3967
4547
|
/* @__PURE__ */ jsxRuntime.jsx(Toolbar, {}),
|
|
3968
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 overflow-hidden bg-gray-
|
|
4548
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 overflow-hidden bg-gray-200", children: [
|
|
3969
4549
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1 overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(DocumentView, {}) }),
|
|
3970
4550
|
sidePanels.map((Panel, idx) => /* @__PURE__ */ jsxRuntime.jsx(Panel, {}, idx)),
|
|
3971
4551
|
/* @__PURE__ */ jsxRuntime.jsx(HistorySidebar, {})
|
|
@@ -4778,6 +5358,7 @@ exports.INSERT_VARIABLE_COMMAND = INSERT_VARIABLE_COMMAND;
|
|
|
4778
5358
|
exports.Lex4Editor = Lex4Editor;
|
|
4779
5359
|
exports.MAX_FOOTER_HEIGHT_PX = MAX_FOOTER_HEIGHT_PX;
|
|
4780
5360
|
exports.MAX_HEADER_HEIGHT_PX = MAX_HEADER_HEIGHT_PX;
|
|
5361
|
+
exports.PT_BR_TRANSLATIONS = PT_BR_TRANSLATIONS;
|
|
4781
5362
|
exports.VariableNode = VariableNode;
|
|
4782
5363
|
exports.astExtension = astExtension;
|
|
4783
5364
|
exports.buildSavePayload = buildSavePayload;
|