@flogeez/angular-tiptap-editor 0.5.4 → 0.6.0
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/CHANGELOG.md +39 -0
- package/LICENSE +1 -1
- package/README.md +115 -96
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +3758 -3119
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/index.d.ts +319 -81
- package/package.json +1 -1
- package/src/lib/styles/bubble-menu.global.css +7 -0
package/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as _flogeez_angular_tiptap_editor from '@flogeez/angular-tiptap-editor';
|
|
2
2
|
import * as _angular_core from '@angular/core';
|
|
3
3
|
import { AfterViewInit, OnDestroy, ElementRef } from '@angular/core';
|
|
4
|
+
import { Editor, Node, Mark, Extension, EditorOptions } from '@tiptap/core';
|
|
4
5
|
import { Observable } from 'rxjs';
|
|
5
6
|
import { ControlValueAccessor } from '@angular/forms';
|
|
6
7
|
|
|
@@ -390,11 +391,6 @@ declare class TiptapI18nService {
|
|
|
390
391
|
static ɵprov: _angular_core.ɵɵInjectableDeclaration<TiptapI18nService>;
|
|
391
392
|
}
|
|
392
393
|
|
|
393
|
-
interface CellBubbleMenuConfig$1 {
|
|
394
|
-
mergeCells?: boolean;
|
|
395
|
-
splitCell?: boolean;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
394
|
interface SlashCommandItem {
|
|
399
395
|
title: string;
|
|
400
396
|
description: string;
|
|
@@ -486,107 +482,222 @@ interface ImageUploadHandlerResult {
|
|
|
486
482
|
*/
|
|
487
483
|
type ImageUploadHandler = (context: ImageUploadContext) => Promise<ImageUploadHandlerResult> | Observable<ImageUploadHandlerResult>;
|
|
488
484
|
declare class ImageService {
|
|
485
|
+
/** Signals for image state */
|
|
489
486
|
selectedImage: _angular_core.WritableSignal<ImageData | null>;
|
|
490
487
|
isImageSelected: _angular_core.Signal<boolean>;
|
|
488
|
+
/** Resizing state */
|
|
491
489
|
isResizing: _angular_core.WritableSignal<boolean>;
|
|
492
490
|
private i18n;
|
|
493
491
|
private readonly t;
|
|
492
|
+
/** Upload state signals */
|
|
494
493
|
isUploading: _angular_core.WritableSignal<boolean>;
|
|
495
494
|
uploadProgress: _angular_core.WritableSignal<number>;
|
|
496
495
|
uploadMessage: _angular_core.WritableSignal<string>;
|
|
497
496
|
/**
|
|
498
|
-
* Custom upload handler
|
|
499
|
-
*
|
|
500
|
-
* This allows users to implement their own image storage logic.
|
|
501
|
-
*
|
|
502
|
-
* @example
|
|
503
|
-
* ```typescript
|
|
504
|
-
* imageService.uploadHandler = async (context) => {
|
|
505
|
-
* const formData = new FormData();
|
|
506
|
-
* formData.append('image', context.file);
|
|
507
|
-
* const response = await fetch('/api/upload', { method: 'POST', body: formData });
|
|
508
|
-
* const data = await response.json();
|
|
509
|
-
* return { src: data.url };
|
|
510
|
-
* };
|
|
511
|
-
* ```
|
|
497
|
+
* Custom upload handler.
|
|
498
|
+
* If set, this handler replaces the default base64 conversion.
|
|
512
499
|
*/
|
|
513
500
|
uploadHandler: ImageUploadHandler | null;
|
|
514
501
|
private currentEditor;
|
|
502
|
+
/** Select and track an image from the editor */
|
|
515
503
|
selectImage(editor: Editor): void;
|
|
516
504
|
clearSelection(): void;
|
|
505
|
+
/** Insert a new image and ensure it's selected */
|
|
517
506
|
insertImage(editor: Editor, imageData: ImageData): void;
|
|
507
|
+
/** Update attributes of the currently active image */
|
|
518
508
|
updateImageAttributes(editor: Editor, attributes: Partial<ImageData>): void;
|
|
509
|
+
/** Resize image with optional aspect ratio maintenance */
|
|
519
510
|
resizeImage(editor: Editor, options: ResizeOptions): void;
|
|
520
|
-
|
|
511
|
+
/** Predetermined resize helpers used by UI */
|
|
521
512
|
resizeImageToSmall(editor: Editor): void;
|
|
522
513
|
resizeImageToMedium(editor: Editor): void;
|
|
523
514
|
resizeImageToLarge(editor: Editor): void;
|
|
524
515
|
resizeImageToOriginal(editor: Editor): void;
|
|
525
|
-
|
|
516
|
+
/** Get current image dimensions */
|
|
526
517
|
getImageDimensions(editor: Editor): {
|
|
527
518
|
width: number;
|
|
528
519
|
height: number;
|
|
529
520
|
} | null;
|
|
530
|
-
|
|
531
|
-
width: number;
|
|
532
|
-
height: number;
|
|
533
|
-
}>;
|
|
521
|
+
/** Remove the selected image */
|
|
534
522
|
deleteImage(editor: Editor): void;
|
|
535
523
|
private updateSelectedImage;
|
|
524
|
+
/** Validate file type and size */
|
|
536
525
|
validateImage(file: File, maxSize?: number): {
|
|
537
526
|
valid: boolean;
|
|
538
527
|
error?: string;
|
|
539
528
|
};
|
|
529
|
+
/** Compress and process image on client side */
|
|
540
530
|
compressImage(file: File, quality?: number, maxWidth?: number, maxHeight?: number): Promise<ImageUploadResult>;
|
|
531
|
+
/** Core upload logic with progress tracking */
|
|
541
532
|
private uploadImageWithProgress;
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
}): Promise<void>;
|
|
533
|
+
private resetUploadState;
|
|
534
|
+
/** Main entry point for file upload and insertion */
|
|
535
|
+
uploadAndInsertImage(editor: Editor, file: File, options?: Record<string, any>): Promise<void>;
|
|
536
|
+
/** Trigger an editor transaction to force decoration update */
|
|
547
537
|
private forceEditorUpdate;
|
|
538
|
+
/** Generic helper to open file picker and process selection */
|
|
548
539
|
private selectFileAndProcess;
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
selectAndReplaceImage(editor: Editor, options?: {
|
|
556
|
-
quality?: number;
|
|
557
|
-
maxWidth?: number;
|
|
558
|
-
maxHeight?: number;
|
|
559
|
-
accept?: string;
|
|
560
|
-
}): Promise<void>;
|
|
561
|
-
uploadAndReplaceImage(editor: Editor, file: File, options?: {
|
|
562
|
-
quality?: number;
|
|
563
|
-
maxWidth?: number;
|
|
564
|
-
maxHeight?: number;
|
|
565
|
-
}): Promise<void>;
|
|
540
|
+
/** Select file and upload as new image */
|
|
541
|
+
selectAndUploadImage(editor: Editor, options?: Record<string, any>): Promise<void>;
|
|
542
|
+
/** Select file and replace currently selected image */
|
|
543
|
+
selectAndReplaceImage(editor: Editor, options?: Record<string, any>): Promise<void>;
|
|
544
|
+
/** Internal helper used by replacement logic */
|
|
545
|
+
uploadAndReplaceImage(editor: Editor, file: File, options?: Record<string, any>): Promise<void>;
|
|
566
546
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ImageService, never>;
|
|
567
547
|
static ɵprov: _angular_core.ɵɵInjectableDeclaration<ImageService>;
|
|
568
548
|
}
|
|
569
549
|
|
|
550
|
+
type StateCalculator = (editor: Editor) => Partial<{
|
|
551
|
+
[K in keyof EditorStateSnapshot]: EditorStateSnapshot[K] extends object ? Partial<EditorStateSnapshot[K]> : EditorStateSnapshot[K];
|
|
552
|
+
}>;
|
|
553
|
+
interface EditorStateSnapshot {
|
|
554
|
+
/** Global editor states */
|
|
555
|
+
isFocused: boolean;
|
|
556
|
+
isEditable: boolean;
|
|
557
|
+
/**
|
|
558
|
+
* Detailed selection information to avoid overlap between menus
|
|
559
|
+
*/
|
|
560
|
+
selection: {
|
|
561
|
+
type: 'text' | 'node' | 'cell' | 'none';
|
|
562
|
+
from: number;
|
|
563
|
+
to: number;
|
|
564
|
+
empty: boolean;
|
|
565
|
+
/** Specific for CellSelection */
|
|
566
|
+
isSingleCell: boolean;
|
|
567
|
+
};
|
|
568
|
+
/** Text formatting states (Marks) */
|
|
569
|
+
marks: {
|
|
570
|
+
bold: boolean;
|
|
571
|
+
italic: boolean;
|
|
572
|
+
underline: boolean;
|
|
573
|
+
strike: boolean;
|
|
574
|
+
code: boolean;
|
|
575
|
+
superscript: boolean;
|
|
576
|
+
subscript: boolean;
|
|
577
|
+
highlight: boolean;
|
|
578
|
+
link: boolean;
|
|
579
|
+
linkHref: string | null;
|
|
580
|
+
color: string | null;
|
|
581
|
+
computedColor: string | null;
|
|
582
|
+
background: string | null;
|
|
583
|
+
computedBackground: string | null;
|
|
584
|
+
};
|
|
585
|
+
/** Capability states (canExecute) */
|
|
586
|
+
can: {
|
|
587
|
+
toggleBold: boolean;
|
|
588
|
+
toggleItalic: boolean;
|
|
589
|
+
toggleUnderline: boolean;
|
|
590
|
+
toggleStrike: boolean;
|
|
591
|
+
toggleCode: boolean;
|
|
592
|
+
toggleHighlight: boolean;
|
|
593
|
+
toggleLink: boolean;
|
|
594
|
+
toggleSuperscript: boolean;
|
|
595
|
+
toggleSubscript: boolean;
|
|
596
|
+
setColor: boolean;
|
|
597
|
+
setHighlight: boolean;
|
|
598
|
+
undo: boolean;
|
|
599
|
+
redo: boolean;
|
|
600
|
+
/** Table specific capabilities */
|
|
601
|
+
addRowBefore: boolean;
|
|
602
|
+
addRowAfter: boolean;
|
|
603
|
+
deleteRow: boolean;
|
|
604
|
+
addColumnBefore: boolean;
|
|
605
|
+
addColumnAfter: boolean;
|
|
606
|
+
deleteColumn: boolean;
|
|
607
|
+
deleteTable: boolean;
|
|
608
|
+
mergeCells: boolean;
|
|
609
|
+
splitCell: boolean;
|
|
610
|
+
toggleHeaderRow: boolean;
|
|
611
|
+
toggleHeaderColumn: boolean;
|
|
612
|
+
/** Structure/Node capabilities */
|
|
613
|
+
toggleHeading1: boolean;
|
|
614
|
+
toggleHeading2: boolean;
|
|
615
|
+
toggleHeading3: boolean;
|
|
616
|
+
toggleBulletList: boolean;
|
|
617
|
+
toggleOrderedList: boolean;
|
|
618
|
+
toggleBlockquote: boolean;
|
|
619
|
+
setTextAlignLeft: boolean;
|
|
620
|
+
setTextAlignCenter: boolean;
|
|
621
|
+
setTextAlignRight: boolean;
|
|
622
|
+
setTextAlignJustify: boolean;
|
|
623
|
+
insertHorizontalRule: boolean;
|
|
624
|
+
insertTable: boolean;
|
|
625
|
+
insertImage: boolean;
|
|
626
|
+
};
|
|
627
|
+
/** Current node context */
|
|
628
|
+
nodes: {
|
|
629
|
+
isTable: boolean;
|
|
630
|
+
isTableNodeSelected: boolean;
|
|
631
|
+
isTableCell: boolean;
|
|
632
|
+
isImage: boolean;
|
|
633
|
+
isBlockquote: boolean;
|
|
634
|
+
isCodeBlock: boolean;
|
|
635
|
+
isBulletList: boolean;
|
|
636
|
+
isOrderedList: boolean;
|
|
637
|
+
/** Headings */
|
|
638
|
+
h1: boolean;
|
|
639
|
+
h2: boolean;
|
|
640
|
+
h3: boolean;
|
|
641
|
+
/** Alignment */
|
|
642
|
+
alignLeft: boolean;
|
|
643
|
+
alignCenter: boolean;
|
|
644
|
+
alignRight: boolean;
|
|
645
|
+
alignJustify: boolean;
|
|
646
|
+
/** Table specific */
|
|
647
|
+
isTableHeaderRow: boolean;
|
|
648
|
+
isTableHeaderColumn: boolean;
|
|
649
|
+
/** Name of the active node at selection head */
|
|
650
|
+
activeNodeName: string | null;
|
|
651
|
+
};
|
|
652
|
+
/** Placeholder for custom extension states */
|
|
653
|
+
custom: Record<string, any>;
|
|
654
|
+
}
|
|
655
|
+
declare const INITIAL_EDITOR_STATE: EditorStateSnapshot;
|
|
656
|
+
|
|
570
657
|
declare class EditorCommandsService {
|
|
571
|
-
|
|
572
|
-
|
|
658
|
+
private imageService;
|
|
659
|
+
private colorPickerSvc;
|
|
660
|
+
private linkSvc;
|
|
661
|
+
private readonly _editorState;
|
|
662
|
+
/** Exposed editor state as a readonly signal */
|
|
663
|
+
readonly editorState: _angular_core.Signal<EditorStateSnapshot>;
|
|
664
|
+
/** Signal to track when the toolbar is being hovered/interacted with */
|
|
665
|
+
private readonly _isToolbarInteracting;
|
|
666
|
+
readonly isToolbarInteracting: _angular_core.Signal<boolean>;
|
|
667
|
+
/** Set toolbar interaction state (called by editor component) */
|
|
668
|
+
setToolbarInteracting(value: boolean): void;
|
|
669
|
+
readonly isUploading: _angular_core.Signal<boolean>;
|
|
670
|
+
readonly uploadProgress: _angular_core.Signal<number>;
|
|
671
|
+
readonly uploadMessage: _angular_core.Signal<string>;
|
|
672
|
+
set uploadHandler(handler: ImageUploadHandler | null);
|
|
673
|
+
/** Update state (called by TiptapStateExtension) */
|
|
674
|
+
updateState(state: EditorStateSnapshot): void;
|
|
675
|
+
/** Signal to toggle link edit mode from UI (Toolbar) - Immediate response */
|
|
676
|
+
readonly linkEditMode: _angular_core.Signal<boolean>;
|
|
677
|
+
/** Reference to the element that triggered the link menu (for anchoring) */
|
|
678
|
+
readonly linkMenuTrigger: _angular_core.Signal<HTMLElement | null>;
|
|
679
|
+
/** Signal to toggle color picker mode from UI (text or highlight) */
|
|
680
|
+
readonly colorEditMode: _angular_core.Signal<_flogeez_angular_tiptap_editor.ColorEditMode | null>;
|
|
681
|
+
/** Reference to the element that triggered the color menu (for anchoring) */
|
|
682
|
+
readonly colorMenuTrigger: _angular_core.Signal<HTMLElement | null>;
|
|
683
|
+
/** Generic method to execute any command by name */
|
|
684
|
+
execute(editor: Editor, command: string, ...args: any[]): void;
|
|
573
685
|
toggleBold(editor: Editor): void;
|
|
574
686
|
toggleItalic(editor: Editor): void;
|
|
575
687
|
toggleStrike(editor: Editor): void;
|
|
576
688
|
toggleCode(editor: Editor): void;
|
|
689
|
+
toggleUnderline(editor: Editor): void;
|
|
690
|
+
toggleSuperscript(editor: Editor): void;
|
|
691
|
+
toggleSubscript(editor: Editor): void;
|
|
577
692
|
toggleHeading(editor: Editor, level: 1 | 2 | 3): void;
|
|
693
|
+
toggleHighlight(editor: Editor, color?: string): void;
|
|
578
694
|
toggleBulletList(editor: Editor): void;
|
|
579
695
|
toggleOrderedList(editor: Editor): void;
|
|
580
696
|
toggleBlockquote(editor: Editor): void;
|
|
581
|
-
undo(editor: Editor): void;
|
|
582
|
-
redo(editor: Editor): void;
|
|
583
|
-
toggleUnderline(editor: Editor): void;
|
|
584
|
-
toggleSuperscript(editor: Editor): void;
|
|
585
|
-
toggleSubscript(editor: Editor): void;
|
|
586
697
|
setTextAlign(editor: Editor, alignment: "left" | "center" | "right" | "justify"): void;
|
|
587
|
-
toggleLink(editor: Editor, url?: string): void;
|
|
588
698
|
insertHorizontalRule(editor: Editor): void;
|
|
589
|
-
|
|
699
|
+
undo(editor: Editor): void;
|
|
700
|
+
redo(editor: Editor): void;
|
|
590
701
|
insertTable(editor: Editor, rows?: number, cols?: number): void;
|
|
591
702
|
addColumnBefore(editor: Editor): void;
|
|
592
703
|
addColumnAfter(editor: Editor): void;
|
|
@@ -599,13 +710,23 @@ declare class EditorCommandsService {
|
|
|
599
710
|
splitCell(editor: Editor): void;
|
|
600
711
|
toggleHeaderColumn(editor: Editor): void;
|
|
601
712
|
toggleHeaderRow(editor: Editor): void;
|
|
602
|
-
toggleHeaderCell(editor: Editor): void;
|
|
603
713
|
clearContent(editor: Editor): void;
|
|
604
714
|
focus(editor: Editor): void;
|
|
605
715
|
blur(editor: Editor): void;
|
|
606
716
|
setContent(editor: Editor, content: string, emitUpdate?: boolean): void;
|
|
607
717
|
setEditable(editor: Editor, editable: boolean): void;
|
|
608
718
|
insertContent(editor: Editor, content: string): void;
|
|
719
|
+
insertImage(editor: Editor, options?: {
|
|
720
|
+
quality?: number;
|
|
721
|
+
maxWidth?: number;
|
|
722
|
+
maxHeight?: number;
|
|
723
|
+
accept?: string;
|
|
724
|
+
}): Promise<void>;
|
|
725
|
+
uploadImage(editor: Editor, file: File, options?: {
|
|
726
|
+
quality?: number;
|
|
727
|
+
maxWidth?: number;
|
|
728
|
+
maxHeight?: number;
|
|
729
|
+
}): Promise<void>;
|
|
609
730
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EditorCommandsService, never>;
|
|
610
731
|
static ɵprov: _angular_core.ɵɵInjectableDeclaration<EditorCommandsService>;
|
|
611
732
|
}
|
|
@@ -633,7 +754,7 @@ declare const DEFAULT_SLASH_COMMANDS_CONFIG: Record<SlashCommandKey, boolean>;
|
|
|
633
754
|
* Factory pour créer les commandes natives avec leurs traductions et leur logique d'exécution.
|
|
634
755
|
* Utilise les services de l'éditeur pour garantir une cohérence de comportement.
|
|
635
756
|
*/
|
|
636
|
-
declare function createDefaultSlashCommands(i18n: TiptapI18nService, commands: EditorCommandsService,
|
|
757
|
+
declare function createDefaultSlashCommands(i18n: TiptapI18nService, commands: EditorCommandsService, imageOptions?: {
|
|
637
758
|
quality?: number;
|
|
638
759
|
maxWidth?: number;
|
|
639
760
|
maxHeight?: number;
|
|
@@ -642,7 +763,7 @@ declare function createDefaultSlashCommands(i18n: TiptapI18nService, commands: E
|
|
|
642
763
|
/**
|
|
643
764
|
* Filtre et assemble les commandes selon la configuration fournie.
|
|
644
765
|
*/
|
|
645
|
-
declare function filterSlashCommands(config: SlashCommandsConfig, i18n: TiptapI18nService, commands: EditorCommandsService,
|
|
766
|
+
declare function filterSlashCommands(config: SlashCommandsConfig, i18n: TiptapI18nService, commands: EditorCommandsService, imageOptions?: {
|
|
646
767
|
quality?: number;
|
|
647
768
|
maxWidth?: number;
|
|
648
769
|
maxHeight?: number;
|
|
@@ -728,11 +849,6 @@ declare class NoopValueAccessorDirective implements ControlValueAccessor {
|
|
|
728
849
|
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NoopValueAccessorDirective, never, never, {}, {}, never, never, true, never>;
|
|
729
850
|
}
|
|
730
851
|
|
|
731
|
-
declare const DEFAULT_TOOLBAR_CONFIG: ToolbarConfig;
|
|
732
|
-
declare const DEFAULT_BUBBLE_MENU_CONFIG: BubbleMenuConfig;
|
|
733
|
-
declare const DEFAULT_IMAGE_BUBBLE_MENU_CONFIG: ImageBubbleMenuConfig;
|
|
734
|
-
declare const DEFAULT_TABLE_MENU_CONFIG: TableBubbleMenuConfig;
|
|
735
|
-
declare const DEFAULT_CELL_MENU_CONFIG: CellBubbleMenuConfig$1;
|
|
736
852
|
declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
|
|
737
853
|
content: _angular_core.InputSignal<string>;
|
|
738
854
|
placeholder: _angular_core.InputSignal<string>;
|
|
@@ -750,14 +866,18 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
|
|
|
750
866
|
slashCommands: _angular_core.InputSignal<SlashCommandsConfig>;
|
|
751
867
|
customSlashCommands: _angular_core.InputSignal<CustomSlashCommands | undefined>;
|
|
752
868
|
locale: _angular_core.InputSignal<SupportedLocale | undefined>;
|
|
753
|
-
autofocus: _angular_core.InputSignal<number | boolean | "
|
|
754
|
-
tiptapExtensions: _angular_core.InputSignal<(Node<any, any> |
|
|
869
|
+
autofocus: _angular_core.InputSignal<number | boolean | "start" | "end" | "all">;
|
|
870
|
+
tiptapExtensions: _angular_core.InputSignal<(Node<any, any> | Mark<any, any> | Extension<any, any>)[]>;
|
|
755
871
|
tiptapOptions: _angular_core.InputSignal<Partial<EditorOptions>>;
|
|
756
872
|
showBubbleMenu: _angular_core.InputSignal<boolean>;
|
|
757
873
|
bubbleMenu: _angular_core.InputSignal<Partial<BubbleMenuConfig>>;
|
|
758
874
|
showImageBubbleMenu: _angular_core.InputSignal<boolean>;
|
|
759
875
|
imageBubbleMenu: _angular_core.InputSignal<Partial<ImageBubbleMenuConfig>>;
|
|
760
876
|
toolbar: _angular_core.InputSignal<Partial<ToolbarConfig>>;
|
|
877
|
+
/**
|
|
878
|
+
* Additionnal state calculators to extend the reactive editor state.
|
|
879
|
+
*/
|
|
880
|
+
stateCalculators: _angular_core.InputSignal<StateCalculator[]>;
|
|
761
881
|
imageUpload: _angular_core.InputSignal<Partial<any>>;
|
|
762
882
|
/**
|
|
763
883
|
* Custom handler for image uploads.
|
|
@@ -794,10 +914,6 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
|
|
|
794
914
|
event: FocusEvent;
|
|
795
915
|
}>;
|
|
796
916
|
editorElement: _angular_core.Signal<ElementRef<any>>;
|
|
797
|
-
private textMenuComp;
|
|
798
|
-
private imageMenuComp;
|
|
799
|
-
private tableMenuComp;
|
|
800
|
-
private cellMenuComp;
|
|
801
917
|
hideBubbleMenus(): void;
|
|
802
918
|
showBubbleMenus(): void;
|
|
803
919
|
private _editor;
|
|
@@ -805,6 +921,7 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
|
|
|
805
921
|
private _wordCount;
|
|
806
922
|
private _isDragOver;
|
|
807
923
|
private _editorFullyInitialized;
|
|
924
|
+
private lastEmittedHtml;
|
|
808
925
|
readonly editor: _angular_core.Signal<Editor | null>;
|
|
809
926
|
readonly characterCount: _angular_core.Signal<number>;
|
|
810
927
|
readonly wordCount: _angular_core.Signal<number>;
|
|
@@ -844,14 +961,13 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
|
|
|
844
961
|
private _destroyRef;
|
|
845
962
|
private ngControl;
|
|
846
963
|
readonly i18nService: TiptapI18nService;
|
|
847
|
-
readonly imageService: ImageService;
|
|
848
964
|
readonly editorCommandsService: EditorCommandsService;
|
|
965
|
+
readonly editorState: _angular_core.Signal<_flogeez_angular_tiptap_editor.EditorStateSnapshot>;
|
|
849
966
|
constructor();
|
|
850
967
|
ngAfterViewInit(): void;
|
|
851
968
|
ngOnDestroy(): void;
|
|
852
969
|
private initEditor;
|
|
853
970
|
private updateCharacterCount;
|
|
854
|
-
onSlashCommandImageUpload(file: File): Promise<void>;
|
|
855
971
|
onDragOver(event: DragEvent): void;
|
|
856
972
|
onDrop(event: DragEvent): void;
|
|
857
973
|
private insertImageFromFile;
|
|
@@ -867,14 +983,136 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
|
|
|
867
983
|
setDisabledState(isDisabled: boolean): void;
|
|
868
984
|
onEditorClick(event: MouseEvent): void;
|
|
869
985
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AngularTiptapEditorComponent, never>;
|
|
870
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<AngularTiptapEditorComponent, "angular-tiptap-editor", never, { "content": { "alias": "content"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "editable": { "alias": "editable"; "required": false; "isSignal": true; }; "minHeight": { "alias": "minHeight"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "maxHeight": { "alias": "maxHeight"; "required": false; "isSignal": true; }; "fillContainer": { "alias": "fillContainer"; "required": false; "isSignal": true; }; "showToolbar": { "alias": "showToolbar"; "required": false; "isSignal": true; }; "showCharacterCount": { "alias": "showCharacterCount"; "required": false; "isSignal": true; }; "showWordCount": { "alias": "showWordCount"; "required": false; "isSignal": true; }; "maxCharacters": { "alias": "maxCharacters"; "required": false; "isSignal": true; }; "enableOfficePaste": { "alias": "enableOfficePaste"; "required": false; "isSignal": true; }; "enableSlashCommands": { "alias": "enableSlashCommands"; "required": false; "isSignal": true; }; "slashCommands": { "alias": "slashCommands"; "required": false; "isSignal": true; }; "customSlashCommands": { "alias": "customSlashCommands"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "autofocus": { "alias": "autofocus"; "required": false; "isSignal": true; }; "tiptapExtensions": { "alias": "tiptapExtensions"; "required": false; "isSignal": true; }; "tiptapOptions": { "alias": "tiptapOptions"; "required": false; "isSignal": true; }; "showBubbleMenu": { "alias": "showBubbleMenu"; "required": false; "isSignal": true; }; "bubbleMenu": { "alias": "bubbleMenu"; "required": false; "isSignal": true; }; "showImageBubbleMenu": { "alias": "showImageBubbleMenu"; "required": false; "isSignal": true; }; "imageBubbleMenu": { "alias": "imageBubbleMenu"; "required": false; "isSignal": true; }; "toolbar": { "alias": "toolbar"; "required": false; "isSignal": true; }; "imageUpload": { "alias": "imageUpload"; "required": false; "isSignal": true; }; "imageUploadHandler": { "alias": "imageUploadHandler"; "required": false; "isSignal": true; }; }, { "contentChange": "contentChange"; "editorCreated": "editorCreated"; "editorUpdate": "editorUpdate"; "editorFocus": "editorFocus"; "editorBlur": "editorBlur"; }, never, never, true, [{ directive: typeof NoopValueAccessorDirective; inputs: {}; outputs: {}; }]>;
|
|
986
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<AngularTiptapEditorComponent, "angular-tiptap-editor", never, { "content": { "alias": "content"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "editable": { "alias": "editable"; "required": false; "isSignal": true; }; "minHeight": { "alias": "minHeight"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "maxHeight": { "alias": "maxHeight"; "required": false; "isSignal": true; }; "fillContainer": { "alias": "fillContainer"; "required": false; "isSignal": true; }; "showToolbar": { "alias": "showToolbar"; "required": false; "isSignal": true; }; "showCharacterCount": { "alias": "showCharacterCount"; "required": false; "isSignal": true; }; "showWordCount": { "alias": "showWordCount"; "required": false; "isSignal": true; }; "maxCharacters": { "alias": "maxCharacters"; "required": false; "isSignal": true; }; "enableOfficePaste": { "alias": "enableOfficePaste"; "required": false; "isSignal": true; }; "enableSlashCommands": { "alias": "enableSlashCommands"; "required": false; "isSignal": true; }; "slashCommands": { "alias": "slashCommands"; "required": false; "isSignal": true; }; "customSlashCommands": { "alias": "customSlashCommands"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "autofocus": { "alias": "autofocus"; "required": false; "isSignal": true; }; "tiptapExtensions": { "alias": "tiptapExtensions"; "required": false; "isSignal": true; }; "tiptapOptions": { "alias": "tiptapOptions"; "required": false; "isSignal": true; }; "showBubbleMenu": { "alias": "showBubbleMenu"; "required": false; "isSignal": true; }; "bubbleMenu": { "alias": "bubbleMenu"; "required": false; "isSignal": true; }; "showImageBubbleMenu": { "alias": "showImageBubbleMenu"; "required": false; "isSignal": true; }; "imageBubbleMenu": { "alias": "imageBubbleMenu"; "required": false; "isSignal": true; }; "toolbar": { "alias": "toolbar"; "required": false; "isSignal": true; }; "stateCalculators": { "alias": "stateCalculators"; "required": false; "isSignal": true; }; "imageUpload": { "alias": "imageUpload"; "required": false; "isSignal": true; }; "imageUploadHandler": { "alias": "imageUploadHandler"; "required": false; "isSignal": true; }; }, { "contentChange": "contentChange"; "editorCreated": "editorCreated"; "editorUpdate": "editorUpdate"; "editorFocus": "editorFocus"; "editorBlur": "editorBlur"; }, never, never, true, [{ directive: typeof NoopValueAccessorDirective; inputs: {}; outputs: {}; }]>;
|
|
871
987
|
}
|
|
872
988
|
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
989
|
+
interface ColorPickerSelection {
|
|
990
|
+
from: number;
|
|
991
|
+
to: number;
|
|
992
|
+
}
|
|
993
|
+
type ColorEditMode = 'text' | 'highlight';
|
|
994
|
+
declare class ColorPickerService {
|
|
995
|
+
private storedSelection;
|
|
996
|
+
/** Current edit mode: null when closed, 'text' or 'highlight' when open */
|
|
997
|
+
readonly editMode: _angular_core.WritableSignal<ColorEditMode | null>;
|
|
998
|
+
/** Reference to the element that triggered the menu (for anchoring) */
|
|
999
|
+
readonly menuTrigger: _angular_core.WritableSignal<HTMLElement | null>;
|
|
1000
|
+
/** Whether the user is currently interacting with the picker UI (e.g. typing) */
|
|
1001
|
+
readonly isInteracting: _angular_core.WritableSignal<boolean>;
|
|
1002
|
+
/**
|
|
1003
|
+
* Open the color picker menu in the specified mode.
|
|
1004
|
+
*/
|
|
1005
|
+
open(mode: ColorEditMode, trigger?: HTMLElement): void;
|
|
1006
|
+
/**
|
|
1007
|
+
* Close the color picker menu.
|
|
1008
|
+
*/
|
|
1009
|
+
close(): void;
|
|
1010
|
+
/**
|
|
1011
|
+
* Set interaction state (prevents premature closing when blurring editor)
|
|
1012
|
+
*/
|
|
1013
|
+
setInteracting(value: boolean): void;
|
|
1014
|
+
/**
|
|
1015
|
+
* Toggle color picker from UI (extracts trigger from event).
|
|
1016
|
+
*/
|
|
1017
|
+
toggle(editor: Editor, mode: ColorEditMode, event?: Event): void;
|
|
1018
|
+
/**
|
|
1019
|
+
* Capture current editor selection.
|
|
1020
|
+
*/
|
|
1021
|
+
captureSelection(editor: Editor): void;
|
|
1022
|
+
/**
|
|
1023
|
+
* Get last captured selection.
|
|
1024
|
+
*/
|
|
1025
|
+
getStoredSelection(): ColorPickerSelection | null;
|
|
1026
|
+
/**
|
|
1027
|
+
* Clear captured selection.
|
|
1028
|
+
*/
|
|
1029
|
+
done(): void;
|
|
1030
|
+
/**
|
|
1031
|
+
* Apply text color to selection.
|
|
1032
|
+
*/
|
|
1033
|
+
applyColor(editor: Editor, color: string, addToHistory?: boolean, focus?: boolean): void;
|
|
1034
|
+
/**
|
|
1035
|
+
* Remove text color from selection.
|
|
1036
|
+
*/
|
|
1037
|
+
unsetColor(editor: Editor, focus?: boolean): void;
|
|
1038
|
+
/**
|
|
1039
|
+
* Apply highlight color to selection.
|
|
1040
|
+
*/
|
|
1041
|
+
applyHighlight(editor: Editor, color: string, addToHistory?: boolean, focus?: boolean): void;
|
|
1042
|
+
/**
|
|
1043
|
+
* Remove highlight from selection.
|
|
1044
|
+
*/
|
|
1045
|
+
unsetHighlight(editor: Editor, focus?: boolean): void;
|
|
1046
|
+
normalizeColor(color: string | null | undefined): string;
|
|
1047
|
+
getLuminance(color: string): number;
|
|
1048
|
+
getContrastColor(color: string): "black" | "white";
|
|
1049
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ColorPickerService, never>;
|
|
1050
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<ColorPickerService>;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
declare class LinkService {
|
|
1054
|
+
/** Whether link edit mode is active */
|
|
1055
|
+
readonly editMode: _angular_core.WritableSignal<boolean>;
|
|
1056
|
+
/** Reference to the element that triggered the menu (for anchoring) */
|
|
1057
|
+
readonly menuTrigger: _angular_core.WritableSignal<HTMLElement | null>;
|
|
1058
|
+
/** Whether the user is currently interacting with the link UI (input focus) */
|
|
1059
|
+
readonly isInteracting: _angular_core.WritableSignal<boolean>;
|
|
1060
|
+
/**
|
|
1061
|
+
* Open the link edit menu.
|
|
1062
|
+
*/
|
|
1063
|
+
open(trigger?: HTMLElement): void;
|
|
1064
|
+
/**
|
|
1065
|
+
* Close the link edit menu.
|
|
1066
|
+
*/
|
|
1067
|
+
close(): void;
|
|
1068
|
+
/**
|
|
1069
|
+
* Final cleanup (called after UI is hidden)
|
|
1070
|
+
*/
|
|
1071
|
+
done(): void;
|
|
1072
|
+
/**
|
|
1073
|
+
* Set interaction state
|
|
1074
|
+
*/
|
|
1075
|
+
setInteracting(value: boolean): void;
|
|
1076
|
+
/**
|
|
1077
|
+
* Toggle link mode from UI.
|
|
1078
|
+
* If a URL string is provided, applies the link and closes.
|
|
1079
|
+
* If an Event is provided, extracts the trigger for anchoring.
|
|
1080
|
+
*/
|
|
1081
|
+
toggle(editor: Editor, urlOrEvent?: string | Event): void;
|
|
1082
|
+
/**
|
|
1083
|
+
* Apply a link to the current selection.
|
|
1084
|
+
*/
|
|
1085
|
+
setLink(editor: Editor, url: string): void;
|
|
1086
|
+
/**
|
|
1087
|
+
* Remove link from the current selection.
|
|
1088
|
+
*/
|
|
1089
|
+
unsetLink(editor: Editor): void;
|
|
1090
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<LinkService, never>;
|
|
1091
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<LinkService>;
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
/**
|
|
1095
|
+
* DiscoveryCalculator automatically detects and tracks the state of any TipTap extension.
|
|
1096
|
+
* It provides a "fallback" reactive state for any mark or node not explicitly handled
|
|
1097
|
+
* by specialized calculators.
|
|
1098
|
+
*/
|
|
1099
|
+
declare const DiscoveryCalculator: StateCalculator;
|
|
1100
|
+
|
|
1101
|
+
declare const ImageCalculator: StateCalculator;
|
|
1102
|
+
|
|
1103
|
+
declare const MarksCalculator: StateCalculator;
|
|
1104
|
+
|
|
1105
|
+
declare const SelectionCalculator: StateCalculator;
|
|
1106
|
+
|
|
1107
|
+
declare const StructureCalculator: StateCalculator;
|
|
1108
|
+
|
|
1109
|
+
declare const TableCalculator: StateCalculator;
|
|
1110
|
+
|
|
1111
|
+
declare const DEFAULT_TOOLBAR_CONFIG: ToolbarConfig;
|
|
1112
|
+
declare const DEFAULT_BUBBLE_MENU_CONFIG: BubbleMenuConfig;
|
|
1113
|
+
declare const DEFAULT_IMAGE_BUBBLE_MENU_CONFIG: ImageBubbleMenuConfig;
|
|
1114
|
+
declare const DEFAULT_TABLE_MENU_CONFIG: TableBubbleMenuConfig;
|
|
1115
|
+
declare const DEFAULT_CELL_MENU_CONFIG: CellBubbleMenuConfig;
|
|
878
1116
|
|
|
879
|
-
export { AngularTiptapEditorComponent, DEFAULT_BUBBLE_MENU_CONFIG, DEFAULT_CELL_MENU_CONFIG, DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, DEFAULT_SLASH_COMMANDS_CONFIG, DEFAULT_TABLE_MENU_CONFIG, DEFAULT_TOOLBAR_CONFIG, EditorCommandsService, ImageService, NoopValueAccessorDirective, SLASH_COMMAND_KEYS, TiptapI18nService, createDefaultSlashCommands, filterSlashCommands };
|
|
880
|
-
export type { BubbleMenuConfig, CellBubbleMenuConfig, CustomSlashCommands,
|
|
1117
|
+
export { AngularTiptapEditorComponent, ColorPickerService, DEFAULT_BUBBLE_MENU_CONFIG, DEFAULT_CELL_MENU_CONFIG, DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, DEFAULT_SLASH_COMMANDS_CONFIG, DEFAULT_TABLE_MENU_CONFIG, DEFAULT_TOOLBAR_CONFIG, DiscoveryCalculator, EditorCommandsService, INITIAL_EDITOR_STATE, ImageCalculator, ImageService, LinkService, MarksCalculator, NoopValueAccessorDirective, SLASH_COMMAND_KEYS, SelectionCalculator, StructureCalculator, TableCalculator, TiptapI18nService, createDefaultSlashCommands, filterSlashCommands };
|
|
1118
|
+
export type { BubbleMenuConfig, CellBubbleMenuConfig, ColorEditMode, ColorPickerSelection, CustomSlashCommands, EditorStateSnapshot, ImageBubbleMenuConfig, ImageData, ImageUploadContext, ImageUploadHandler, ImageUploadHandlerResult, ImageUploadResult, ResizeOptions, SlashCommandItem, SlashCommandKey, SlashCommandsConfig, StateCalculator, SupportedLocale, TableBubbleMenuConfig, TiptapTranslations, ToolbarConfig };
|
package/package.json
CHANGED
|
@@ -26,6 +26,13 @@
|
|
|
26
26
|
white-space: nowrap;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/* Cache le menu intelligemment si la source (le slash) est scrollée hors vue */
|
|
30
|
+
.tippy-box[data-reference-hidden] {
|
|
31
|
+
opacity: 0 !important;
|
|
32
|
+
transition: opacity 0.18s cubic-bezier(0, 0, 0.2, 1);
|
|
33
|
+
pointer-events: none !important;
|
|
34
|
+
}
|
|
35
|
+
|
|
29
36
|
.bubble-menu .tiptap-separator {
|
|
30
37
|
width: 1px;
|
|
31
38
|
height: 28px;
|