@flogeez/angular-tiptap-editor 2.0.3 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -410,151 +410,6 @@ interface CustomSlashCommands {
410
410
  commands?: SlashCommandItem[];
411
411
  }
412
412
 
413
- interface ImageData {
414
- src: string;
415
- alt?: string;
416
- title?: string;
417
- width?: number;
418
- height?: number;
419
- }
420
- interface ImageUploadResult {
421
- src: string;
422
- name: string;
423
- size: number;
424
- type: string;
425
- width?: number;
426
- height?: number;
427
- originalSize?: number;
428
- }
429
- interface ResizeOptions {
430
- width?: number;
431
- height?: number;
432
- maintainAspectRatio?: boolean;
433
- }
434
- /**
435
- * Context passed to the image upload handler containing information about the image
436
- */
437
- interface ImageUploadContext {
438
- /** Original file being uploaded */
439
- file: File;
440
- /** Width of the processed image */
441
- width: number;
442
- /** Height of the processed image */
443
- height: number;
444
- /** MIME type of the image */
445
- type: string;
446
- /** Base64 data URL of the processed image (after compression/resize) */
447
- base64: string;
448
- }
449
- /**
450
- * Result expected from a custom image upload handler.
451
- * Must contain at least the `src` property with the image URL.
452
- */
453
- interface ImageUploadHandlerResult {
454
- /** URL of the uploaded image (can be a remote URL or any string) */
455
- src: string;
456
- /** Optional custom alt text */
457
- alt?: string;
458
- /** Optional custom title */
459
- title?: string;
460
- }
461
- /**
462
- * Custom handler function for image uploads.
463
- * Allows users to implement their own image storage logic (e.g., upload to S3, Cloudinary, etc.)
464
- *
465
- * Can return either a Promise or an Observable (Angular-friendly).
466
- *
467
- * @param context - Context containing the image file and metadata
468
- * @returns Promise or Observable resolving to ImageUploadHandlerResult
469
- *
470
- * @example Using Promise (async/await)
471
- * ```typescript
472
- * uploadHandler: ImageUploadHandler = async (ctx) => {
473
- * const formData = new FormData();
474
- * formData.append('image', ctx.file);
475
- * const result = await firstValueFrom(this.http.post<{url: string}>('/api/upload', formData));
476
- * return { src: result.url };
477
- * };
478
- * ```
479
- *
480
- * @example Using Observable (Angular HttpClient)
481
- * ```typescript
482
- * uploadHandler: ImageUploadHandler = (ctx) => {
483
- * const formData = new FormData();
484
- * formData.append('image', ctx.file);
485
- * return this.http.post<{url: string}>('/api/upload', formData).pipe(
486
- * map(result => ({ src: result.url }))
487
- * );
488
- * };
489
- * ```
490
- */
491
- type ImageUploadHandler = (context: ImageUploadContext) => Promise<ImageUploadHandlerResult> | Observable<ImageUploadHandlerResult>;
492
- declare class ImageService {
493
- /** Signals for image state */
494
- selectedImage: _angular_core.WritableSignal<ImageData | null>;
495
- isImageSelected: _angular_core.Signal<boolean>;
496
- /** Resizing state */
497
- isResizing: _angular_core.WritableSignal<boolean>;
498
- private i18n;
499
- private readonly t;
500
- /** Upload state signals */
501
- isUploading: _angular_core.WritableSignal<boolean>;
502
- uploadProgress: _angular_core.WritableSignal<number>;
503
- uploadMessage: _angular_core.WritableSignal<string>;
504
- /**
505
- * Custom upload handler.
506
- * If set, this handler replaces the default base64 conversion.
507
- */
508
- uploadHandler: ImageUploadHandler | null;
509
- private currentEditor;
510
- /** Select and track an image from the editor */
511
- selectImage(editor: Editor): void;
512
- clearSelection(): void;
513
- /** Insert a new image and ensure it's selected */
514
- insertImage(editor: Editor, imageData: ImageData): void;
515
- /** Update attributes of the currently active image */
516
- updateImageAttributes(editor: Editor, attributes: Partial<ImageData>): void;
517
- /** Resize image with optional aspect ratio maintenance */
518
- resizeImage(editor: Editor, options: ResizeOptions): void;
519
- /** Predetermined resize helpers used by UI */
520
- resizeImageToSmall(editor: Editor): void;
521
- resizeImageToMedium(editor: Editor): void;
522
- resizeImageToLarge(editor: Editor): void;
523
- resizeImageToOriginal(editor: Editor): void;
524
- /** Get current image dimensions */
525
- getImageDimensions(editor: Editor): {
526
- width: number;
527
- height: number;
528
- } | null;
529
- /** Remove the selected image */
530
- deleteImage(editor: Editor): void;
531
- private updateSelectedImage;
532
- /** Validate file type and size */
533
- validateImage(file: File, maxSize?: number): {
534
- valid: boolean;
535
- error?: string;
536
- };
537
- /** Compress and process image on client side */
538
- compressImage(file: File, quality?: number, maxWidth?: number, maxHeight?: number): Promise<ImageUploadResult>;
539
- /** Core upload logic with progress tracking */
540
- private uploadImageWithProgress;
541
- private resetUploadState;
542
- /** Main entry point for file upload and insertion */
543
- uploadAndInsertImage(editor: Editor, file: File, options?: Record<string, any>): Promise<void>;
544
- /** Trigger an editor transaction to force decoration update */
545
- private forceEditorUpdate;
546
- /** Generic helper to open file picker and process selection */
547
- private selectFileAndProcess;
548
- /** Select file and upload as new image */
549
- selectAndUploadImage(editor: Editor, options?: Record<string, any>): Promise<void>;
550
- /** Select file and replace currently selected image */
551
- selectAndReplaceImage(editor: Editor, options?: Record<string, any>): Promise<void>;
552
- /** Internal helper used by replacement logic */
553
- uploadAndReplaceImage(editor: Editor, file: File, options?: Record<string, any>): Promise<void>;
554
- static ɵfac: _angular_core.ɵɵFactoryDeclaration<ImageService, never>;
555
- static ɵprov: _angular_core.ɵɵInjectableDeclaration<ImageService>;
556
- }
557
-
558
413
  type StateCalculator = (editor: Editor) => Partial<{
559
414
  [K in keyof EditorStateSnapshot]: EditorStateSnapshot[K] extends object ? Partial<EditorStateSnapshot[K]> : EditorStateSnapshot[K];
560
415
  }>;
