@flogeez/angular-tiptap-editor 3.5.5 → 3.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +27 -1
  2. package/README.md +2 -2
  3. package/esm2022/lib/components/editor/angular-tiptap-editor.component.mjs +93 -21
  4. package/esm2022/lib/config/ate-editor.config.mjs +3 -1
  5. package/esm2022/lib/config/ate-slash-commands.config.mjs +2 -1
  6. package/esm2022/lib/directives/ate-tooltip.directive.mjs +37 -2
  7. package/esm2022/lib/extensions/ate-block-shortcuts.extension.mjs +100 -0
  8. package/esm2022/lib/extensions/ate-pasted-image.extension.mjs +7 -3
  9. package/esm2022/lib/i18n/ateTranslationsModel.mjs +1 -1
  10. package/esm2022/lib/i18n/es_ateTranslations.mjs +230 -0
  11. package/esm2022/lib/i18n/pt_ateTranslations.mjs +220 -0
  12. package/esm2022/lib/models/ate-editor-config.model.mjs +1 -1
  13. package/esm2022/lib/models/ate-editor-ref.mjs +3 -3
  14. package/esm2022/lib/models/ate-image.model.mjs +12 -2
  15. package/esm2022/lib/services/ate-editor-commands.service.mjs +6 -3
  16. package/esm2022/lib/services/ate-i18n.service.mjs +19 -9
  17. package/esm2022/lib/services/ate-image.service.mjs +18 -11
  18. package/esm2022/lib/utils/ate-extensions.utils.mjs +79 -0
  19. package/esm2022/public-api.mjs +2 -1
  20. package/fesm2022/flogeez-angular-tiptap-editor.mjs +814 -47
  21. package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
  22. package/lib/components/editor/angular-tiptap-editor.component.d.ts +12 -2
  23. package/lib/config/ate-slash-commands.config.d.ts +2 -0
  24. package/lib/extensions/ate-block-shortcuts.extension.d.ts +32 -0
  25. package/lib/i18n/ateTranslationsModel.d.ts +1 -1
  26. package/lib/i18n/es_ateTranslations.d.ts +2 -0
  27. package/lib/i18n/pt_ateTranslations.d.ts +2 -0
  28. package/lib/models/ate-editor-config.model.d.ts +8 -0
  29. package/lib/models/ate-image.model.d.ts +30 -2
  30. package/lib/services/ate-editor-commands.service.d.ts +2 -1
  31. package/lib/services/ate-i18n.service.d.ts +3 -1
  32. package/lib/services/ate-image.service.d.ts +5 -3
  33. package/lib/utils/ate-extensions.utils.d.ts +13 -0
  34. package/package.json +1 -1
  35. package/public-api.d.ts +1 -0
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, signal, inject, Injectable, computed, Directive, ApplicationRef, EnvironmentInjector, createComponent, input, booleanAttribute, effect, untracked, Component, ChangeDetectionStrategy, HostListener, ElementRef, ViewEncapsulation, output, viewChild, DestroyRef, Injector, makeEnvironmentProviders, APP_INITIALIZER } from '@angular/core';
2
+ import { InjectionToken, signal, inject, Injectable, computed, Directive, ApplicationRef, EnvironmentInjector, createComponent, input, booleanAttribute, effect, untracked, Component, ChangeDetectionStrategy, HostListener, ElementRef, ViewEncapsulation, output, viewChild, DestroyRef, Injector, isDevMode, makeEnvironmentProviders, APP_INITIALIZER } from '@angular/core';
3
3
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
4
  import { Node as Node$1, mergeAttributes, nodeInputRule, Extension, getAttributes, Editor } from '@tiptap/core';
5
5
  import StarterKit from '@tiptap/starter-kit';
@@ -11,7 +11,7 @@ import { Highlight } from '@tiptap/extension-highlight';
11
11
  import { TextStyle } from '@tiptap/extension-text-style';
12
12
  import { Color } from '@tiptap/extension-color';
13
13
  import OfficePaste from '@intevation/tiptap-extension-office-paste';
14
- import { Plugin, PluginKey, TextSelection, NodeSelection } from '@tiptap/pm/state';
14
+ import { Plugin, PluginKey, NodeSelection, TextSelection } from '@tiptap/pm/state';
15
15
  import { DecorationSet, Decoration } from '@tiptap/pm/view';
16
16
  import { Fragment, Slice } from '@tiptap/pm/model';
17
17
  import { Table, TableRow, TableHeader, TableCell } from '@tiptap/extension-table';
@@ -682,6 +682,18 @@ const AteUploadProgress = Extension.create({
682
682
  },
683
683
  });
684
684
 
685
+ /**
686
+ * Thrown when an image fails validation, before compression and before `imageUploadHandler` runs.
687
+ * `message` is the translated, user-facing text.
688
+ */
689
+ class AteImageValidationError extends Error {
690
+ constructor(reason, message) {
691
+ super(message);
692
+ this.reason = reason;
693
+ this.name = "AteImageValidationError";
694
+ }
695
+ }
696
+
685
697
  const IMAGE_NODE_NAMES = new Set(["resizableImage", "image"]);
686
698
  const REMOTE_SRC = /^(https?:)?\/\//i;
687
699
  const INLINE_SRC = /^data:(image\/[\w.+-]+);base64,(.*)$/is;
