@flogeez/angular-tiptap-editor 0.5.3 → 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 +45 -0
- package/LICENSE +1 -1
- package/README.md +115 -96
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +3588 -2741
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/index.d.ts +329 -77
- package/package.json +1 -1
- package/src/lib/styles/bubble-menu.global.css +8 -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
|
|
|
@@ -34,6 +35,8 @@ interface TiptapTranslations {
|
|
|
34
35
|
redo: string;
|
|
35
36
|
clear: string;
|
|
36
37
|
textColor: string;
|
|
38
|
+
customColor: string;
|
|
39
|
+
presets: string;
|
|
37
40
|
};
|
|
38
41
|
bubbleMenu: {
|
|
39
42
|
bold: string;
|
|
@@ -53,6 +56,8 @@ interface TiptapTranslations {
|
|
|
53
56
|
linkUrl: string;
|
|
54
57
|
linkText: string;
|
|
55
58
|
openLink: string;
|
|
59
|
+
customColor: string;
|
|
60
|
+
presets: string;
|
|
56
61
|
};
|
|
57
62
|
slashCommands: {
|
|
58
63
|
heading1: {
|
|
@@ -199,6 +204,8 @@ declare class TiptapI18nService {
|
|
|
199
204
|
redo: string;
|
|
200
205
|
clear: string;
|
|
201
206
|
textColor: string;
|
|
207
|
+
customColor: string;
|
|
208
|
+
presets: string;
|
|
202
209
|
}>;
|
|
203
210
|
readonly bubbleMenu: _angular_core.Signal<{
|
|
204
211
|
bold: string;
|
|
@@ -218,6 +225,8 @@ declare class TiptapI18nService {
|
|
|
218
225
|
linkUrl: string;
|
|
219
226
|
linkText: string;
|
|
220
227
|
openLink: string;
|
|
228
|
+
customColor: string;
|
|
229
|
+
presets: string;
|
|
221
230
|
}>;
|
|
222
231
|
readonly slashCommands: _angular_core.Signal<{
|
|
223
232
|
heading1: {
|
|
@@ -382,11 +391,6 @@ declare class TiptapI18nService {
|
|
|
382
391
|
static ɵprov: _angular_core.ɵɵInjectableDeclaration<TiptapI18nService>;
|
|
383
392
|
}
|
|
384
393
|
|
|
385
|
-
interface CellBubbleMenuConfig$1 {
|
|
386
|
-
mergeCells?: boolean;
|
|
387
|
-
splitCell?: boolean;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
394
|
interface SlashCommandItem {
|
|
391
395
|
title: string;
|
|
392
396
|
description: string;
|
|
@@ -478,107 +482,222 @@ interface ImageUploadHandlerResult {
|
|
|
478
482
|
*/
|
|
479
483
|
type ImageUploadHandler = (context: ImageUploadContext) => Promise<ImageUploadHandlerResult> | Observable<ImageUploadHandlerResult>;
|
|
480
484
|
declare class ImageService {
|
|
485
|
+
/** Signals for image state */
|
|
481
486
|
selectedImage: _angular_core.WritableSignal<ImageData | null>;
|
|
482
487
|
isImageSelected: _angular_core.Signal<boolean>;
|
|
488
|
+
/** Resizing state */
|
|
483
489
|
isResizing: _angular_core.WritableSignal<boolean>;
|
|
484
490
|
private i18n;
|
|
485
491
|
private readonly t;
|
|
492
|
+
/** Upload state signals */
|
|
486
493
|
isUploading: _angular_core.WritableSignal<boolean>;
|
|
487
494
|
uploadProgress: _angular_core.WritableSignal<number>;
|
|
488
495
|
uploadMessage: _angular_core.WritableSignal<string>;
|
|
489
496
|
/**
|
|
490
|
-
* Custom upload handler
|
|
491
|
-
*
|
|
492
|
-
* This allows users to implement their own image storage logic.
|
|
493
|
-
*
|
|
494
|
-
* @example
|
|
495
|
-
* ```typescript
|
|
496
|
-
* imageService.uploadHandler = async (context) => {
|
|
497
|
-
* const formData = new FormData();
|
|
498
|
-
* formData.append('image', context.file);
|
|
499
|
-
* const response = await fetch('/api/upload', { method: 'POST', body: formData });
|
|
500
|
-
* const data = await response.json();
|
|
501
|
-
* return { src: data.url };
|
|
502
|
-
* };
|
|
503
|
-
* ```
|
|
497
|
+
* Custom upload handler.
|
|
498
|
+
* If set, this handler replaces the default base64 conversion.
|
|
504
499
|
*/
|
|
505
500
|
uploadHandler: ImageUploadHandler | null;
|
|
506
501
|
private currentEditor;
|
|
502
|
+
/** Select and track an image from the editor */
|
|
507
503
|
selectImage(editor: Editor): void;
|
|
508
504
|
clearSelection(): void;
|
|
505
|
+
/** Insert a new image and ensure it's selected */
|
|
509
506
|
insertImage(editor: Editor, imageData: ImageData): void;
|
|
507
|
+
/** Update attributes of the currently active image */
|
|
510
508
|
updateImageAttributes(editor: Editor, attributes: Partial<ImageData>): void;
|
|
509
|
+
/** Resize image with optional aspect ratio maintenance */
|
|
511
510
|
resizeImage(editor: Editor, options: ResizeOptions): void;
|
|
512
|
-
|
|
511
|
+
/** Predetermined resize helpers used by UI */
|
|
513
512
|
resizeImageToSmall(editor: Editor): void;
|
|
514
513
|
resizeImageToMedium(editor: Editor): void;
|
|
515
514
|
resizeImageToLarge(editor: Editor): void;
|
|
516
515
|
resizeImageToOriginal(editor: Editor): void;
|
|
517
|
-
|
|
516
|
+
/** Get current image dimensions */
|
|
518
517
|
getImageDimensions(editor: Editor): {
|
|
519
518
|
width: number;
|
|
520
519
|
height: number;
|
|
521
520
|
} | null;
|
|
522
|
-
|
|
523
|
-
width: number;
|
|
524
|
-
height: number;
|
|
525
|
-
}>;
|
|
521
|
+
/** Remove the selected image */
|
|
526
522
|
deleteImage(editor: Editor): void;
|
|
527
523
|
private updateSelectedImage;
|
|
524
|
+
/** Validate file type and size */
|
|
528
525
|
validateImage(file: File, maxSize?: number): {
|
|
529
526
|
valid: boolean;
|
|
530
527
|
error?: string;
|
|
531
528
|
};
|
|
529
|
+
/** Compress and process image on client side */
|
|
532
530
|
compressImage(file: File, quality?: number, maxWidth?: number, maxHeight?: number): Promise<ImageUploadResult>;
|
|
531
|
+
/** Core upload logic with progress tracking */
|
|
533
532
|
private uploadImageWithProgress;
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
}): 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 */
|
|
539
537
|
private forceEditorUpdate;
|
|
538
|
+
/** Generic helper to open file picker and process selection */
|
|
540
539
|
private selectFileAndProcess;
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
selectAndReplaceImage(editor: Editor, options?: {
|
|
548
|
-
quality?: number;
|
|
549
|
-
maxWidth?: number;
|
|
550
|
-
maxHeight?: number;
|
|
551
|
-
accept?: string;
|
|
552
|
-
}): Promise<void>;
|
|
553
|
-
uploadAndReplaceImage(editor: Editor, file: File, options?: {
|
|
554
|
-
quality?: number;
|
|
555
|
-
maxWidth?: number;
|
|
556
|
-
maxHeight?: number;
|
|
557
|
-
}): 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>;
|
|
558
546
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ImageService, never>;
|
|
559
547
|
static ɵprov: _angular_core.ɵɵInjectableDeclaration<ImageService>;
|
|
560
548
|
}
|
|
561
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
|
+
|
|
562
657
|
declare class EditorCommandsService {
|
|
563
|
-
|
|
564
|
-
|
|
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;
|
|
565
685
|
toggleBold(editor: Editor): void;
|
|
566
686
|
toggleItalic(editor: Editor): void;
|
|
567
687
|
toggleStrike(editor: Editor): void;
|
|
568
688
|
toggleCode(editor: Editor): void;
|
|
689
|
+
toggleUnderline(editor: Editor): void;
|
|
690
|
+
toggleSuperscript(editor: Editor): void;
|
|
691
|
+
toggleSubscript(editor: Editor): void;
|
|
569
692
|
toggleHeading(editor: Editor, level: 1 | 2 | 3): void;
|
|
693
|
+
toggleHighlight(editor: Editor, color?: string): void;
|
|
570
694
|
toggleBulletList(editor: Editor): void;
|
|
571
695
|
toggleOrderedList(editor: Editor): void;
|
|
572
696
|
toggleBlockquote(editor: Editor): void;
|
|
573
|
-
undo(editor: Editor): void;
|
|
574
|
-
redo(editor: Editor): void;
|
|
575
|
-
toggleUnderline(editor: Editor): void;
|
|
576
|
-
toggleSuperscript(editor: Editor): void;
|
|
577
|
-
toggleSubscript(editor: Editor): void;
|
|
578
697
|
setTextAlign(editor: Editor, alignment: "left" | "center" | "right" | "justify"): void;
|
|
579
|
-
toggleLink(editor: Editor, url?: string): void;
|
|
580
698
|
insertHorizontalRule(editor: Editor): void;
|
|
581
|
-
|
|
699
|
+
undo(editor: Editor): void;
|
|
700
|
+
redo(editor: Editor): void;
|
|
582
701
|
insertTable(editor: Editor, rows?: number, cols?: number): void;
|
|
583
702
|
addColumnBefore(editor: Editor): void;
|
|
584
703
|
addColumnAfter(editor: Editor): void;
|
|
@@ -591,13 +710,23 @@ declare class EditorCommandsService {
|
|
|
591
710
|
splitCell(editor: Editor): void;
|
|
592
711
|
toggleHeaderColumn(editor: Editor): void;
|
|
593
712
|
toggleHeaderRow(editor: Editor): void;
|
|
594
|
-
toggleHeaderCell(editor: Editor): void;
|
|
595
713
|
clearContent(editor: Editor): void;
|
|
596
714
|
focus(editor: Editor): void;
|
|
597
715
|
blur(editor: Editor): void;
|
|
598
716
|
setContent(editor: Editor, content: string, emitUpdate?: boolean): void;
|
|
599
717
|
setEditable(editor: Editor, editable: boolean): void;
|
|
600
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>;
|
|
601
730
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EditorCommandsService, never>;
|
|
602
731
|
static ɵprov: _angular_core.ɵɵInjectableDeclaration<EditorCommandsService>;
|
|
603
732
|
}
|
|
@@ -625,7 +754,7 @@ declare const DEFAULT_SLASH_COMMANDS_CONFIG: Record<SlashCommandKey, boolean>;
|
|
|
625
754
|
* Factory pour créer les commandes natives avec leurs traductions et leur logique d'exécution.
|
|
626
755
|
* Utilise les services de l'éditeur pour garantir une cohérence de comportement.
|
|
627
756
|
*/
|
|
628
|
-
declare function createDefaultSlashCommands(i18n: TiptapI18nService, commands: EditorCommandsService,
|
|
757
|
+
declare function createDefaultSlashCommands(i18n: TiptapI18nService, commands: EditorCommandsService, imageOptions?: {
|
|
629
758
|
quality?: number;
|
|
630
759
|
maxWidth?: number;
|
|
631
760
|
maxHeight?: number;
|
|
@@ -634,7 +763,7 @@ declare function createDefaultSlashCommands(i18n: TiptapI18nService, commands: E
|
|
|
634
763
|
/**
|
|
635
764
|
* Filtre et assemble les commandes selon la configuration fournie.
|
|
636
765
|
*/
|
|
637
|
-
declare function filterSlashCommands(config: SlashCommandsConfig, i18n: TiptapI18nService, commands: EditorCommandsService,
|
|
766
|
+
declare function filterSlashCommands(config: SlashCommandsConfig, i18n: TiptapI18nService, commands: EditorCommandsService, imageOptions?: {
|
|
638
767
|
quality?: number;
|
|
639
768
|
maxWidth?: number;
|
|
640
769
|
maxHeight?: number;
|
|
@@ -720,11 +849,6 @@ declare class NoopValueAccessorDirective implements ControlValueAccessor {
|
|
|
720
849
|
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<NoopValueAccessorDirective, never, never, {}, {}, never, never, true, never>;
|
|
721
850
|
}
|
|
722
851
|
|
|
723
|
-
declare const DEFAULT_TOOLBAR_CONFIG: ToolbarConfig;
|
|
724
|
-
declare const DEFAULT_BUBBLE_MENU_CONFIG: BubbleMenuConfig;
|
|
725
|
-
declare const DEFAULT_IMAGE_BUBBLE_MENU_CONFIG: ImageBubbleMenuConfig;
|
|
726
|
-
declare const DEFAULT_TABLE_MENU_CONFIG: TableBubbleMenuConfig;
|
|
727
|
-
declare const DEFAULT_CELL_MENU_CONFIG: CellBubbleMenuConfig$1;
|
|
728
852
|
declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
|
|
729
853
|
content: _angular_core.InputSignal<string>;
|
|
730
854
|
placeholder: _angular_core.InputSignal<string>;
|
|
@@ -742,14 +866,18 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
|
|
|
742
866
|
slashCommands: _angular_core.InputSignal<SlashCommandsConfig>;
|
|
743
867
|
customSlashCommands: _angular_core.InputSignal<CustomSlashCommands | undefined>;
|
|
744
868
|
locale: _angular_core.InputSignal<SupportedLocale | undefined>;
|
|
745
|
-
autofocus: _angular_core.InputSignal<number | boolean | "
|
|
746
|
-
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>)[]>;
|
|
747
871
|
tiptapOptions: _angular_core.InputSignal<Partial<EditorOptions>>;
|
|
748
872
|
showBubbleMenu: _angular_core.InputSignal<boolean>;
|
|
749
873
|
bubbleMenu: _angular_core.InputSignal<Partial<BubbleMenuConfig>>;
|
|
750
874
|
showImageBubbleMenu: _angular_core.InputSignal<boolean>;
|
|
751
875
|
imageBubbleMenu: _angular_core.InputSignal<Partial<ImageBubbleMenuConfig>>;
|
|
752
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[]>;
|
|
753
881
|
imageUpload: _angular_core.InputSignal<Partial<any>>;
|
|
754
882
|
/**
|
|
755
883
|
* Custom handler for image uploads.
|
|
@@ -786,11 +914,14 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
|
|
|
786
914
|
event: FocusEvent;
|
|
787
915
|
}>;
|
|
788
916
|
editorElement: _angular_core.Signal<ElementRef<any>>;
|
|
917
|
+
hideBubbleMenus(): void;
|
|
918
|
+
showBubbleMenus(): void;
|
|
789
919
|
private _editor;
|
|
790
920
|
private _characterCount;
|
|
791
921
|
private _wordCount;
|
|
792
922
|
private _isDragOver;
|
|
793
923
|
private _editorFullyInitialized;
|
|
924
|
+
private lastEmittedHtml;
|
|
794
925
|
readonly editor: _angular_core.Signal<Editor | null>;
|
|
795
926
|
readonly characterCount: _angular_core.Signal<number>;
|
|
796
927
|
readonly wordCount: _angular_core.Signal<number>;
|
|
@@ -830,14 +961,13 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
|
|
|
830
961
|
private _destroyRef;
|
|
831
962
|
private ngControl;
|
|
832
963
|
readonly i18nService: TiptapI18nService;
|
|
833
|
-
readonly imageService: ImageService;
|
|
834
964
|
readonly editorCommandsService: EditorCommandsService;
|
|
965
|
+
readonly editorState: _angular_core.Signal<_flogeez_angular_tiptap_editor.EditorStateSnapshot>;
|
|
835
966
|
constructor();
|
|
836
967
|
ngAfterViewInit(): void;
|
|
837
968
|
ngOnDestroy(): void;
|
|
838
969
|
private initEditor;
|
|
839
970
|
private updateCharacterCount;
|
|
840
|
-
onSlashCommandImageUpload(file: File): Promise<void>;
|
|
841
971
|
onDragOver(event: DragEvent): void;
|
|
842
972
|
onDrop(event: DragEvent): void;
|
|
843
973
|
private insertImageFromFile;
|
|
@@ -853,14 +983,136 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
|
|
|
853
983
|
setDisabledState(isDisabled: boolean): void;
|
|
854
984
|
onEditorClick(event: MouseEvent): void;
|
|
855
985
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<AngularTiptapEditorComponent, never>;
|
|
856
|
-
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: {}; }]>;
|
|
857
987
|
}
|
|
858
988
|
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
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;
|
|
864
1116
|
|
|
865
|
-
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 };
|
|
866
|
-
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;
|
|
@@ -43,3 +50,4 @@
|
|
|
43
50
|
transform: translateY(0) scale(1);
|
|
44
51
|
}
|
|
45
52
|
}
|
|
53
|
+
|