@@ -664,6 +519,110 @@ interface EditorStateSnapshot {
664
519
  }
665
520
  declare const INITIAL_EDITOR_STATE: EditorStateSnapshot;
666
521
 
522
+ interface ImageData {
523
+ src: string;
524
+ alt?: string;
525
+ title?: string;
526
+ width?: number;
527
+ height?: number;
528
+ }
529
+ interface ImageUploadResult {
530
+ src: string;
531
+ name: string;
532
+ size: number;
533
+ type: string;
534
+ width?: number;
535
+ height?: number;
536
+ originalSize?: number;
537
+ }
538
+ interface ResizeOptions {
539
+ width?: number;
540
+ height?: number;
541
+ maintainAspectRatio?: boolean;
542
+ }
543
+ interface ImageUploadOptions {
544
+ quality?: number;
545
+ maxWidth?: number;
546
+ maxHeight?: number;
547
+ maxSize?: number;
548
+ allowedTypes?: string[];
549
+ }
550
+ /**
551
+ * Context passed to the image upload handler containing information about the image
552
+ */
553
+ interface ImageUploadContext {
554
+ /** Original file being uploaded */
555
+ file: File;
556
+ /** Width of the processed image */
557
+ width: number;
558
+ /** Height of the processed image */
559
+ height: number;
560
+ /** MIME type of the image */
561
+ type: string;
562
+ /** Base64 data URL of the processed image (after compression/resize) */
563
+ base64: string;
564
+ }
565
+ /**
566
+ * Result expected from a custom image upload handler.
567
+ * Must contain at least the `src` property with the image URL.
568
+ */
569
+ interface ImageUploadHandlerResult {
570
+ /** URL of the uploaded image (can be a remote URL or any string) */
571
+ src: string;
572
+ /** Optional custom alt text */
573
+ alt?: string;
574
+ /** Optional custom title */
575
+ title?: string;
576
+ }
577
+ /**
578
+ * Custom handler function for image uploads.
579
+ * Allows users to implement their own image storage logic (e.g., upload to S3, Cloudinary, etc.)
580
+ *
581
+ * Can return either a Promise or an Observable (Angular-friendly).
582
+ *
583
+ * @param context - Context containing the image file and metadata
584
+ * @returns Promise or Observable resolving to ImageUploadHandlerResult
585
+ *
586
+ * @example Using Promise (async/await)
587
+ * ```typescript
588
+ * uploadHandler: ImageUploadHandler = async (ctx) => {
589
+ * const formData = new FormData();
590
+ * formData.append('image', ctx.file);
591
+ * const result = await firstValueFrom(this.http.post<{url: string}>('/api/upload', formData));
592
+ * return { src: result.url };
593
+ * };
594
+ * ```
595
+ *
596
+ * @example Using Observable (Angular HttpClient)
597
+ * ```typescript
598
+ * uploadHandler: ImageUploadHandler = (ctx) => {
599
+ * const formData = new FormData();
600
+ * formData.append('image', ctx.file);
601
+ * return this.http.post<{url: string}>('/api/upload', formData).pipe(
602
+ * map(result => ({ src: result.url }))
603
+ * );
604
+ * };
605
+ * ```
606
+ */
607
+ type ImageUploadHandler = (context: ImageUploadContext) => Promise<ImageUploadHandlerResult> | Observable<ImageUploadHandlerResult>;
608
+ /**
609
+ * Interface dedicated to image upload configuration.
610
+ */
611
+ interface AteImageUploadConfig {
612
+ /** Callback function to handle upload (Promise or Observable) */
613
+ handler?: ImageUploadHandler;
614
+ /** Compression quality (0 to 1) */
615
+ quality?: number;
616
+ /** Maximum allowed width in pixels */
617
+ maxWidth?: number;
618
+ /** Maximum allowed height in pixels */
619
+ maxHeight?: number;
620
+ /** Maximum allowed size in MB */
621
+ maxSize?: number;
622
+ /** Accepted file types (e.g., ['image/jpeg', 'image/png']) */
623
+ allowedTypes?: string[];
624
+ }
625
+
667
626
  declare class EditorCommandsService {
668
627
  private imageService;
669
628
  private colorPickerSvc;
@@ -727,17 +686,8 @@ declare class EditorCommandsService {
727
686
  setContent(editor: Editor, content: string, emitUpdate?: boolean): void;
728
687
  setEditable(editor: Editor, editable: boolean): void;
729
688
  insertContent(editor: Editor, content: string): void;
730
- insertImage(editor: Editor, options?: {
731
- quality?: number;
732
- maxWidth?: number;
733
- maxHeight?: number;
734
- accept?: string;
735
- }): Promise<void>;
736
- uploadImage(editor: Editor, file: File, options?: {
737
- quality?: number;
738
- maxWidth?: number;
739
- maxHeight?: number;
740
- }): Promise<void>;
689
+ insertImage(editor: Editor, options?: ImageUploadOptions): Promise<void>;
690
+ uploadImage(editor: Editor, file: File, options?: ImageUploadOptions): Promise<void>;
741
691
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<EditorCommandsService, never>;
742
692
  static ɵprov: _angular_core.ɵɵInjectableDeclaration<EditorCommandsService>;
743
693
  }
@@ -853,6 +803,77 @@ interface CellBubbleMenuConfig {
853
803
  splitCell?: boolean;
854
804
  }
855
805
 
806
+ /**
807
+ * Global configuration interface for Angular Tiptap Editor.
808
+ * Uses a flat structure for common settings and objects for complex configurations.
809
+ */
810
+ interface AteEditorConfig {
811
+ /** Editor theme: light, dark, or system auto-detection */
812
+ theme?: "light" | "dark" | "auto";
813
+ /** Display mode: classic or seamless (no borders/background) */
814
+ mode?: "classic" | "seamless";
815
+ /** Editor height (e.g., '300px', 'auto') */
816
+ height?: string;
817
+ /** Focus position on initialization */
818
+ autofocus?: "start" | "end" | "all" | boolean | number;
819
+ /** Placeholder text displayed when the editor is empty */
820
+ placeholder?: string;
821
+ /** Initial editing state (if false, the editor is read-only) */
822
+ editable?: boolean;
823
+ /** Minimum editor height (e.g., '200px') */
824
+ minHeight?: string;
825
+ /** Maximum editor height (e.g., '500px') */
826
+ maxHeight?: string;
827
+ /** If true, the editor takes 100% of the parent container's height */
828
+ fillContainer?: boolean;
829
+ /** Disabled state (often used with forms) */
830
+ disabled?: boolean;
831
+ /** Editor locale (overrides the global i18n service) */
832
+ locale?: string;
833
+ /** Enable browser spellcheck */
834
+ spellcheck?: boolean;
835
+ /** Enable smart cleanup when pasting from Office/Word */
836
+ enableOfficePaste?: boolean;
837
+ /** Show or hide the toolbar */
838
+ showToolbar?: boolean;
839
+ /** Show or hide the footer (counters area) */
840
+ showFooter?: boolean;
841
+ /** Show or hide the character count */
842
+ showCharacterCount?: boolean;
843
+ /** Show or hide the word count */
844
+ showWordCount?: boolean;
845
+ /** Show or hide the read-only/edit toggle button */
846
+ showEditToggle?: boolean;
847
+ /** Show or hide the text context menu */
848
+ showBubbleMenu?: boolean;
849
+ /** Show or hide the image context menu */
850
+ showImageBubbleMenu?: boolean;
851
+ /** Show or hide the table menu */
852
+ showTableMenu?: boolean;
853
+ /** Show or hide the cell menu */
854
+ showCellMenu?: boolean;
855
+ /** Enable or disable slash commands (/) */
856
+ enableSlashCommands?: boolean;
857
+ /** Maximum number of characters allowed */
858
+ maxCharacters?: number;
859
+ /** Detailed toolbar configuration (items, groups) */
860
+ toolbar?: ToolbarConfig;
861
+ /** Text context menu configuration */
862
+ bubbleMenu?: BubbleMenuConfig;
863
+ /** Image context menu configuration */
864
+ imageBubbleMenu?: ImageBubbleMenuConfig;
865
+ /** Table context menu configuration */
866
+ tableBubbleMenu?: TableBubbleMenuConfig;
867
+ /** Cell context menu configuration */
868
+ cellBubbleMenu?: CellBubbleMenuConfig;
869
+ /** Slash commands configuration (/) */
870
+ slashCommands?: SlashCommandsConfig;
871
+ /** If true, shows the floating toolbar on focus */
872
+ floatingToolbar?: boolean;
873
+ /** Technical configuration for image uploads */
874
+ imageUpload?: AteImageUploadConfig;
875
+ }
876
+
856
877
  declare class NoopValueAccessorDirective implements ControlValueAccessor {
857
878
  writeValue(obj: any): void;
858
879
  registerOnChange(fn: any): void;
@@ -862,6 +883,8 @@ declare class NoopValueAccessorDirective implements ControlValueAccessor {
862
883
  }
863
884
 
864
885
  declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
886
+ /** Configuration globale de l'éditeur */
887
+ config: _angular_core.InputSignal<AteEditorConfig>;
865
888
  content: _angular_core.InputSignal<string>;
866
889
  placeholder: _angular_core.InputSignal<string>;
867
890
  editable: _angular_core.InputSignal<boolean>;
@@ -884,6 +907,7 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
884
907
  seamless: _angular_core.InputSignal<boolean>;
885
908
  floatingToolbar: _angular_core.InputSignal<boolean>;
886
909
  showEditToggle: _angular_core.InputSignal<boolean>;
910
+ spellcheck: _angular_core.InputSignal<boolean>;
887
911
  tiptapExtensions: _angular_core.InputSignal<(Node<any, any> | Mark<any, any> | Extension<any, any>)[]>;
888
912
  tiptapOptions: _angular_core.InputSignal<Partial<EditorOptions>>;
889
913
  showBubbleMenu: _angular_core.InputSignal<boolean>;
@@ -899,7 +923,7 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
899
923
  * Additionnal state calculators to extend the reactive editor state.
900
924
  */
901
925
  stateCalculators: _angular_core.InputSignal<StateCalculator[]>;
902
- imageUpload: _angular_core.InputSignal<Partial<any>>;
926
+ imageUpload: _angular_core.InputSignal<Partial<ImageUploadOptions>>;
903
927
  /**
904
928
  * Custom handler for image uploads.
905
929
  * When provided, images will be processed through this handler instead of being converted to base64.
@@ -953,13 +977,38 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
953
977
  readonly isFormControlDisabled: _angular_core.Signal<boolean>;
954
978
  readonly mergedDisabled: _angular_core.Signal<boolean>;
955
979
  isEditorReady: _angular_core.Signal<boolean>;
956
- toolbarConfig: _angular_core.Signal<ToolbarConfig>;
957
- bubbleMenuConfig: _angular_core.Signal<BubbleMenuConfig>;
958
- imageBubbleMenuConfig: _angular_core.Signal<ImageBubbleMenuConfig>;
959
- tableBubbleMenuConfig: _angular_core.Signal<TableBubbleMenuConfig>;
960
- cellBubbleMenuConfig: _angular_core.Signal<CellBubbleMenuConfig>;
961
- imageUploadConfig: _angular_core.Signal<{
980
+ readonly finalSeamless: _angular_core.Signal<boolean>;
981
+ readonly finalPlaceholder: _angular_core.Signal<string>;
982
+ readonly finalFillContainer: _angular_core.Signal<boolean>;
983
+ readonly finalShowFooter: _angular_core.Signal<boolean>;
984
+ readonly finalShowEditToggle: _angular_core.Signal<boolean>;
985
+ readonly finalHeight: _angular_core.Signal<string | undefined>;
986
+ readonly finalMinHeight: _angular_core.Signal<string | undefined>;
987
+ readonly finalMaxHeight: _angular_core.Signal<string | undefined>;
988
+ readonly finalSpellcheck: _angular_core.Signal<boolean>;
989
+ readonly finalEnableOfficePaste: _angular_core.Signal<boolean>;
990
+ readonly finalShowToolbar: _angular_core.Signal<boolean>;
991
+ readonly finalToolbarConfig: _angular_core.Signal<ToolbarConfig>;
992
+ readonly finalFloatingToolbar: _angular_core.Signal<boolean>;
993
+ readonly finalShowBubbleMenu: _angular_core.Signal<boolean>;
994
+ readonly finalBubbleMenuConfig: _angular_core.Signal<BubbleMenuConfig>;
995
+ readonly finalShowImageBubbleMenu: _angular_core.Signal<boolean>;
996
+ readonly finalImageBubbleMenuConfig: _angular_core.Signal<ImageBubbleMenuConfig>;
997
+ readonly finalShowTableBubbleMenu: _angular_core.Signal<boolean>;
998
+ readonly finalTableBubbleMenuConfig: _angular_core.Signal<TableBubbleMenuConfig>;
999
+ readonly finalShowCellBubbleMenu: _angular_core.Signal<boolean>;
1000
+ readonly finalCellBubbleMenuConfig: _angular_core.Signal<CellBubbleMenuConfig>;
1001
+ readonly finalEnableSlashCommands: _angular_core.Signal<boolean>;
1002
+ readonly finalSlashCommandsConfig: _angular_core.Signal<CustomSlashCommands>;
1003
+ readonly finalAutofocus: _angular_core.Signal<number | boolean | "start" | "end" | "all">;
1004
+ readonly finalMaxCharacters: _angular_core.Signal<number | undefined>;
1005
+ readonly finalShowCharacterCount: _angular_core.Signal<boolean>;
1006
+ readonly finalShowWordCount: _angular_core.Signal<boolean>;
1007
+ readonly finalLocale: _angular_core.Signal<SupportedLocale>;
1008
+ readonly finalImageUploadConfig: _angular_core.Signal<{
962
1009
  maxSize: number;
1010
+ handler?: ImageUploadHandler;
1011
+ quality: number;
963
1012
  maxWidth: number;
964
1013
  maxHeight: number;
965
1014
  allowedTypes: string[];
@@ -967,9 +1016,8 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
967
1016
  showPreview: boolean;
968
1017
  multiple: boolean;
969
1018
  compressImages: boolean;
970
- quality: number;
971
1019
  }>;
972
- slashCommandsConfigComputed: _angular_core.Signal<CustomSlashCommands>;
1020
+ readonly finalImageUploadHandler: _angular_core.Signal<ImageUploadHandler | undefined>;
973
1021
  readonly currentTranslations: _angular_core.Signal<_flogeez_angular_tiptap_editor.TiptapTranslations>;
974
1022
  private _destroyRef;
975
1023
  private ngControl;
@@ -996,7 +1044,76 @@ declare class AngularTiptapEditorComponent implements AfterViewInit, OnDestroy {
996
1044
  private setupFormControlSubscription;
997
1045
  onEditorClick(event: MouseEvent): void;
998
1046
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<AngularTiptapEditorComponent, never>;
999
- 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; }; "disabled": { "alias": "disabled"; "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; }; "showFooter": { "alias": "showFooter"; "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; }; "seamless": { "alias": "seamless"; "required": false; "isSignal": true; }; "floatingToolbar": { "alias": "floatingToolbar"; "required": false; "isSignal": true; }; "showEditToggle": { "alias": "showEditToggle"; "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; }; "showTableBubbleMenu": { "alias": "showTableBubbleMenu"; "required": false; "isSignal": true; }; "tableBubbleMenu": { "alias": "tableBubbleMenu"; "required": false; "isSignal": true; }; "showCellBubbleMenu": { "alias": "showCellBubbleMenu"; "required": false; "isSignal": true; }; "cellBubbleMenu": { "alias": "cellBubbleMenu"; "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"; "editableChange": "editableChange"; }, never, never, true, [{ directive: typeof NoopValueAccessorDirective; inputs: {}; outputs: {}; }]>;
1047
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<AngularTiptapEditorComponent, "angular-tiptap-editor", never, { "config": { "alias": "config"; "required": false; "isSignal": true; }; "content": { "alias": "content"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "editable": { "alias": "editable"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "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; }; "showFooter": { "alias": "showFooter"; "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; }; "seamless": { "alias": "seamless"; "required": false; "isSignal": true; }; "floatingToolbar": { "alias": "floatingToolbar"; "required": false; "isSignal": true; }; "showEditToggle": { "alias": "showEditToggle"; "required": false; "isSignal": true; }; "spellcheck": { "alias": "spellcheck"; "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; }; "showTableBubbleMenu": { "alias": "showTableBubbleMenu"; "required": false; "isSignal": true; }; "tableBubbleMenu": { "alias": "tableBubbleMenu"; "required": false; "isSignal": true; }; "showCellBubbleMenu": { "alias": "showCellBubbleMenu"; "required": false; "isSignal": true; }; "cellBubbleMenu": { "alias": "cellBubbleMenu"; "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"; "editableChange": "editableChange"; }, never, never, true, [{ directive: typeof NoopValueAccessorDirective; inputs: {}; outputs: {}; }]>;
1048
+ }
1049
+
1050
+ declare class ImageService {
1051
+ /** Signals for image state */
1052
+ selectedImage: _angular_core.WritableSignal<ImageData | null>;
1053
+ isImageSelected: _angular_core.Signal<boolean>;
1054
+ /** Resizing state */
1055
+ isResizing: _angular_core.WritableSignal<boolean>;
1056
+ private i18n;
1057
+ private readonly t;
1058
+ /** Upload state signals */
1059
+ isUploading: _angular_core.WritableSignal<boolean>;
1060
+ uploadProgress: _angular_core.WritableSignal<number>;
1061
+ uploadMessage: _angular_core.WritableSignal<string>;
1062
+ /**
1063
+ * Custom upload handler.
1064
+ * If set, this handler replaces the default base64 conversion.
1065
+ */
1066
+ uploadHandler: ImageUploadHandler | null;
1067
+ private currentEditor;
1068
+ /** Select and track an image from the editor */
1069
+ selectImage(editor: Editor): void;
1070
+ clearSelection(): void;
1071
+ /** Insert a new image and ensure it's selected */
1072
+ insertImage(editor: Editor, imageData: ImageData): void;
1073
+ /** Update attributes of the currently active image */
1074
+ updateImageAttributes(editor: Editor, attributes: Partial<ImageData>): void;
1075
+ /** Resize image with optional aspect ratio maintenance */
1076
+ resizeImage(editor: Editor, options: ResizeOptions): void;
1077
+ /** Predetermined resize helpers used by UI */
1078
+ resizeImageToSmall(editor: Editor): void;
1079
+ resizeImageToMedium(editor: Editor): void;
1080
+ resizeImageToLarge(editor: Editor): void;
1081
+ resizeImageToOriginal(editor: Editor): void;
1082
+ /** Get current image dimensions */
1083
+ getImageDimensions(editor: Editor): {
1084
+ width: number;
1085
+ height: number;
1086
+ } | null;
1087
+ /** Remove the selected image */
1088
+ deleteImage(editor: Editor): void;
1089
+ private updateSelectedImage;
1090
+ /** Validate file type and size */
1091
+ validateImage(file: File, options?: {
1092
+ maxSize?: number;
1093
+ allowedTypes?: string[];
1094
+ }): {
1095
+ valid: boolean;
1096
+ error?: string;
1097
+ };
1098
+ /** Compress and process image on client side */
1099
+ compressImage(file: File, quality?: number, maxWidth?: number, maxHeight?: number): Promise<ImageUploadResult>;
1100
+ /** Core upload logic with progress tracking */
1101
+ private uploadImageWithProgress;
1102
+ private resetUploadState;
1103
+ /** Main entry point for file upload and insertion */
1104
+ uploadAndInsertImage(editor: Editor, file: File, options?: ImageUploadOptions): Promise<void>;
1105
+ /** Trigger an editor transaction to force decoration update */
1106
+ private forceEditorUpdate;
1107
+ /** Generic helper to open file picker and process selection */
1108
+ private selectFileAndProcess;
1109
+ /** Select file and upload as new image */
1110
+ selectAndUploadImage(editor: Editor, options?: ImageUploadOptions): Promise<void>;
1111
+ /** Select file and replace currently selected image */
1112
+ selectAndReplaceImage(editor: Editor, options?: ImageUploadOptions): Promise<void>;
1113
+ /** Internal helper used by replacement logic */
1114
+ uploadAndReplaceImage(editor: Editor, file: File, options?: ImageUploadOptions): Promise<void>;
1115
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ImageService, never>;
1116
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<ImageService>;
1000
1117
  }
1001
1118
 
1002
1119
  interface ColorPickerSelection {
@@ -1128,4 +1245,4 @@ declare const DEFAULT_TABLE_MENU_CONFIG: TableBubbleMenuConfig;
1128
1245
  declare const DEFAULT_CELL_MENU_CONFIG: CellBubbleMenuConfig;
1129
1246
 
1130
1247
  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 };
1131
- export type { BubbleMenuConfig, CellBubbleMenuConfig, ColorEditMode, ColorPickerSelection, CustomSlashCommands, EditorStateSnapshot, ImageBubbleMenuConfig, ImageData, ImageUploadContext, ImageUploadHandler, ImageUploadHandlerResult, ImageUploadResult, ResizeOptions, SlashCommandItem, SlashCommandKey, SlashCommandsConfig, StateCalculator, SupportedLocale, TableBubbleMenuConfig, TiptapTranslations, ToolbarConfig };
1248
+ export type { AteEditorConfig, AteImageUploadConfig, BubbleMenuConfig, CellBubbleMenuConfig, ColorEditMode, ColorPickerSelection, CustomSlashCommands, EditorStateSnapshot, ImageBubbleMenuConfig, ImageData, ImageUploadContext, ImageUploadHandler, ImageUploadHandlerResult, ImageUploadOptions, ImageUploadResult, ResizeOptions, SlashCommandItem, SlashCommandKey, SlashCommandsConfig, StateCalculator, SupportedLocale, TableBubbleMenuConfig, TiptapTranslations, ToolbarConfig };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flogeez/angular-tiptap-editor",
3
- "version": "2.0.3",
3
+ "version": "2.1.1",
4
4
  "description": "A modern, customizable rich-text editor for Angular (18+), built with Tiptap and featuring complete internationalization support",
5
5
  "keywords": [
6
6
  "angular",