@@ -812,9 +824,12 @@ const AtePastedImage = Extension.create({
812
824
  options
813
825
  .rehost(file)
814
826
  .then(url => replaceImageSrc(editor, src, url))
815
- .catch(() => {
827
+ .catch((error) => {
816
828
  replaceImageSrc(editor, src, null);
817
- options.onRejected({ reason: "upload-failed", src });
829
+ options.onRejected({
830
+ reason: error instanceof AteImageValidationError ? error.reason : "upload-failed",
831
+ src,
832
+ });
818
833
  });
819
834
  };
820
835
  return [
@@ -883,6 +898,104 @@ const AteLinkShortcut = Extension.create({
883
898
  },
884
899
  });
885
900
 
901
+ const LIST_ITEM_NODE_NAMES = new Set(["listItem", "taskItem"]);
902
+ /**
903
+ * Resolves the block the shortcuts act on: a selected block node, the list or task item
904
+ * holding the cursor, or else the top-level block holding the cursor.
905
+ */
906
+ function findBlockAtSelection(selection) {
907
+ const { $from } = selection;
908
+ if (selection instanceof NodeSelection && selection.node.isBlock) {
909
+ return {
910
+ node: selection.node,
911
+ pos: selection.from,
912
+ parent: $from.parent,
913
+ index: $from.index(),
914
+ };
915
+ }
916
+ if ($from.depth < 1) {
917
+ return null;
918
+ }
919
+ let depth = 1;
920
+ for (let current = $from.depth; current > 0; current--) {
921
+ if (LIST_ITEM_NODE_NAMES.has($from.node(current).type.name)) {
922
+ depth = current;
923
+ break;
924
+ }
925
+ }
926
+ return {
927
+ node: $from.node(depth),
928
+ pos: $from.before(depth),
929
+ parent: $from.node(depth - 1),
930
+ index: $from.index(depth - 1),
931
+ };
932
+ }
933
+ /** Inserts a copy of the current block right after it */
934
+ function duplicateBlock(state) {
935
+ const block = findBlockAtSelection(state.selection);
936
+ if (!block) {
937
+ return null;
938
+ }
939
+ return state.tr.insert(block.pos, block.node).scrollIntoView();
940
+ }
941
+ /** Swaps the current block with its previous sibling, or returns `null` at the first position */
942
+ function moveBlockUp(state) {
943
+ const block = findBlockAtSelection(state.selection);
944
+ if (!block || block.index === 0) {
945
+ return null;
946
+ }
947
+ const previous = block.parent.child(block.index - 1);
948
+ const end = block.pos + block.node.nodeSize;
949
+ return state.tr
950
+ .insert(end, previous)
951
+ .delete(block.pos - previous.nodeSize, block.pos)
952
+ .scrollIntoView();
953
+ }
954
+ /** Swaps the current block with its next sibling, or returns `null` at the last position */
955
+ function moveBlockDown(state) {
956
+ const block = findBlockAtSelection(state.selection);
957
+ if (!block || block.index >= block.parent.childCount - 1) {
958
+ return null;
959
+ }
960
+ const next = block.parent.child(block.index + 1);
961
+ const end = block.pos + block.node.nodeSize;
962
+ return state.tr
963
+ .delete(end, end + next.nodeSize)
964
+ .insert(block.pos, next)
965
+ .scrollIntoView();
966
+ }
967
+ /**
968
+ * Notion-style block shortcuts: `Mod+D` duplicates the current block, `Mod+Shift+ArrowUp` and
969
+ * `Mod+Shift+ArrowDown` move it one sibling up or down. Inside a list the block is the list
970
+ * or task item, which moves within its list. At the edges the key event is left alone.
971
+ */
972
+ const AteBlockShortcuts = Extension.create({
973
+ name: "ateBlockShortcuts",
974
+ addOptions() {
975
+ return {
976
+ enabled: () => true,
977
+ };
978
+ },
979
+ addKeyboardShortcuts() {
980
+ const run = (build) => () => {
981
+ if (!this.options.enabled() || !this.editor.isEditable) {
982
+ return false;
983
+ }
984
+ const transaction = build(this.editor.state);
985
+ if (!transaction) {
986
+ return false;
987
+ }
988
+ this.editor.view.dispatch(transaction);
989
+ return true;
990
+ };
991
+ return {
992
+ "Mod-d": run(duplicateBlock),
993
+ "Mod-Shift-ArrowUp": run(moveBlockUp),
994
+ "Mod-Shift-ArrowDown": run(moveBlockDown),
995
+ };
996
+ },
997
+ });
998
+
886
999
  const AteTableExtension = Extension.create({
887
1000
  name: "tableExtension",
888
1001
  addExtensions() {
@@ -1471,13 +1584,13 @@ class AteEditorRef {
1471
1584
  insertImage(options) {
1472
1585
  const editor = this.editor;
1473
1586
  if (editor) {
1474
- this.commandsService.insertImage(editor, options);
1587
+ this.commandsService.insertImage(editor, options).catch(() => undefined);
1475
1588
  }
1476
1589
  }
1477
1590
  uploadImage(file, options) {
1478
1591
  const editor = this.editor;
1479
1592
  if (editor) {
1480
- this.commandsService.uploadImage(editor, file, options);
1593
+ this.commandsService.uploadImage(editor, file, options).catch(() => undefined);
1481
1594
  }
1482
1595
  }
1483
1596
  toggleHighlight(color) {
@@ -2348,6 +2461,456 @@ const GERMAN_TRANSLATIONS = {
2348
2461
  },
2349
2462
  };
2350
2463
 
2464
+ const PORTUGUESE_TRANSLATIONS = {
2465
+ toolbar: {
2466
+ bold: "Negrito\nCtrl+B",
2467
+ italic: "Itálico\nCtrl+I",
2468
+ underline: "Sublinhado\nCtrl+U",
2469
+ strike: "Tachado\nCtrl+Shift+X",
2470
+ code: "Código em linha\nCtrl+E",
2471
+ codeBlock: "Bloco de código",
2472
+ superscript: "Sobrescrito",
2473
+ subscript: "Subscrito",
2474
+ highlight: "Destacar",
2475
+ highlightPicker: "Cor de destaque",
2476
+ heading1: "Título 1",
2477
+ heading2: "Título 2",
2478
+ heading3: "Título 3",
2479
+ bulletList: "Lista com marcadores",
2480
+ orderedList: "Lista numerada",
2481
+ blockquote: "Citação",
2482
+ alignLeft: "Alinhar à esquerda",
2483
+ alignCenter: "Centralizar",
2484
+ alignRight: "Alinhar à direita",
2485
+ alignJustify: "Justificar",
2486
+ link: "Inserir link",
2487
+ image: "Inserir imagem",
2488
+ horizontalRule: "Linha horizontal",
2489
+ table: "Inserir tabela",
2490
+ undo: "Desfazer\nCtrl+Z",
2491
+ redo: "Refazer\nCtrl+Shift+Z",
2492
+ clear: "Limpar",
2493
+ textColor: "Cor do texto",
2494
+ customColor: "Cor personalizada",
2495
+ presets: "Predefinições",
2496
+ },
2497
+ bubbleMenu: {
2498
+ bold: "Negrito\nCtrl+B",
2499
+ italic: "Itálico\nCtrl+I",
2500
+ underline: "Sublinhado\nCtrl+U",
2501
+ strike: "Tachado\nCtrl+Shift+X",
2502
+ code: "Código\nCtrl+E",
2503
+ superscript: "Sobrescrito",
2504
+ subscript: "Subscrito",
2505
+ highlight: "Destacar",
2506
+ highlightPicker: "Cor de destaque",
2507
+ textColor: "Cor do texto",
2508
+ link: "Link",
2509
+ addLink: "Inserir link",
2510
+ editLink: "Editar link",
2511
+ removeLink: "Remover link",
2512
+ linkUrl: "URL do link",
2513
+ linkText: "Texto do link",
2514
+ openLink: "Abrir link",
2515
+ customColor: "Cor personalizada",
2516
+ presets: "Predefinições",
2517
+ },
2518
+ slashCommands: {
2519
+ heading1: {
2520
+ title: "Título 1",
2521
+ description: "Título de seção grande",
2522
+ keywords: ["heading", "h1", "title", "1", "header", "título", "titulo", "cabeçalho"],
2523
+ },
2524
+ heading2: {
2525
+ title: "Título 2",
2526
+ description: "Título de seção médio",
2527
+ keywords: ["heading", "h2", "title", "2", "header", "título", "titulo", "subtítulo"],
2528
+ },
2529
+ heading3: {
2530
+ title: "Título 3",
2531
+ description: "Título de seção pequeno",
2532
+ keywords: ["heading", "h3", "title", "3", "header", "título", "titulo", "subtítulo"],
2533
+ },
2534
+ bulletList: {
2535
+ title: "Lista com marcadores",
2536
+ description: "Criar uma lista com marcadores",
2537
+ keywords: ["bullet", "list", "ul", "unordered", "lista", "marcadores", "tópicos"],
2538
+ },
2539
+ orderedList: {
2540
+ title: "Lista numerada",
2541
+ description: "Criar uma lista numerada",
2542
+ keywords: ["ordered", "list", "ol", "numbered", "lista", "numerada", "ordenada"],
2543
+ },
2544
+ blockquote: {
2545
+ title: "Citação",
2546
+ description: "Adicionar uma citação",
2547
+ keywords: ["quote", "blockquote", "citation", "citação", "citacao", "aspas"],
2548
+ },
2549
+ code: {
2550
+ title: "Bloco de código",
2551
+ description: "Adicionar um bloco de código",
2552
+ keywords: ["code", "codeblock", "pre", "programming", "código", "codigo", "programação"],
2553
+ },
2554
+ image: {
2555
+ title: "Imagem",
2556
+ description: "Inserir uma imagem",
2557
+ keywords: ["image", "photo", "picture", "img", "imagem", "foto"],
2558
+ },
2559
+ horizontalRule: {
2560
+ title: "Linha horizontal",
2561
+ description: "Adicionar uma linha divisória",
2562
+ keywords: ["hr", "horizontal", "rule", "line", "separator", "linha", "divisor", "separador"],
2563
+ },
2564
+ table: {
2565
+ title: "Tabela",
2566
+ description: "Inserir uma tabela",
2567
+ keywords: [
2568
+ "table",
2569
+ "grid",
2570
+ "data",
2571
+ "rows",
2572
+ "columns",
2573
+ "tabela",
2574
+ "grade",
2575
+ "dados",
2576
+ "linhas",
2577
+ "colunas",
2578
+ ],
2579
+ },
2580
+ tableOfContents: {
2581
+ title: "Sumário",
2582
+ description: "Inserir um sumário",
2583
+ keywords: [
2584
+ "toc",
2585
+ "table",
2586
+ "contents",
2587
+ "summary",
2588
+ "index",
2589
+ "headings",
2590
+ "outline",
2591
+ "sumário",
2592
+ "sumario",
2593
+ "índice",
2594
+ "indice",
2595
+ "títulos",
2596
+ ],
2597
+ },
2598
+ filterPlaceholder: "Filtrar...",
2599
+ },
2600
+ table: {
2601
+ addRowBefore: "Inserir linha acima",
2602
+ addRowAfter: "Inserir linha abaixo",
2603
+ deleteRow: "Excluir linha",
2604
+ addColumnBefore: "Inserir coluna à esquerda",
2605
+ addColumnAfter: "Inserir coluna à direita",
2606
+ deleteColumn: "Excluir coluna",
2607
+ deleteTable: "Excluir tabela",
2608
+ toggleHeaderRow: "Alternar linha de cabeçalho",
2609
+ toggleHeaderColumn: "Alternar coluna de cabeçalho",
2610
+ mergeCells: "Mesclar células",
2611
+ splitCell: "Dividir célula",
2612
+ },
2613
+ imageUpload: {
2614
+ selectImage: "Selecionar imagem",
2615
+ loadError: "Erro ao carregar a imagem",
2616
+ uploadingImage: "Enviando imagem...",
2617
+ uploadProgress: "Progresso do envio",
2618
+ uploadError: "Erro no envio",
2619
+ uploadSuccess: "Envio concluído",
2620
+ imageTooLarge: "Imagem muito grande",
2621
+ invalidFileType: "Tipo de arquivo inválido",
2622
+ dragDropText: "Arraste e solte imagens aqui",
2623
+ changeImage: "Trocar imagem",
2624
+ downloadImage: "Baixar imagem",
2625
+ deleteImage: "Excluir imagem",
2626
+ resizeSmall: "Pequena",
2627
+ resizeMedium: "Média",
2628
+ resizeLarge: "Grande",
2629
+ resizeOriginal: "Original",
2630
+ alignLeft: "Alinhar à esquerda",
2631
+ alignCenter: "Centralizar",
2632
+ alignRight: "Alinhar à direita",
2633
+ resizing: "Redimensionando...",
2634
+ compressing: "Comprimindo...",
2635
+ compressionError: "Erro ao comprimir a imagem",
2636
+ validating: "Validando arquivo...",
2637
+ uploadingToServer: "Enviando para o servidor...",
2638
+ replacingImage: "Substituindo imagem...",
2639
+ insertingImage: "Inserindo no editor...",
2640
+ noFileSelected: "Nenhum arquivo de imagem selecionado",
2641
+ selectionCancelled: "Seleção cancelada",
2642
+ },
2643
+ editor: {
2644
+ placeholder: "Comece a escrever...",
2645
+ character: "caractere",
2646
+ characterPlural: "caracteres",
2647
+ word: "palavra",
2648
+ wordPlural: "palavras",
2649
+ linkPrompt: "Digite a URL do link",
2650
+ linkUrlPrompt: "Digite a URL",
2651
+ confirmDelete: "Tem certeza de que deseja excluir?",
2652
+ toggleEdit: "Mudar para o modo de edição",
2653
+ viewMode: "Mudar para o modo de leitura",
2654
+ blockAdd: "Clique para adicionar um bloco",
2655
+ blockDrag: "Arraste para mover este bloco",
2656
+ tableOfContents: "Sumário",
2657
+ },
2658
+ common: {
2659
+ cancel: "Cancelar",
2660
+ confirm: "Confirmar",
2661
+ apply: "Aplicar",
2662
+ delete: "Excluir",
2663
+ save: "Salvar",
2664
+ close: "Fechar",
2665
+ loading: "Carregando",
2666
+ error: "Erro",
2667
+ success: "Sucesso",
2668
+ },
2669
+ export: {
2670
+ export: "Exportar",
2671
+ html: "HTML",
2672
+ markdown: "Markdown",
2673
+ text: "Texto simples",
2674
+ copyHtml: "Copiar como HTML",
2675
+ copyMarkdown: "Copiar como Markdown",
2676
+ copyText: "Copiar como texto simples",
2677
+ downloadHtml: "Baixar .html",
2678
+ downloadMarkdown: "Baixar .md",
2679
+ downloadText: "Baixar .txt",
2680
+ copiedSuccess: "Copiado para a área de transferência!",
2681
+ },
2682
+ };
2683
+
2684
+ const SPANISH_TRANSLATIONS = {
2685
+ toolbar: {
2686
+ bold: "Negrita\nCtrl+B",
2687
+ italic: "Cursiva\nCtrl+I",
2688
+ underline: "Subrayado\nCtrl+U",
2689
+ strike: "Tachado\nCtrl+Shift+X",
2690
+ code: "Código en línea\nCtrl+E",
2691
+ codeBlock: "Bloque de código",
2692
+ superscript: "Superíndice",
2693
+ subscript: "Subíndice",
2694
+ highlight: "Resaltar",
2695
+ highlightPicker: "Color de resaltado",
2696
+ heading1: "Título 1",
2697
+ heading2: "Título 2",
2698
+ heading3: "Título 3",
2699
+ bulletList: "Lista con viñetas",
2700
+ orderedList: "Lista numerada",
2701
+ blockquote: "Cita",
2702
+ alignLeft: "Alinear a la izquierda",
2703
+ alignCenter: "Centrar",
2704
+ alignRight: "Alinear a la derecha",
2705
+ alignJustify: "Justificar",
2706
+ link: "Insertar enlace",
2707
+ image: "Insertar imagen",
2708
+ horizontalRule: "Línea horizontal",
2709
+ table: "Insertar tabla",
2710
+ undo: "Deshacer\nCtrl+Z",
2711
+ redo: "Rehacer\nCtrl+Shift+Z",
2712
+ clear: "Limpiar",
2713
+ textColor: "Color del texto",
2714
+ customColor: "Color personalizado",
2715
+ presets: "Predefinidos",
2716
+ },
2717
+ bubbleMenu: {
2718
+ bold: "Negrita\nCtrl+B",
2719
+ italic: "Cursiva\nCtrl+I",
2720
+ underline: "Subrayado\nCtrl+U",
2721
+ strike: "Tachado\nCtrl+Shift+X",
2722
+ code: "Código\nCtrl+E",
2723
+ superscript: "Superíndice",
2724
+ subscript: "Subíndice",
2725
+ highlight: "Resaltar",
2726
+ highlightPicker: "Color de resaltado",
2727
+ textColor: "Color del texto",
2728
+ link: "Enlace",
2729
+ addLink: "Insertar enlace",
2730
+ editLink: "Editar enlace",
2731
+ removeLink: "Quitar enlace",
2732
+ linkUrl: "URL del enlace",
2733
+ linkText: "Texto del enlace",
2734
+ openLink: "Abrir enlace",
2735
+ customColor: "Color personalizado",
2736
+ presets: "Predefinidos",
2737
+ },
2738
+ slashCommands: {
2739
+ heading1: {
2740
+ title: "Título 1",
2741
+ description: "Título de sección grande",
2742
+ keywords: ["heading", "h1", "title", "1", "header", "título", "titulo", "encabezado"],
2743
+ },
2744
+ heading2: {
2745
+ title: "Título 2",
2746
+ description: "Título de sección mediano",
2747
+ keywords: ["heading", "h2", "title", "2", "header", "título", "titulo", "subtítulo"],
2748
+ },
2749
+ heading3: {
2750
+ title: "Título 3",
2751
+ description: "Título de sección pequeño",
2752
+ keywords: ["heading", "h3", "title", "3", "header", "título", "titulo", "subtítulo"],
2753
+ },
2754
+ bulletList: {
2755
+ title: "Lista con viñetas",
2756
+ description: "Crear una lista con viñetas",
2757
+ keywords: ["bullet", "list", "ul", "unordered", "lista", "viñetas", "puntos"],
2758
+ },
2759
+ orderedList: {
2760
+ title: "Lista numerada",
2761
+ description: "Crear una lista numerada",
2762
+ keywords: ["ordered", "list", "ol", "numbered", "lista", "numerada", "ordenada"],
2763
+ },
2764
+ blockquote: {
2765
+ title: "Cita",
2766
+ description: "Añadir una cita",
2767
+ keywords: ["quote", "blockquote", "citation", "cita", "citar", "comillas"],
2768
+ },
2769
+ code: {
2770
+ title: "Bloque de código",
2771
+ description: "Añadir un bloque de código",
2772
+ keywords: ["code", "codeblock", "pre", "programming", "código", "codigo", "programación"],
2773
+ },
2774
+ image: {
2775
+ title: "Imagen",
2776
+ description: "Insertar una imagen",
2777
+ keywords: ["image", "photo", "picture", "img", "imagen", "foto"],
2778
+ },
2779
+ horizontalRule: {
2780
+ title: "Línea horizontal",
2781
+ description: "Añadir una línea divisoria",
2782
+ keywords: [
2783
+ "hr",
2784
+ "horizontal",
2785
+ "rule",
2786
+ "line",
2787
+ "separator",
2788
+ "línea",
2789
+ "linea",
2790
+ "divisor",
2791
+ "separador",
2792
+ ],
2793
+ },
2794
+ table: {
2795
+ title: "Tabla",
2796
+ description: "Insertar una tabla",
2797
+ keywords: [
2798
+ "table",
2799
+ "grid",
2800
+ "data",
2801
+ "rows",
2802
+ "columns",
2803
+ "tabla",
2804
+ "cuadrícula",
2805
+ "datos",
2806
+ "filas",
2807
+ "columnas",
2808
+ ],
2809
+ },
2810
+ tableOfContents: {
2811
+ title: "Índice",
2812
+ description: "Insertar un índice",
2813
+ keywords: [
2814
+ "toc",
2815
+ "table",
2816
+ "contents",
2817
+ "summary",
2818
+ "index",
2819
+ "headings",
2820
+ "outline",
2821
+ "índice",
2822
+ "indice",
2823
+ "contenido",
2824
+ "sumario",
2825
+ "títulos",
2826
+ ],
2827
+ },
2828
+ filterPlaceholder: "Filtrar...",
2829
+ },
2830
+ table: {
2831
+ addRowBefore: "Insertar fila arriba",
2832
+ addRowAfter: "Insertar fila abajo",
2833
+ deleteRow: "Eliminar fila",
2834
+ addColumnBefore: "Insertar columna a la izquierda",
2835
+ addColumnAfter: "Insertar columna a la derecha",
2836
+ deleteColumn: "Eliminar columna",
2837
+ deleteTable: "Eliminar tabla",
2838
+ toggleHeaderRow: "Alternar fila de encabezado",
2839
+ toggleHeaderColumn: "Alternar columna de encabezado",
2840
+ mergeCells: "Combinar celdas",
2841
+ splitCell: "Dividir celda",
2842
+ },
2843
+ imageUpload: {
2844
+ selectImage: "Seleccionar imagen",
2845
+ loadError: "Error al cargar la imagen",
2846
+ uploadingImage: "Subiendo imagen...",
2847
+ uploadProgress: "Progreso de la subida",
2848
+ uploadError: "Error al subir",
2849
+ uploadSuccess: "Subida completada",
2850
+ imageTooLarge: "Imagen demasiado grande",
2851
+ invalidFileType: "Tipo de archivo no válido",
2852
+ dragDropText: "Arrastra y suelta imágenes aquí",
2853
+ changeImage: "Cambiar imagen",
2854
+ downloadImage: "Descargar imagen",
2855
+ deleteImage: "Eliminar imagen",
2856
+ resizeSmall: "Pequeña",
2857
+ resizeMedium: "Mediana",
2858
+ resizeLarge: "Grande",
2859
+ resizeOriginal: "Original",
2860
+ alignLeft: "Alinear a la izquierda",
2861
+ alignCenter: "Centrar",
2862
+ alignRight: "Alinear a la derecha",
2863
+ resizing: "Redimensionando...",
2864
+ compressing: "Comprimiendo...",
2865
+ compressionError: "Error al comprimir la imagen",
2866
+ validating: "Validando archivo...",
2867
+ uploadingToServer: "Subiendo al servidor...",
2868
+ replacingImage: "Reemplazando imagen...",
2869
+ insertingImage: "Insertando en el editor...",
2870
+ noFileSelected: "Ningún archivo de imagen seleccionado",
2871
+ selectionCancelled: "Selección cancelada",
2872
+ },
2873
+ editor: {
2874
+ placeholder: "Empieza a escribir...",
2875
+ character: "carácter",
2876
+ characterPlural: "caracteres",
2877
+ word: "palabra",
2878
+ wordPlural: "palabras",
2879
+ linkPrompt: "Introduce la URL del enlace",
2880
+ linkUrlPrompt: "Introduce la URL",
2881
+ confirmDelete: "¿Seguro que quieres eliminar esto?",
2882
+ toggleEdit: "Cambiar al modo de edición",
2883
+ viewMode: "Cambiar al modo de lectura",
2884
+ blockAdd: "Haz clic para añadir un bloque",
2885
+ blockDrag: "Arrastra para mover este bloque",
2886
+ tableOfContents: "Índice",
2887
+ },
2888
+ common: {
2889
+ cancel: "Cancelar",
2890
+ confirm: "Confirmar",
2891
+ apply: "Aplicar",
2892
+ delete: "Eliminar",
2893
+ save: "Guardar",
2894
+ close: "Cerrar",
2895
+ loading: "Cargando",
2896
+ error: "Error",
2897
+ success: "Éxito",
2898
+ },
2899
+ export: {
2900
+ export: "Exportar",
2901
+ html: "HTML",
2902
+ markdown: "Markdown",
2903
+ text: "Texto sin formato",
2904
+ copyHtml: "Copiar como HTML",
2905
+ copyMarkdown: "Copiar como Markdown",
2906
+ copyText: "Copiar como texto sin formato",
2907
+ downloadHtml: "Descargar .html",
2908
+ downloadMarkdown: "Descargar .md",
2909
+ downloadText: "Descargar .txt",
2910
+ copiedSuccess: "¡Copiado al portapapeles!",
2911
+ },
2912
+ };
2913
+
2351
2914
  class AteI18nService {
2352
2915
  constructor() {
2353
2916
  this._currentLocale = signal("en");
@@ -2355,12 +2918,14 @@ class AteI18nService {
2355
2918
  en: ENGLISH_TRANSLATIONS,
2356
2919
  fr: FRENCH_TRANSLATIONS,
2357
2920
  de: GERMAN_TRANSLATIONS,
2921
+ pt: PORTUGUESE_TRANSLATIONS,
2922
+ es: SPANISH_TRANSLATIONS,
2358
2923
  });
2359
2924
  // Public signals
2360
2925
  this.currentLocale = this._currentLocale.asReadonly();
2361
2926
  /** All loaded translations (useful for dynamic key access) */
2362
2927
  this.allTranslations = this._translations.asReadonly();
2363
- this.translations = computed(() => this._translations()[this._currentLocale()] ?? this._translations().en);
2928
+ this.translations = computed(() => this.getTranslations(this._currentLocale()) ?? this._translations().en);
2364
2929
  // Fast translation methods
2365
2930
  this.t = computed(() => this.translations());
2366
2931
  this.toolbar = computed(() => this.translations().toolbar);
@@ -2395,14 +2960,20 @@ class AteI18nService {
2395
2960
  };
2396
2961
  });
2397
2962
  }
2398
- detectBrowserLanguage() {
2399
- const browserLang = navigator.language.toLowerCase();
2400
- if (browserLang.startsWith("fr")) {
2401
- this._currentLocale.set("fr");
2402
- }
2403
- else {
2404
- this._currentLocale.set("en");
2963
+ getTranslations(locale) {
2964
+ const resolved = this.resolveLocale(locale);
2965
+ return resolved ? this._translations()[resolved] : undefined;
2966
+ }
2967
+ resolveLocale(locale) {
2968
+ const all = this._translations();
2969
+ if (all[locale]) {
2970
+ return locale;
2405
2971
  }
2972
+ const language = locale.toLowerCase().split(/[-_]/)[0];
2973
+ return all[language] ? language : undefined;
2974
+ }
2975
+ detectBrowserLanguage() {
2976
+ this._currentLocale.set(this.resolveLocale(navigator.language) ?? "en");
2406
2977
  }
2407
2978
  // Utility methods for components
2408
2979
  getToolbarTitle(key) {
@@ -3037,6 +3608,14 @@ const AteTiptapStateExtension = Extension.create({
3037
3608
 
3038
3609
  // Pre-calculate platform once to avoid repeated checks
3039
3610
  const IS_MAC = typeof window !== "undefined" && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
3611
+ const DURATION = [100, 100];
3612
+ // After a tooltip closes, the next one still opens at once if hovered within this gap
3613
+ const WARM_GAP = 300;
3614
+ // Shared by every tooltip: the first one waits for its delay, the next ones open at once,
3615
+ // without animation, as long as the pointer moves from one control to the next.
3616
+ let openTooltip = null;
3617
+ let warm = false;
3618
+ let coolTimeout;
3040
3619
  class AteTooltipDirective {
3041
3620
  constructor() {
3042
3621
  this.el = inject(ElementRef);
@@ -3128,7 +3707,7 @@ class AteTooltipDirective {
3128
3707
  allowHTML,
3129
3708
  placement,
3130
3709
  delay,
3131
- duration: [100, 100],
3710
+ duration: DURATION,
3132
3711
  offset: [0, 6],
3133
3712
  theme: "ate-tooltip",
3134
3713
  touch: ["hold", 500],
@@ -3137,6 +3716,30 @@ class AteTooltipDirective {
3137
3716
  aria: {
3138
3717
  content: "describedby",
3139
3718
  },
3719
+ onTrigger: (instance, event) => {
3720
+ const base = this.delay();
3721
+ const instant = warm && event.type === "mouseenter";
3722
+ instance.setProps({
3723
+ delay: instant ? [0, Array.isArray(base) ? base[1] : base] : base,
3724
+ duration: instant ? [0, DURATION[1]] : DURATION,
3725
+ });
3726
+ },
3727
+ onShow: instance => {
3728
+ // Only one tooltip at a time: the previous one goes away at once
3729
+ if (openTooltip && openTooltip !== instance) {
3730
+ openTooltip.unmount();
3731
+ }
3732
+ openTooltip = instance;
3733
+ warm = true;
3734
+ clearTimeout(coolTimeout);
3735
+ },
3736
+ onHidden: instance => {
3737
+ if (openTooltip !== instance) {
3738
+ return;
3739
+ }
3740
+ openTooltip = null;
3741
+ coolTimeout = setTimeout(() => (warm = false), WARM_GAP);
3742
+ },
3140
3743
  popperOptions: {
3141
3744
  modifiers: [
3142
3745
  {
@@ -3152,6 +3755,9 @@ class AteTooltipDirective {
3152
3755
  }
3153
3756
  destroyTippy() {
3154
3757
  if (this.tippyInstance) {
3758
+ if (openTooltip === this.tippyInstance) {
3759
+ openTooltip = null;
3760
+ }
3155
3761
  this.tippyInstance.destroy();
3156
3762
  this.tippyInstance = null;
3157
3763
  }
@@ -3475,12 +4081,13 @@ class AteImageService {
3475
4081
  const maxSize = options?.maxSize || 10 * 1024 * 1024;
3476
4082
  const allowedTypes = options?.allowedTypes || [];
3477
4083
  if (allowedTypes.length > 0 && !allowedTypes.includes(file.type)) {
3478
- return { valid: false, error: this.t().invalidFileType };
4084
+ return { valid: false, error: this.t().invalidFileType, reason: "invalid-type" };
3479
4085
  }
3480
4086
  if (file.size > maxSize) {
3481
4087
  return {
3482
4088
  valid: false,
3483
4089
  error: `${this.t().imageTooLarge} (max ${Math.round(maxSize / 1024 / 1024)}MB)`,
4090
+ reason: "too-large",
3484
4091
  };
3485
4092
  }
3486
4093
  return { valid: true };
@@ -3536,7 +4143,7 @@ class AteImageService {
3536
4143
  });
3537
4144
  }
3538
4145
  /** Core upload logic with progress tracking */
3539
- async uploadImageWithProgress(editor, file, insertionStrategy, actionMessage, options) {
4146
+ async uploadImageWithProgress(editor, file, insertionStrategy, actionMessage, options, source) {
3540
4147
  try {
3541
4148
  this.currentEditor = editor;
3542
4149
  this.isUploading.set(true);
@@ -3565,6 +4172,11 @@ class AteImageService {
3565
4172
  catch (error) {
3566
4173
  this.resetUploadState();
3567
4174
  console.error(this.t().uploadError, error);
4175
+ this.onImageRejectedCallback?.({
4176
+ reason: error instanceof AteImageValidationError ? error.reason : "upload-failed",
4177
+ file,
4178
+ source,
4179
+ });
3568
4180
  throw error;
3569
4181
  }
3570
4182
  }
@@ -3575,7 +4187,7 @@ class AteImageService {
3575
4187
  allowedTypes: options?.allowedTypes,
3576
4188
  });
3577
4189
  if (!validation.valid) {
3578
- throw new Error(validation.error);
4190
+ throw new AteImageValidationError(validation.reason ?? "invalid-type", validation.error ?? "");
3579
4191
  }
3580
4192
  onStep?.(30, this.t().compressing);
3581
4193
  const result = await this.compressImage(file, options?.quality || 0.8, options?.maxWidth || 1920, options?.maxHeight || 1200);
@@ -3631,7 +4243,7 @@ class AteImageService {
3631
4243
  this.currentEditor = null;
3632
4244
  }
3633
4245
  /** Main entry point for file upload and insertion */
3634
- async uploadAndInsertImage(editor, file, options) {
4246
+ async uploadAndInsertImage(editor, file, options, source = "api") {
3635
4247
  return this.uploadImageWithProgress(editor, file, (ed, result) => {
3636
4248
  this.insertImage(ed, {
3637
4249
  src: result.src,
@@ -3640,7 +4252,7 @@ class AteImageService {
3640
4252
  width: result.width,
3641
4253
  height: result.height,
3642
4254
  });
3643
- }, this.t().insertingImage, options);
4255
+ }, this.t().insertingImage, options, source);
3644
4256
  }
3645
4257
  /** Trigger an editor transaction to force decoration update */
3646
4258
  forceEditorUpdate() {
@@ -3666,7 +4278,7 @@ class AteImageService {
3666
4278
  const file = e.target.files?.[0];
3667
4279
  if (file && file.type.startsWith("image/")) {
3668
4280
  try {
3669
- await uploadMethod(editor, file, options);
4281
+ await uploadMethod(editor, file, options, "picker");
3670
4282
  resolve();
3671
4283
  }
3672
4284
  catch (error) {
@@ -3697,7 +4309,7 @@ class AteImageService {
3697
4309
  return this.selectFileAndProcess(editor, this.uploadAndReplaceImage.bind(this), options);
3698
4310
  }
3699
4311
  /** Internal helper used by replacement logic */
3700
- async uploadAndReplaceImage(editor, file, options) {
4312
+ async uploadAndReplaceImage(editor, file, options, source = "api") {
3701
4313
  // Store current position to ensure we can re-select the image even if selection blurs during upload
3702
4314
  const wasActive = editor.isActive("resizableImage");
3703
4315
  await this.uploadImageWithProgress(editor, file, (ed, result) => {
@@ -3727,7 +4339,7 @@ class AteImageService {
3727
4339
  }
3728
4340
  // After replacement, ensure the image is tracked in our signals
3729
4341
  this.selectImage(ed);
3730
- }, this.t().replacingImage, options);
4342
+ }, this.t().replacingImage, options, source);
3731
4343
  }
3732
4344
  /**
3733
4345
  * Handle image drop event.
@@ -3749,7 +4361,7 @@ class AteImageService {
3749
4361
  if (pos) {
3750
4362
  editor.commands.setTextSelection(pos.pos);
3751
4363
  }
3752
- void this.uploadAndInsertImage(editor, file, options);
4364
+ this.uploadAndInsertImage(editor, file, options, "drop").catch(() => undefined);
3753
4365
  return true;
3754
4366
  }
3755
4367
  /**
@@ -3765,7 +4377,7 @@ class AteImageService {
3765
4377
  return false;
3766
4378
  }
3767
4379
  event.preventDefault();
3768
- void this.uploadAndInsertImage(editor, imageFile, options);
4380
+ this.uploadAndInsertImage(editor, imageFile, options, "paste").catch(() => undefined);
3769
4381
  return true;
3770
4382
  }
3771
4383
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
@@ -4448,6 +5060,9 @@ class AteEditorCommandsService {
4448
5060
  set onImageUploaded(callback) {
4449
5061
  this.imageService.onImageUploadedCallback = callback || undefined;
4450
5062
  }
5063
+ set onImageRejected(callback) {
5064
+ this.imageService.onImageRejectedCallback = callback || undefined;
5065
+ }
4451
5066
  set uploadHandler(handler) {
4452
5067
  this.imageService.uploadHandler = handler;
4453
5068
  }
@@ -4519,10 +5134,10 @@ class AteEditorCommandsService {
4519
5134
  this.insertHorizontalRule(editor);
4520
5135
  break;
4521
5136
  case "insertImage":
4522
- this.insertImage(editor, args[0]);
5137
+ this.insertImage(editor, args[0]).catch(() => undefined);
4523
5138
  break;
4524
5139
  case "uploadImage":
4525
- this.uploadImage(editor, args[0], args[1]);
5140
+ this.uploadImage(editor, args[0], args[1]).catch(() => undefined);
4526
5141
  break;
4527
5142
  case "toggleHighlight":
4528
5143
  this.toggleHighlight(editor, args[0]);
@@ -5634,6 +6249,7 @@ const ATE_DEFAULT_CONFIG = {
5634
6249
  showTableMenu: true,
5635
6250
  showCellMenu: true,
5636
6251
  enableSlashCommands: true,
6252
+ enableBlockShortcuts: true,
5637
6253
  blockControls: "none",
5638
6254
  floatingToolbar: false,
5639
6255
  toolbar: ATE_DEFAULT_TOOLBAR_CONFIG,
@@ -5645,6 +6261,7 @@ const ATE_DEFAULT_CONFIG = {
5645
6261
  slashCommands: {},
5646
6262
  tiptapExtensions: [],
5647
6263
  tiptapOptions: {},
6264
+ starterKitOptions: {},
5648
6265
  stateCalculators: [],
5649
6266
  angularNodes: [],
5650
6267
  };
@@ -7709,6 +8326,7 @@ function createDefaultSlashCommands(i18n, commands, imageOptions) {
7709
8326
  quality: imageOptions?.quality,
7710
8327
  maxWidth: imageOptions?.maxWidth,
7711
8328
  maxHeight: imageOptions?.maxHeight,
8329
+ maxSize: imageOptions?.maxSize,
7712
8330
  allowedTypes: imageOptions?.allowedTypes,
7713
8331
  }),
7714
8332
  },
@@ -8872,6 +9490,85 @@ function shallowObjectEqual(a, b) {
8872
9490
  a[key] === b[key]));
8873
9491
  }
8874
9492
 
9493
+ /**
9494
+ * Maps the runtime `.name` of each extension bundled in `@tiptap/starter-kit`
9495
+ * to its corresponding option key in `StarterKitOptions`.
9496
+ */
9497
+ const STARTER_KIT_NAME_TO_OPTION = {
9498
+ blockquote: "blockquote",
9499
+ bold: "bold",
9500
+ bulletList: "bulletList",
9501
+ code: "code",
9502
+ codeBlock: "codeBlock",
9503
+ doc: "document",
9504
+ dropCursor: "dropcursor",
9505
+ gapCursor: "gapcursor",
9506
+ hardBreak: "hardBreak",
9507
+ heading: "heading",
9508
+ undoRedo: "undoRedo",
9509
+ horizontalRule: "horizontalRule",
9510
+ italic: "italic",
9511
+ listItem: "listItem",
9512
+ listKeymap: "listKeymap",
9513
+ link: "link",
9514
+ orderedList: "orderedList",
9515
+ paragraph: "paragraph",
9516
+ strike: "strike",
9517
+ text: "text",
9518
+ underline: "underline",
9519
+ trailingNode: "trailingNode",
9520
+ };
9521
+ /**
9522
+ * Describes which parts of Angular Tiptap Editor's UI or state calculators
9523
+ * depend on a given built-in or StarterKit extension name.
9524
+ */
9525
+ const ATE_BUILTIN_UI_DEPENDENCIES = {
9526
+ blockquote: "toolbar/slash menu blockquote buttons, AteStructureCalculator",
9527
+ bold: "toolbar/bubble menu bold buttons, AteMarksCalculator",
9528
+ bulletList: "toolbar/slash menu bullet list buttons, AteStructureCalculator",
9529
+ code: "toolbar/bubble menu inline code buttons, AteMarksCalculator",
9530
+ codeBlock: "toolbar/slash menu code block buttons, AteStructureCalculator",
9531
+ doc: "top-level ProseMirror document schema",
9532
+ dropCursor: "drag-and-drop cursor indicator",
9533
+ gapCursor: "gap cursor navigation around leaf block nodes",
9534
+ hardBreak: "Shift+Enter line break shortcut",
9535
+ heading: "toolbar/bubble menu/slash menu heading controls, table of contents, AteStructureCalculator",
9536
+ undoRedo: "toolbar undo/redo buttons, AteStructureCalculator",
9537
+ horizontalRule: "toolbar/slash menu horizontal rule buttons",
9538
+ italic: "toolbar/bubble menu italic buttons, AteMarksCalculator",
9539
+ listItem: "bullet/ordered list items, block shortcuts",
9540
+ listKeymap: "list backspace/delete keyboard navigation",
9541
+ link: "toolbar/bubble menu link editor, Mod+K shortcut, AteMarksCalculator",
9542
+ orderedList: "toolbar/slash menu ordered list buttons, AteStructureCalculator",
9543
+ paragraph: "default text block node, AteStructureCalculator",
9544
+ strike: "toolbar/bubble menu strikethrough buttons, AteMarksCalculator",
9545
+ text: "core inline text node",
9546
+ underline: "toolbar/bubble menu underline buttons, AteMarksCalculator",
9547
+ trailingNode: "automatic trailing paragraph after block nodes",
9548
+ textStyle: "color picker, AteMarksCalculator",
9549
+ color: "toolbar/bubble menu text color picker, AteMarksCalculator",
9550
+ placeholder: "empty editor placeholder decoration",
9551
+ superscript: "toolbar/bubble menu superscript buttons, AteMarksCalculator",
9552
+ subscript: "toolbar/bubble menu subscript buttons, AteMarksCalculator",
9553
+ textAlign: "toolbar/image bubble menu alignment buttons, AteStructureCalculator",
9554
+ ateLinkClickBehavior: "read-only and Ctrl+click link navigation",
9555
+ ateBlockShortcuts: "Mod+D and Mod+Shift+ArrowUp/Down block shortcuts",
9556
+ ateLinkShortcut: "Mod+K link editor shortcut",
9557
+ highlight: "toolbar/bubble menu highlight picker, AteMarksCalculator",
9558
+ resizableImage: "image node view, image bubble menu, image upload/resize service, AteImageCalculator",
9559
+ atePastedImage: "pasted HTML image sanitization and base64 re-hosting",
9560
+ ateUploadProgress: "image upload progress overlay",
9561
+ tableExtension: "toolbar/slash menu table insertion, table/cell bubble menus, AteTableCalculator",
9562
+ tableOfContents: "slash menu table of contents node, AteTableOfContentsComponent",
9563
+ tiptapState: "reactive editor state engine (toolbar, bubble menus, footer)",
9564
+ blockControls: "block plus button and drag handle",
9565
+ officePaste: "Word/Excel paste normalization",
9566
+ characterCount: "footer character/word counters and maxCharacters limit",
9567
+ };
9568
+ function getExtensionName(ext) {
9569
+ return ext?.name;
9570
+ }
9571
+
8875
9572
  function transformBooleanInput(val) {
8876
9573
  if (val === undefined || val === null) {
8877
9574
  return undefined;
@@ -8927,6 +9624,9 @@ class AngularTiptapEditorComponent {
8927
9624
  this.enableSlashCommands = input(undefined, {
8928
9625
  transform: transformBooleanInput,
8929
9626
  });
9627
+ this.enableBlockShortcuts = input(undefined, {
9628
+ transform: transformBooleanInput,
9629
+ });
8930
9630
  this.slashCommands = input(undefined);
8931
9631
  this.customSlashCommands = input(undefined);
8932
9632
  this.blockControls = input();
@@ -8943,6 +9643,7 @@ class AngularTiptapEditorComponent {
8943
9643
  this.spellcheck = input(undefined, { transform: transformBooleanInput });
8944
9644
  this.tiptapExtensions = input(undefined);
8945
9645
  this.tiptapOptions = input(undefined);
9646
+ this.starterKitOptions = input(undefined);
8946
9647
  // Nouveaux inputs pour les bubble menus
8947
9648
  this.showBubbleMenu = input(undefined, {
8948
9649
  transform: transformBooleanInput,
@@ -9002,6 +9703,8 @@ class AngularTiptapEditorComponent {
9002
9703
  this.editorBlur = output();
9003
9704
  this.editableChange = output();
9004
9705
  this.imageUploaded = output();
9706
+ /** Emitted when an image file is rejected (disallowed type, too large or failed upload) */
9707
+ this.imageRejected = output();
9005
9708
  /** Emitted when an image from pasted HTML is dropped (unreachable source or failed upload) */
9006
9709
  this.pastedImageRejected = output();
9007
9710
  // ViewChild with signal
@@ -9152,6 +9855,7 @@ class AngularTiptapEditorComponent {
9152
9855
  // Behavior
9153
9856
  this.finalAutofocus = computed(() => this.autofocus() ?? this.effectiveConfig().autofocus);
9154
9857
  this.finalMaxCharacters = computed(() => this.maxCharacters() ?? this.effectiveConfig().maxCharacters);
9858
+ this.finalEnableBlockShortcuts = computed(() => this.enableBlockShortcuts() ?? this.effectiveConfig().enableBlockShortcuts ?? true);
9155
9859
  this.finalBlockControls = computed(() => this.blockControls() ?? this.effectiveConfig().blockControls ?? "none");
9156
9860
  this.finalShowCharacterCount = computed(() => this.showCharacterCount() ?? this.effectiveConfig().showCharacterCount ?? true);
9157
9861
  this.finalShowWordCount = computed(() => this.showWordCount() ?? this.effectiveConfig().showWordCount ?? true);
@@ -9159,6 +9863,7 @@ class AngularTiptapEditorComponent {
9159
9863
  // Extensions & Options
9160
9864
  this.finalTiptapExtensions = computed(() => this.tiptapExtensions() ?? this.effectiveConfig().tiptapExtensions ?? [], { equal: shallowArrayEqual });
9161
9865
  this.finalTiptapOptions = computed(() => this.tiptapOptions() ?? this.effectiveConfig().tiptapOptions ?? {}, { equal: shallowObjectEqual });
9866
+ this.finalStarterKitOptions = computed(() => this.starterKitOptions() ?? this.effectiveConfig().starterKitOptions ?? {}, { equal: shallowObjectEqual });
9162
9867
  this.finalStateCalculators = computed(() => this.stateCalculators() ?? this.effectiveConfig().stateCalculators ?? []);
9163
9868
  this.finalAngularNodesConfig = computed(() => this.effectiveConfig().angularNodes ?? [], {
9164
9869
  equal: shallowArrayEqual,
@@ -9183,8 +9888,7 @@ class AngularTiptapEditorComponent {
9183
9888
  this.currentTranslations = computed(() => {
9184
9889
  const localeOverride = this.finalLocale();
9185
9890
  if (localeOverride) {
9186
- const allTranslations = this.i18nService.allTranslations();
9187
- return allTranslations[localeOverride] || this.i18nService.translations();
9891
+ return this.i18nService.getTranslations(localeOverride) ?? this.i18nService.translations();
9188
9892
  }
9189
9893
  return this.i18nService.translations();
9190
9894
  });
@@ -9196,6 +9900,7 @@ class AngularTiptapEditorComponent {
9196
9900
  // Access editor state via service
9197
9901
  this.editorState = this.editorCommandsService.editorState;
9198
9902
  this.editorRegistry = inject(AteEditorRegistry);
9903
+ this.warnedExtensionOverrides = new Set();
9199
9904
  this.iconRegistry = inject(AteIconRegistry);
9200
9905
  this._registeredId = signal(null);
9201
9906
  this.registeredId = this._registeredId.asReadonly();
@@ -9281,6 +9986,7 @@ class AngularTiptapEditorComponent {
9281
9986
  // Monitor technical dependencies
9282
9987
  this.finalTiptapExtensions();
9283
9988
  this.finalTiptapOptions();
9989
+ this.finalStarterKitOptions();
9284
9990
  this.finalAngularNodesConfig();
9285
9991
  this.finalBlockControls();
9286
9992
  untracked(() => {
@@ -9298,6 +10004,9 @@ class AngularTiptapEditorComponent {
9298
10004
  this.editorCommandsService.onImageUploaded = result => {
9299
10005
  this.imageUploaded.emit(result);
9300
10006
  };
10007
+ this.editorCommandsService.onImageRejected = rejection => {
10008
+ this.imageRejected.emit(rejection);
10009
+ };
9301
10010
  }
9302
10011
  ngAfterViewInit() {
9303
10012
  // La vue est déjà complètement initialisée dans ngAfterViewInit
@@ -9319,15 +10028,46 @@ class AngularTiptapEditorComponent {
9319
10028
  }
9320
10029
  }
9321
10030
  initEditor() {
9322
- const extensions = [
9323
- StarterKit.configure({
9324
- link: {
9325
- openOnClick: false,
10031
+ const starterKitOptions = this.finalStarterKitOptions();
10032
+ const customExtensions = this.finalTiptapExtensions();
10033
+ const customNames = new Set(customExtensions.map(getExtensionName).filter((name) => !!name));
10034
+ const defaultLinkOptions = {
10035
+ openOnClick: false,
10036
+ HTMLAttributes: {
10037
+ class: "ate-link",
10038
+ },
10039
+ };
10040
+ const effectiveStarterKitOptions = {
10041
+ ...starterKitOptions,
10042
+ link: starterKitOptions.link === false
10043
+ ? false
10044
+ : {
10045
+ ...defaultLinkOptions,
10046
+ ...starterKitOptions.link,
9326
10047
  HTMLAttributes: {
9327
- class: "ate-link",
10048
+ ...defaultLinkOptions.HTMLAttributes,
10049
+ ...starterKitOptions.link?.HTMLAttributes,
9328
10050
  },
9329
10051
  },
9330
- }),
10052
+ };
10053
+ const replacedNames = [];
10054
+ const ignoredStarterKitOptionKeys = [];
10055
+ for (const customName of customNames) {
10056
+ const optionKey = STARTER_KIT_NAME_TO_OPTION[customName];
10057
+ if (!optionKey) {
10058
+ continue;
10059
+ }
10060
+ const userStarterKitValue = starterKitOptions[optionKey];
10061
+ if (userStarterKitValue !== undefined && userStarterKitValue !== false) {
10062
+ ignoredStarterKitOptionKeys.push(optionKey);
10063
+ }
10064
+ if (userStarterKitValue !== false) {
10065
+ replacedNames.push(customName);
10066
+ }
10067
+ effectiveStarterKitOptions[optionKey] = false;
10068
+ }
10069
+ const extensions = [
10070
+ StarterKit.configure(effectiveStarterKitOptions),
9331
10071
  TextStyle,
9332
10072
  Color.configure({
9333
10073
  types: ["textStyle"],
@@ -9341,6 +10081,9 @@ class AngularTiptapEditorComponent {
9341
10081
  types: ["heading", "paragraph", "resizableImage"],
9342
10082
  }),
9343
10083
  AteLinkClickBehavior,
10084
+ AteBlockShortcuts.configure({
10085
+ enabled: () => this.finalEnableBlockShortcuts(),
10086
+ }),
9344
10087
  AteLinkShortcut.configure({
9345
10088
  canOpen: () => this.editorCommandsService.editorState().can.toggleLink,
9346
10089
  open: editor => this.editorCommandsService.execute(editor, "toggleLink"),
@@ -9416,17 +10159,41 @@ class AngularTiptapEditorComponent {
9416
10159
  console.error("[ATE] Failed to auto-register node view:", e);
9417
10160
  }
9418
10161
  });
9419
- // Allow addition of custom extensions, but avoid duplicates by filtering by name
9420
- const customExtensions = this.finalTiptapExtensions();
10162
+ // Custom extensions in tiptapExtensions take precedence over built-in extensions of the same name
9421
10163
  if (customExtensions.length > 0) {
9422
- const existingNames = new Set(extensions
9423
- .map((ext) => ext?.name)
9424
- .filter((name) => !!name));
9425
- const toAdd = customExtensions.filter((ext) => {
9426
- const name = ext?.name;
9427
- return !name || !existingNames.has(name);
9428
- });
9429
- extensions.push(...toAdd);
10164
+ for (let i = extensions.length - 1; i >= 0; i--) {
10165
+ const name = getExtensionName(extensions[i]);
10166
+ if (name && customNames.has(name)) {
10167
+ replacedNames.push(name);
10168
+ extensions.splice(i, 1);
10169
+ }
10170
+ }
10171
+ extensions.push(...customExtensions);
10172
+ if (isDevMode()) {
10173
+ const newlyReplaced = replacedNames.filter(name => !this.warnedExtensionOverrides.has(`override:${name}`));
10174
+ const newlyIgnoredOptions = ignoredStarterKitOptionKeys.filter(key => !this.warnedExtensionOverrides.has(`conflict:${key}`));
10175
+ if (newlyReplaced.length > 0 || newlyIgnoredOptions.length > 0) {
10176
+ newlyReplaced.forEach(name => this.warnedExtensionOverrides.add(`override:${name}`));
10177
+ newlyIgnoredOptions.forEach(key => this.warnedExtensionOverrides.add(`conflict:${key}`));
10178
+ const parts = [];
10179
+ if (newlyReplaced.length > 0) {
10180
+ const details = newlyReplaced
10181
+ .map(name => {
10182
+ const deps = ATE_BUILTIN_UI_DEPENDENCIES[name];
10183
+ return deps ? `${name} (used by: ${deps})` : name;
10184
+ })
10185
+ .join("; ");
10186
+ parts.push(`Custom extension(s) in tiptapExtensions replaced built-in extension(s): ${details}.`);
10187
+ }
10188
+ if (newlyIgnoredOptions.length > 0) {
10189
+ const ignoredList = newlyIgnoredOptions
10190
+ .map(key => `starterKitOptions.${key}`)
10191
+ .join(", ");
10192
+ parts.push(`${ignoredList} was ignored because the custom extension in tiptapExtensions takes precedence.`);
10193
+ }
10194
+ console.warn(`[ATE] ${parts.join(" ")}`);
10195
+ }
10196
+ }
9430
10197
  }
9431
10198
  // Also allow any tiptap user options
9432
10199
  const userOptions = this.finalTiptapOptions();
@@ -9645,7 +10412,7 @@ class AngularTiptapEditorComponent {
9645
10412
  }
9646
10413
  }
9647
10414
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AngularTiptapEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9648
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AngularTiptapEditorComponent, isStandalone: true, selector: "angular-tiptap-editor", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, fillContainer: { classPropertyName: "fillContainer", publicName: "fillContainer", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showFooter: { classPropertyName: "showFooter", publicName: "showFooter", isSignal: true, isRequired: false, transformFunction: null }, showCharacterCount: { classPropertyName: "showCharacterCount", publicName: "showCharacterCount", isSignal: true, isRequired: false, transformFunction: null }, showWordCount: { classPropertyName: "showWordCount", publicName: "showWordCount", isSignal: true, isRequired: false, transformFunction: null }, maxCharacters: { classPropertyName: "maxCharacters", publicName: "maxCharacters", isSignal: true, isRequired: false, transformFunction: null }, enableOfficePaste: { classPropertyName: "enableOfficePaste", publicName: "enableOfficePaste", isSignal: true, isRequired: false, transformFunction: null }, enableSlashCommands: { classPropertyName: "enableSlashCommands", publicName: "enableSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, slashCommands: { classPropertyName: "slashCommands", publicName: "slashCommands", isSignal: true, isRequired: false, transformFunction: null }, customSlashCommands: { classPropertyName: "customSlashCommands", publicName: "customSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, blockControls: { classPropertyName: "blockControls", publicName: "blockControls", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, seamless: { classPropertyName: "seamless", publicName: "seamless", isSignal: true, isRequired: false, transformFunction: null }, floatingToolbar: { classPropertyName: "floatingToolbar", publicName: "floatingToolbar", isSignal: true, isRequired: false, transformFunction: null }, showEditToggle: { classPropertyName: "showEditToggle", publicName: "showEditToggle", isSignal: true, isRequired: false, transformFunction: null }, spellcheck: { classPropertyName: "spellcheck", publicName: "spellcheck", isSignal: true, isRequired: false, transformFunction: null }, tiptapExtensions: { classPropertyName: "tiptapExtensions", publicName: "tiptapExtensions", isSignal: true, isRequired: false, transformFunction: null }, tiptapOptions: { classPropertyName: "tiptapOptions", publicName: "tiptapOptions", isSignal: true, isRequired: false, transformFunction: null }, showBubbleMenu: { classPropertyName: "showBubbleMenu", publicName: "showBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, bubbleMenu: { classPropertyName: "bubbleMenu", publicName: "bubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showImageBubbleMenu: { classPropertyName: "showImageBubbleMenu", publicName: "showImageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, imageBubbleMenu: { classPropertyName: "imageBubbleMenu", publicName: "imageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, showTableBubbleMenu: { classPropertyName: "showTableBubbleMenu", publicName: "showTableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, tableBubbleMenu: { classPropertyName: "tableBubbleMenu", publicName: "tableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showCellBubbleMenu: { classPropertyName: "showCellBubbleMenu", publicName: "showCellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, cellBubbleMenu: { classPropertyName: "cellBubbleMenu", publicName: "cellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, stateCalculators: { classPropertyName: "stateCalculators", publicName: "stateCalculators", isSignal: true, isRequired: false, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null }, imageUploadHandler: { classPropertyName: "imageUploadHandler", publicName: "imageUploadHandler", isSignal: true, isRequired: false, transformFunction: null }, editorId: { classPropertyName: "editorId", publicName: "editorId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentChange: "contentChange", editorCreated: "editorCreated", editorUpdate: "editorUpdate", editorFocus: "editorFocus", editorBlur: "editorBlur", editableChange: "editableChange", imageUploaded: "imageUploaded", pastedImageRejected: "pastedImageRejected" }, host: { properties: { "class.fill-container": "finalFillContainer()", "class.floating-toolbar": "finalFloatingToolbar()", "class.is-readonly": "!finalEditable() && !mergedDisabled()", "class.is-disabled": "mergedDisabled()", "style.--ate-border-width": "finalSeamless() || mergedDisabled() ? '0' : null", "style.--ate-background": "finalSeamless() ? 'transparent' : (mergedDisabled() ? 'var(--ate-surface-tertiary)' : null)", "style.--ate-toolbar-border-color": "finalSeamless() ? 'transparent' : null", "style.--ate-counter-background": "finalSeamless() ? 'transparent' : null", "style.--ate-counter-border-color": "finalSeamless() ? 'transparent' : null", "class.dark": "config().theme === 'dark'", "class.ate-blocks-inside": "finalBlockControls() === 'inside'", "class.ate-blocks-outside": "finalBlockControls() === 'outside'", "attr.data-theme": "config().theme" } }, providers: [
10415
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AngularTiptapEditorComponent, isStandalone: true, selector: "angular-tiptap-editor", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, fillContainer: { classPropertyName: "fillContainer", publicName: "fillContainer", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showFooter: { classPropertyName: "showFooter", publicName: "showFooter", isSignal: true, isRequired: false, transformFunction: null }, showCharacterCount: { classPropertyName: "showCharacterCount", publicName: "showCharacterCount", isSignal: true, isRequired: false, transformFunction: null }, showWordCount: { classPropertyName: "showWordCount", publicName: "showWordCount", isSignal: true, isRequired: false, transformFunction: null }, maxCharacters: { classPropertyName: "maxCharacters", publicName: "maxCharacters", isSignal: true, isRequired: false, transformFunction: null }, enableOfficePaste: { classPropertyName: "enableOfficePaste", publicName: "enableOfficePaste", isSignal: true, isRequired: false, transformFunction: null }, enableSlashCommands: { classPropertyName: "enableSlashCommands", publicName: "enableSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, enableBlockShortcuts: { classPropertyName: "enableBlockShortcuts", publicName: "enableBlockShortcuts", isSignal: true, isRequired: false, transformFunction: null }, slashCommands: { classPropertyName: "slashCommands", publicName: "slashCommands", isSignal: true, isRequired: false, transformFunction: null }, customSlashCommands: { classPropertyName: "customSlashCommands", publicName: "customSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, blockControls: { classPropertyName: "blockControls", publicName: "blockControls", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, seamless: { classPropertyName: "seamless", publicName: "seamless", isSignal: true, isRequired: false, transformFunction: null }, floatingToolbar: { classPropertyName: "floatingToolbar", publicName: "floatingToolbar", isSignal: true, isRequired: false, transformFunction: null }, showEditToggle: { classPropertyName: "showEditToggle", publicName: "showEditToggle", isSignal: true, isRequired: false, transformFunction: null }, spellcheck: { classPropertyName: "spellcheck", publicName: "spellcheck", isSignal: true, isRequired: false, transformFunction: null }, tiptapExtensions: { classPropertyName: "tiptapExtensions", publicName: "tiptapExtensions", isSignal: true, isRequired: false, transformFunction: null }, tiptapOptions: { classPropertyName: "tiptapOptions", publicName: "tiptapOptions", isSignal: true, isRequired: false, transformFunction: null }, starterKitOptions: { classPropertyName: "starterKitOptions", publicName: "starterKitOptions", isSignal: true, isRequired: false, transformFunction: null }, showBubbleMenu: { classPropertyName: "showBubbleMenu", publicName: "showBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, bubbleMenu: { classPropertyName: "bubbleMenu", publicName: "bubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showImageBubbleMenu: { classPropertyName: "showImageBubbleMenu", publicName: "showImageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, imageBubbleMenu: { classPropertyName: "imageBubbleMenu", publicName: "imageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, showTableBubbleMenu: { classPropertyName: "showTableBubbleMenu", publicName: "showTableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, tableBubbleMenu: { classPropertyName: "tableBubbleMenu", publicName: "tableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showCellBubbleMenu: { classPropertyName: "showCellBubbleMenu", publicName: "showCellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, cellBubbleMenu: { classPropertyName: "cellBubbleMenu", publicName: "cellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, stateCalculators: { classPropertyName: "stateCalculators", publicName: "stateCalculators", isSignal: true, isRequired: false, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null }, imageUploadHandler: { classPropertyName: "imageUploadHandler", publicName: "imageUploadHandler", isSignal: true, isRequired: false, transformFunction: null }, editorId: { classPropertyName: "editorId", publicName: "editorId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentChange: "contentChange", editorCreated: "editorCreated", editorUpdate: "editorUpdate", editorFocus: "editorFocus", editorBlur: "editorBlur", editableChange: "editableChange", imageUploaded: "imageUploaded", imageRejected: "imageRejected", pastedImageRejected: "pastedImageRejected" }, host: { properties: { "class.fill-container": "finalFillContainer()", "class.floating-toolbar": "finalFloatingToolbar()", "class.is-readonly": "!finalEditable() && !mergedDisabled()", "class.is-disabled": "mergedDisabled()", "style.--ate-border-width": "finalSeamless() || mergedDisabled() ? '0' : null", "style.--ate-background": "finalSeamless() ? 'transparent' : (mergedDisabled() ? 'var(--ate-surface-tertiary)' : null)", "style.--ate-toolbar-border-color": "finalSeamless() ? 'transparent' : null", "style.--ate-counter-background": "finalSeamless() ? 'transparent' : null", "style.--ate-counter-border-color": "finalSeamless() ? 'transparent' : null", "class.dark": "config().theme === 'dark'", "class.ate-blocks-inside": "finalBlockControls() === 'inside'", "class.ate-blocks-outside": "finalBlockControls() === 'outside'", "attr.data-theme": "config().theme" } }, providers: [
9649
10416
  AteEditorCommandsService,
9650
10417
  AteImageService,
9651
10418
  AteColorPickerService,
@@ -10141,5 +10908,5 @@ const ATE_DEFAULT_TOC_CONFIG = {
10141
10908
  * Generated bundle index. Do not edit.
10142
10909
  */
10143
10910
 
10144
- export { ATE_BUBBLE_MENU_KEYS, ATE_CELL_BUBBLE_MENU_KEYS, ATE_DEFAULT_BUBBLE_MENU_CONFIG, ATE_DEFAULT_CELL_MENU_CONFIG, ATE_DEFAULT_CONFIG, ATE_DEFAULT_ICONS, ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ATE_DEFAULT_IMAGE_UPLOAD_CONFIG, ATE_DEFAULT_SLASH_COMMANDS_CONFIG, ATE_DEFAULT_TABLE_MENU_CONFIG, ATE_DEFAULT_TOC_CONFIG, ATE_DEFAULT_TOOLBAR_CONFIG, ATE_GLOBAL_CONFIG, ATE_ICONS, ATE_IMAGE_BUBBLE_MENU_KEYS, ATE_INITIAL_EDITOR_STATE, ATE_MATERIAL_SYMBOLS_VIEWBOX, ATE_SLASH_COMMAND_KEYS, ATE_STROKE_ICONS, ATE_TABLE_BUBBLE_MENU_KEYS, ATE_TOOLBAR_KEYS, AngularTiptapEditorComponent, AteAngularNodeView, AteColorPickerService, AteDiscoveryCalculator, AteEditorCommandsService, AteEditorRef, AteEditorRegistry, AteExportService, AteI18nService, AteIconComponent, AteIconRegistry, AteImageCalculator, AteImageService, AteLinkService, AteLinkShortcut, AteMarksCalculator, AteNodeViewRenderer, AteNoopValueAccessorDirective, AtePastedImage, AteSelectionCalculator, AteStructureCalculator, AteTableCalculator, AteTableOfContentsComponent, AteTocNodeComponent, AteTocNodeOptions, AteTooltipDirective, classifyPastedImageSrc, createAngularComponentExtension, createDefaultSlashCommands, dataUriToFile, filterSlashCommands, getAteTocNodeExtension, isLinkShortcut, provideAteEditor, provideAteIcons, registerAngularComponent, sanitizePastedImages };
10911
+ export { ATE_BUBBLE_MENU_KEYS, ATE_CELL_BUBBLE_MENU_KEYS, ATE_DEFAULT_BUBBLE_MENU_CONFIG, ATE_DEFAULT_CELL_MENU_CONFIG, ATE_DEFAULT_CONFIG, ATE_DEFAULT_ICONS, ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ATE_DEFAULT_IMAGE_UPLOAD_CONFIG, ATE_DEFAULT_SLASH_COMMANDS_CONFIG, ATE_DEFAULT_TABLE_MENU_CONFIG, ATE_DEFAULT_TOC_CONFIG, ATE_DEFAULT_TOOLBAR_CONFIG, ATE_GLOBAL_CONFIG, ATE_ICONS, ATE_IMAGE_BUBBLE_MENU_KEYS, ATE_INITIAL_EDITOR_STATE, ATE_MATERIAL_SYMBOLS_VIEWBOX, ATE_SLASH_COMMAND_KEYS, ATE_STROKE_ICONS, ATE_TABLE_BUBBLE_MENU_KEYS, ATE_TOOLBAR_KEYS, AngularTiptapEditorComponent, AteAngularNodeView, AteBlockShortcuts, AteColorPickerService, AteDiscoveryCalculator, AteEditorCommandsService, AteEditorRef, AteEditorRegistry, AteExportService, AteI18nService, AteIconComponent, AteIconRegistry, AteImageCalculator, AteImageService, AteImageValidationError, AteLinkService, AteLinkShortcut, AteMarksCalculator, AteNodeViewRenderer, AteNoopValueAccessorDirective, AtePastedImage, AteSelectionCalculator, AteStructureCalculator, AteTableCalculator, AteTableOfContentsComponent, AteTocNodeComponent, AteTocNodeOptions, AteTooltipDirective, classifyPastedImageSrc, createAngularComponentExtension, createDefaultSlashCommands, dataUriToFile, filterSlashCommands, getAteTocNodeExtension, isLinkShortcut, provideAteEditor, provideAteIcons, registerAngularComponent, sanitizePastedImages };
10145
10912
  //# sourceMappingURL=flogeez-angular-tiptap-editor.mjs.map