@flogeez/angular-tiptap-editor 0.2.5 → 0.2.6

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.
@@ -1,6 +1,6 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, output, Component, signal, computed, Injectable, inject, effect, ViewChild, viewChild, forwardRef } from '@angular/core';
3
- import { NG_VALUE_ACCESSOR } from '@angular/forms';
2
+ import { input, output, Component, signal, computed, Injectable, inject, effect, ViewChild, Directive, viewChild, DestroyRef } from '@angular/core';
3
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
4
  import { Node, nodeInputRule, mergeAttributes, Extension, Editor } from '@tiptap/core';
5
5
  import StarterKit from '@tiptap/starter-kit';
6
6
  import Placeholder from '@tiptap/extension-placeholder';
@@ -16,6 +16,8 @@ import { Plugin, PluginKey } from '@tiptap/pm/state';
16
16
  import { DecorationSet, Decoration } from '@tiptap/pm/view';
17
17
  import tippy from 'tippy.js';
18
18
  import { Plugin as Plugin$1, PluginKey as PluginKey$1 } from 'prosemirror-state';
19
+ import { NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
20
+ import { tap } from 'rxjs';
19
21
 
20
22
  const ResizableImage = Node.create({
21
23
  name: "resizableImage",
@@ -3495,6 +3497,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
3495
3497
  args: ["menuRef", { static: false }]
3496
3498
  }] } });
3497
3499
 
3500
+ class NoopValueAccessorDirective {
3501
+ writeValue(obj) { }
3502
+ registerOnChange(fn) { }
3503
+ registerOnTouched(fn) { }
3504
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: NoopValueAccessorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3505
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.0.0", type: NoopValueAccessorDirective, isStandalone: true, providers: [
3506
+ {
3507
+ provide: NG_VALUE_ACCESSOR,
3508
+ multi: true,
3509
+ useExisting: NoopValueAccessorDirective,
3510
+ },
3511
+ ], ngImport: i0 }); }
3512
+ }
3513
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: NoopValueAccessorDirective, decorators: [{
3514
+ type: Directive,
3515
+ args: [{
3516
+ standalone: true,
3517
+ providers: [
3518
+ {
3519
+ provide: NG_VALUE_ACCESSOR,
3520
+ multi: true,
3521
+ useExisting: NoopValueAccessorDirective,
3522
+ },
3523
+ ],
3524
+ }]
3525
+ }] });
3526
+
3498
3527
  // Configuration par défaut de la toolbar
3499
3528
  const DEFAULT_TOOLBAR_CONFIG = {
3500
3529
  bold: true,
@@ -3546,8 +3575,7 @@ const DEFAULT_IMAGE_BUBBLE_MENU_CONFIG = {
3546
3575
  separator: true,
3547
3576
  };
3548
3577
  class AngularTiptapEditorComponent {
3549
- constructor(imageService) {
3550
- this.imageService = imageService;
3578
+ constructor() {
3551
3579
  // Nouveaux inputs avec signal
3552
3580
  this.content = input("");
3553
3581
  this.placeholder = input("");
@@ -3647,11 +3675,11 @@ class AngularTiptapEditorComponent {
3647
3675
  // Configuration par défaut si aucune n'est fournie
3648
3676
  return { commands: undefined }; // Le composant utilisera DEFAULT_SLASH_COMMANDS
3649
3677
  });
3650
- // ControlValueAccessor implementation
3651
- this.onChange = (value) => { };
3652
- this.onTouched = () => { };
3653
- this.pendingFormValue = null;
3678
+ this._destroyRef = inject(DestroyRef);
3679
+ // NgControl pour gérer les FormControls
3680
+ this.ngControl = inject(NgControl, { self: true, optional: true });
3654
3681
  this.i18nService = inject(TiptapI18nService);
3682
+ this.imageService = inject(ImageService);
3655
3683
  // Effet pour gérer le changement de langue
3656
3684
  effect(() => {
3657
3685
  const locale = this.locale();
@@ -3691,12 +3719,11 @@ class AngularTiptapEditorComponent {
3691
3719
  }
3692
3720
  });
3693
3721
  }
3694
- ngOnInit() {
3695
- // L'initialisation se fait maintenant dans ngAfterViewInit
3696
- }
3697
3722
  ngAfterViewInit() {
3698
3723
  // La vue est déjà complètement initialisée dans ngAfterViewInit
3699
3724
  this.initEditor();
3725
+ // S'abonner aux changements du FormControl
3726
+ this.setupFormControlSubscription();
3700
3727
  }
3701
3728
  ngOnDestroy() {
3702
3729
  const currentEditor = this.editor();
@@ -3763,16 +3790,17 @@ class AngularTiptapEditorComponent {
3763
3790
  onUpdate: ({ editor, transaction }) => {
3764
3791
  const html = editor.getHTML();
3765
3792
  this.contentChange.emit(html);
3766
- // Defer the onChange call to prevent ExpressionChangedAfterItHasBeenCheckedError
3767
- Promise.resolve().then(() => {
3768
- this.onChange(html);
3769
- });
3793
+ // Mettre à jour le FormControl si il existe (dans le prochain cycle)
3794
+ if (this.ngControl?.control) {
3795
+ setTimeout(() => {
3796
+ this.ngControl.control.setValue(html, {
3797
+ emitEvent: false,
3798
+ });
3799
+ }, 0);
3800
+ }
3770
3801
  this.editorUpdate.emit({ editor, transaction });
3771
3802
  this.updateCharacterCount(editor);
3772
3803
  },
3773
- onSelectionUpdate: ({ editor, transaction }) => {
3774
- // Note: La mise à jour des états des boutons est maintenant gérée par TiptapBubbleMenuComponent
3775
- },
3776
3804
  onCreate: ({ editor }) => {
3777
3805
  this.editorCreated.emit(editor);
3778
3806
  this.updateCharacterCount(editor);
@@ -3786,16 +3814,19 @@ class AngularTiptapEditorComponent {
3786
3814
  this.editorFocus.emit({ editor, event });
3787
3815
  },
3788
3816
  onBlur: ({ editor, event }) => {
3789
- this.onTouched();
3817
+ // Marquer le FormControl comme touché si il existe
3818
+ if (this.ngControl?.control) {
3819
+ this.ngControl.control.markAsTouched();
3820
+ }
3790
3821
  this.editorBlur.emit({ editor, event });
3791
3822
  },
3792
3823
  });
3793
3824
  // Stocker la référence de l'éditeur immédiatement
3794
3825
  this.editor.set(newEditor);
3795
- // Appliquer la valeur du FormControl en attente si elle existe
3796
- if (this.pendingFormValue !== null) {
3797
- this.setContent(this.pendingFormValue, false);
3798
- this.pendingFormValue = null;
3826
+ // Vérifier si on a un contenu initial via l'input content()
3827
+ const initialContent = this.content();
3828
+ if (initialContent) {
3829
+ this.setContent(initialContent, false);
3799
3830
  }
3800
3831
  }
3801
3832
  updateCharacterCount(editor) {
@@ -3885,24 +3916,37 @@ class AngularTiptapEditorComponent {
3885
3916
  clearContent() {
3886
3917
  this.editor()?.commands.clearContent();
3887
3918
  }
3888
- // ControlValueAccessor methods
3889
- writeValue(value) {
3890
- const currentEditor = this.editor();
3891
- if (currentEditor && value !== currentEditor.getHTML()) {
3892
- this.setContent(value || "", false);
3893
- this.pendingFormValue = null; // Valeur appliquée, plus besoin de la stocker
3919
+ normalizeHTML(html) {
3920
+ if (!html)
3921
+ return "";
3922
+ // Normaliser les espaces et retours à la ligne pour une comparaison fiable
3923
+ return html
3924
+ .replace(/\s+/g, " ") // Remplacer espaces multiples par un seul
3925
+ .replace(/>\s+</g, "><") // Supprimer espaces entre balises
3926
+ .replace(/<br\s*\/?>/gi, "<br>") // Normaliser les <br>
3927
+ .trim();
3928
+ }
3929
+ checkInitialFormValue() {
3930
+ // Vérifier si on a une valeur initiale dans le FormControl
3931
+ if (this.ngControl?.control?.value) {
3932
+ console.log("Found initial FormControl value:", this.ngControl.control.value);
3933
+ this.setContent(this.ngControl.control.value, false);
3894
3934
  }
3895
- else {
3896
- // Éditeur pas encore prêt, stocker la valeur du FormControl pour plus tard
3897
- this.pendingFormValue = value || "";
3898
- }
3899
- }
3900
- registerOnChange(fn) {
3901
- this.onChange = fn;
3902
3935
  }
3903
- registerOnTouched(fn) {
3904
- this.onTouched = fn;
3936
+ setupFormControlSubscription() {
3937
+ const control = this.ngControl?.control;
3938
+ if (control) {
3939
+ control.valueChanges
3940
+ .pipe(tap((value) => {
3941
+ const editor = this.editor();
3942
+ if (editor && value !== editor.getHTML()) {
3943
+ this.setContent(value, false);
3944
+ }
3945
+ }), takeUntilDestroyed(this._destroyRef))
3946
+ .subscribe();
3947
+ }
3905
3948
  }
3949
+ // Méthode pour gérer l'état disabled
3906
3950
  setDisabledState(isDisabled) {
3907
3951
  const currentEditor = this.editor();
3908
3952
  if (currentEditor) {
@@ -3927,14 +3971,8 @@ class AngularTiptapEditorComponent {
3927
3971
  }, 0);
3928
3972
  }
3929
3973
  }
3930
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AngularTiptapEditorComponent, deps: [{ token: ImageService }], target: i0.ɵɵFactoryTarget.Component }); }
3931
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: AngularTiptapEditorComponent, isStandalone: true, selector: "angular-tiptap-editor", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showCharacterCount: { classPropertyName: "showCharacterCount", publicName: "showCharacterCount", isSignal: true, isRequired: false, transformFunction: null }, maxCharacters: { classPropertyName: "maxCharacters", publicName: "maxCharacters", isSignal: true, isRequired: false, transformFunction: null }, enableOfficePaste: { classPropertyName: "enableOfficePaste", publicName: "enableOfficePaste", isSignal: true, isRequired: false, transformFunction: null }, enableSlashCommands: { classPropertyName: "enableSlashCommands", publicName: "enableSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, slashCommandsConfig: { classPropertyName: "slashCommandsConfig", publicName: "slashCommandsConfig", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, showBubbleMenu: { classPropertyName: "showBubbleMenu", publicName: "showBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, bubbleMenu: { classPropertyName: "bubbleMenu", publicName: "bubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showImageBubbleMenu: { classPropertyName: "showImageBubbleMenu", publicName: "showImageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, imageBubbleMenu: { classPropertyName: "imageBubbleMenu", publicName: "imageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentChange: "contentChange", editorCreated: "editorCreated", editorUpdate: "editorUpdate", editorFocus: "editorFocus", editorBlur: "editorBlur" }, providers: [
3932
- {
3933
- provide: NG_VALUE_ACCESSOR,
3934
- useExisting: forwardRef(() => AngularTiptapEditorComponent),
3935
- multi: true,
3936
- },
3937
- ], viewQueries: [{ propertyName: "editorElement", first: true, predicate: ["editorElement"], descendants: true, isSignal: true }], ngImport: i0, template: `
3974
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AngularTiptapEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3975
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: AngularTiptapEditorComponent, isStandalone: true, selector: "angular-tiptap-editor", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showCharacterCount: { classPropertyName: "showCharacterCount", publicName: "showCharacterCount", isSignal: true, isRequired: false, transformFunction: null }, maxCharacters: { classPropertyName: "maxCharacters", publicName: "maxCharacters", isSignal: true, isRequired: false, transformFunction: null }, enableOfficePaste: { classPropertyName: "enableOfficePaste", publicName: "enableOfficePaste", isSignal: true, isRequired: false, transformFunction: null }, enableSlashCommands: { classPropertyName: "enableSlashCommands", publicName: "enableSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, slashCommandsConfig: { classPropertyName: "slashCommandsConfig", publicName: "slashCommandsConfig", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, showBubbleMenu: { classPropertyName: "showBubbleMenu", publicName: "showBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, bubbleMenu: { classPropertyName: "bubbleMenu", publicName: "bubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showImageBubbleMenu: { classPropertyName: "showImageBubbleMenu", publicName: "showImageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, imageBubbleMenu: { classPropertyName: "imageBubbleMenu", publicName: "imageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentChange: "contentChange", editorCreated: "editorCreated", editorUpdate: "editorUpdate", editorFocus: "editorFocus", editorBlur: "editorBlur" }, viewQueries: [{ propertyName: "editorElement", first: true, predicate: ["editorElement"], descendants: true, isSignal: true }], hostDirectives: [{ directive: NoopValueAccessorDirective }], ngImport: i0, template: `
3938
3976
  <div class="tiptap-editor">
3939
3977
  <!-- Toolbar -->
3940
3978
  @if (showToolbar() && editor()) {
@@ -4003,7 +4041,7 @@ class AngularTiptapEditorComponent {
4003
4041
  }
4004
4042
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AngularTiptapEditorComponent, decorators: [{
4005
4043
  type: Component,
4006
- args: [{ selector: "angular-tiptap-editor", standalone: true, imports: [
4044
+ args: [{ selector: "angular-tiptap-editor", standalone: true, hostDirectives: [NoopValueAccessorDirective], imports: [
4007
4045
  TiptapToolbarComponent,
4008
4046
  TiptapImageUploadComponent,
4009
4047
  TiptapBubbleMenuComponent,
@@ -4074,14 +4112,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
4074
4112
  </div>
4075
4113
  }
4076
4114
  </div>
4077
- `, providers: [
4078
- {
4079
- provide: NG_VALUE_ACCESSOR,
4080
- useExisting: forwardRef(() => AngularTiptapEditorComponent),
4081
- multi: true,
4082
- },
4083
- ], styles: [".tiptap-editor{border:2px solid #e2e8f0;border-radius:8px;background:#fff;box-shadow:0 2px 4px #0000001a;overflow:hidden;transition:border-color .2s ease}.tiptap-editor:focus-within{border-color:#3182ce;box-shadow:0 0 0 3px #3182ce1a}.tiptap-content{padding:16px;min-height:var(--editor-min-height, 200px);height:var(--editor-height, auto);max-height:var(--editor-max-height, none);overflow-y:var(--editor-overflow, visible);outline:none;position:relative}.tiptap-content.drag-over{background:#f0f8ff;border:2px dashed #3182ce}.character-count{padding:8px 16px;font-size:12px;color:#718096;text-align:right;border-top:1px solid #e2e8f0;background:#f8f9fa}.image-upload-container{position:relative;display:inline-block}:host ::ng-deep .ProseMirror{outline:none;line-height:1.6;color:#2d3748;min-height:100%;height:100%;word-wrap:break-word;overflow-wrap:break-word}:host ::ng-deep .ProseMirror h1{font-size:2em;font-weight:700;margin-top:0;margin-bottom:.5em}:host ::ng-deep .ProseMirror h2{font-size:1.5em;font-weight:700;margin-top:1em;margin-bottom:.5em}:host ::ng-deep .ProseMirror h3{font-size:1.25em;font-weight:700;margin-top:1em;margin-bottom:.5em}:host ::ng-deep .ProseMirror p{margin:.5em 0}:host ::ng-deep .ProseMirror ul,:host ::ng-deep .ProseMirror ol{padding-left:2em;margin:.5em 0}:host ::ng-deep .ProseMirror blockquote{border-left:4px solid #e2e8f0;margin:1em 0;font-style:italic;background:#f8f9fa;padding:.5em 1em;border-radius:0 4px 4px 0}:host ::ng-deep .ProseMirror code{background:#f1f5f9;padding:.2em .4em;border-radius:3px;font-family:Monaco,Consolas,monospace;font-size:.9em}:host ::ng-deep .ProseMirror pre{background:#1a202c;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;margin:1em 0}:host ::ng-deep .ProseMirror pre code{background:none;color:inherit;padding:0}:host ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:#a0aec0;pointer-events:none;float:left;height:0}:host ::ng-deep .ProseMirror[contenteditable=false]{pointer-events:none}:host ::ng-deep .ProseMirror[contenteditable=false] img{cursor:default;pointer-events:none}:host ::ng-deep .ProseMirror[contenteditable=false] img:hover{transform:none;box-shadow:0 2px 8px #0000001a}:host ::ng-deep .ProseMirror[contenteditable=false] img.ProseMirror-selectednode{outline:none}:host ::ng-deep .ProseMirror img{position:relative;display:inline-block;max-width:100%;height:auto;cursor:pointer;transition:all .2s ease;border:2px solid transparent;border-radius:8px}:host ::ng-deep .ProseMirror img:hover{border-color:#e2e8f0;box-shadow:0 2px 4px #0000001a}:host ::ng-deep .ProseMirror img.ProseMirror-selectednode{border-color:#3182ce;box-shadow:0 0 0 3px #3182ce1a;transition:all .2s ease}:host ::ng-deep .ProseMirror .tiptap-image{max-width:100%;height:auto;border-radius:16px;box-shadow:0 4px 20px #00000014;margin:.5em 0;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);display:block;filter:brightness(1) contrast(1)}:host ::ng-deep .ProseMirror .tiptap-image:hover{box-shadow:0 8px 30px #0000001f;filter:brightness(1.02) contrast(1.02)}:host ::ng-deep .ProseMirror .tiptap-image.ProseMirror-selectednode{outline:2px solid #6366f1;outline-offset:2px;border-radius:16px;box-shadow:0 0 0 4px #6366f11a}:host ::ng-deep .image-container{margin:.5em 0;text-align:center;border-radius:16px;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1)}:host ::ng-deep .image-container.image-align-left{text-align:left}:host ::ng-deep .image-container.image-align-center{text-align:center}:host ::ng-deep .image-container.image-align-right{text-align:right}:host ::ng-deep .image-container img{display:inline-block;max-width:100%;height:auto;border-radius:16px}:host ::ng-deep .resizable-image-container{position:relative;display:inline-block;margin:.5em 0}:host ::ng-deep .resize-controls{position:absolute;inset:0;pointer-events:none;z-index:1000}:host ::ng-deep .resize-handle{position:absolute;width:12px;height:12px;background:#3b82f6;border:2px solid white;border-radius:50%;pointer-events:all;cursor:pointer;z-index:1001;transition:all .15s ease;box-shadow:0 2px 6px #0003}:host ::ng-deep .resize-handle:hover{background:#2563eb;box-shadow:0 3px 8px #0000004d}:host ::ng-deep .resize-handle:active{background:#1d4ed8}:host ::ng-deep .resize-handle-n:hover,:host ::ng-deep .resize-handle-s:hover{transform:translate(-50%) scale(1.2)}:host ::ng-deep .resize-handle-w:hover,:host ::ng-deep .resize-handle-e:hover{transform:translateY(-50%) scale(1.2)}:host ::ng-deep .resize-handle-n:active,:host ::ng-deep .resize-handle-s:active{transform:translate(-50%) scale(.9)}:host ::ng-deep .resize-handle-w:active,:host ::ng-deep .resize-handle-e:active{transform:translateY(-50%) scale(.9)}:host ::ng-deep .resize-handle-nw:hover,:host ::ng-deep .resize-handle-ne:hover,:host ::ng-deep .resize-handle-sw:hover,:host ::ng-deep .resize-handle-se:hover{transform:scale(1.2)}:host ::ng-deep .resize-handle-nw:active,:host ::ng-deep .resize-handle-ne:active,:host ::ng-deep .resize-handle-sw:active,:host ::ng-deep .resize-handle-se:active{transform:scale(.9)}:host ::ng-deep .resize-handle-nw{top:0;left:-6px;cursor:nw-resize}:host ::ng-deep .resize-handle-n{top:0;left:50%;transform:translate(-50%);cursor:n-resize}:host ::ng-deep .resize-handle-ne{top:0;right:-6px;cursor:ne-resize}:host ::ng-deep .resize-handle-w{top:50%;left:-6px;transform:translateY(-50%);cursor:w-resize}:host ::ng-deep .resize-handle-e{top:50%;right:-6px;transform:translateY(-50%);cursor:e-resize}:host ::ng-deep .resize-handle-sw{bottom:0;left:-6px;cursor:sw-resize}:host ::ng-deep .resize-handle-s{bottom:0;left:50%;transform:translate(-50%);cursor:s-resize}:host ::ng-deep .resize-handle-se{bottom:0;right:-6px;cursor:se-resize}:host ::ng-deep body.resizing{-webkit-user-select:none;user-select:none;cursor:crosshair}:host ::ng-deep body.resizing .ProseMirror{pointer-events:none}:host ::ng-deep body.resizing .ProseMirror .tiptap-image{pointer-events:none}:host ::ng-deep .image-size-info{position:absolute;bottom:-20px;left:50%;transform:translate(-50%);background:#000c;color:#fff;padding:2px 6px;border-radius:3px;font-size:11px;white-space:nowrap;opacity:0;transition:opacity .2s ease}:host ::ng-deep .image-container:hover .image-size-info{opacity:1}\n"] }]
4084
- }], ctorParameters: () => [{ type: ImageService }] });
4115
+ `, styles: [".tiptap-editor{border:2px solid #e2e8f0;border-radius:8px;background:#fff;box-shadow:0 2px 4px #0000001a;overflow:hidden;transition:border-color .2s ease}.tiptap-editor:focus-within{border-color:#3182ce;box-shadow:0 0 0 3px #3182ce1a}.tiptap-content{padding:16px;min-height:var(--editor-min-height, 200px);height:var(--editor-height, auto);max-height:var(--editor-max-height, none);overflow-y:var(--editor-overflow, visible);outline:none;position:relative}.tiptap-content.drag-over{background:#f0f8ff;border:2px dashed #3182ce}.character-count{padding:8px 16px;font-size:12px;color:#718096;text-align:right;border-top:1px solid #e2e8f0;background:#f8f9fa}.image-upload-container{position:relative;display:inline-block}:host ::ng-deep .ProseMirror{outline:none;line-height:1.6;color:#2d3748;min-height:100%;height:100%;word-wrap:break-word;overflow-wrap:break-word}:host ::ng-deep .ProseMirror h1{font-size:2em;font-weight:700;margin-top:0;margin-bottom:.5em}:host ::ng-deep .ProseMirror h2{font-size:1.5em;font-weight:700;margin-top:1em;margin-bottom:.5em}:host ::ng-deep .ProseMirror h3{font-size:1.25em;font-weight:700;margin-top:1em;margin-bottom:.5em}:host ::ng-deep .ProseMirror p{margin:.5em 0}:host ::ng-deep .ProseMirror ul,:host ::ng-deep .ProseMirror ol{padding-left:2em;margin:.5em 0}:host ::ng-deep .ProseMirror blockquote{border-left:4px solid #e2e8f0;margin:1em 0;font-style:italic;background:#f8f9fa;padding:.5em 1em;border-radius:0 4px 4px 0}:host ::ng-deep .ProseMirror code{background:#f1f5f9;padding:.2em .4em;border-radius:3px;font-family:Monaco,Consolas,monospace;font-size:.9em}:host ::ng-deep .ProseMirror pre{background:#1a202c;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;margin:1em 0}:host ::ng-deep .ProseMirror pre code{background:none;color:inherit;padding:0}:host ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:#a0aec0;pointer-events:none;float:left;height:0}:host ::ng-deep .ProseMirror[contenteditable=false]{pointer-events:none}:host ::ng-deep .ProseMirror[contenteditable=false] img{cursor:default;pointer-events:none}:host ::ng-deep .ProseMirror[contenteditable=false] img:hover{transform:none;box-shadow:0 2px 8px #0000001a}:host ::ng-deep .ProseMirror[contenteditable=false] img.ProseMirror-selectednode{outline:none}:host ::ng-deep .ProseMirror img{position:relative;display:inline-block;max-width:100%;height:auto;cursor:pointer;transition:all .2s ease;border:2px solid transparent;border-radius:8px}:host ::ng-deep .ProseMirror img:hover{border-color:#e2e8f0;box-shadow:0 2px 4px #0000001a}:host ::ng-deep .ProseMirror img.ProseMirror-selectednode{border-color:#3182ce;box-shadow:0 0 0 3px #3182ce1a;transition:all .2s ease}:host ::ng-deep .ProseMirror .tiptap-image{max-width:100%;height:auto;border-radius:16px;box-shadow:0 4px 20px #00000014;margin:.5em 0;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);display:block;filter:brightness(1) contrast(1)}:host ::ng-deep .ProseMirror .tiptap-image:hover{box-shadow:0 8px 30px #0000001f;filter:brightness(1.02) contrast(1.02)}:host ::ng-deep .ProseMirror .tiptap-image.ProseMirror-selectednode{outline:2px solid #6366f1;outline-offset:2px;border-radius:16px;box-shadow:0 0 0 4px #6366f11a}:host ::ng-deep .image-container{margin:.5em 0;text-align:center;border-radius:16px;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1)}:host ::ng-deep .image-container.image-align-left{text-align:left}:host ::ng-deep .image-container.image-align-center{text-align:center}:host ::ng-deep .image-container.image-align-right{text-align:right}:host ::ng-deep .image-container img{display:inline-block;max-width:100%;height:auto;border-radius:16px}:host ::ng-deep .resizable-image-container{position:relative;display:inline-block;margin:.5em 0}:host ::ng-deep .resize-controls{position:absolute;inset:0;pointer-events:none;z-index:1000}:host ::ng-deep .resize-handle{position:absolute;width:12px;height:12px;background:#3b82f6;border:2px solid white;border-radius:50%;pointer-events:all;cursor:pointer;z-index:1001;transition:all .15s ease;box-shadow:0 2px 6px #0003}:host ::ng-deep .resize-handle:hover{background:#2563eb;box-shadow:0 3px 8px #0000004d}:host ::ng-deep .resize-handle:active{background:#1d4ed8}:host ::ng-deep .resize-handle-n:hover,:host ::ng-deep .resize-handle-s:hover{transform:translate(-50%) scale(1.2)}:host ::ng-deep .resize-handle-w:hover,:host ::ng-deep .resize-handle-e:hover{transform:translateY(-50%) scale(1.2)}:host ::ng-deep .resize-handle-n:active,:host ::ng-deep .resize-handle-s:active{transform:translate(-50%) scale(.9)}:host ::ng-deep .resize-handle-w:active,:host ::ng-deep .resize-handle-e:active{transform:translateY(-50%) scale(.9)}:host ::ng-deep .resize-handle-nw:hover,:host ::ng-deep .resize-handle-ne:hover,:host ::ng-deep .resize-handle-sw:hover,:host ::ng-deep .resize-handle-se:hover{transform:scale(1.2)}:host ::ng-deep .resize-handle-nw:active,:host ::ng-deep .resize-handle-ne:active,:host ::ng-deep .resize-handle-sw:active,:host ::ng-deep .resize-handle-se:active{transform:scale(.9)}:host ::ng-deep .resize-handle-nw{top:0;left:-6px;cursor:nw-resize}:host ::ng-deep .resize-handle-n{top:0;left:50%;transform:translate(-50%);cursor:n-resize}:host ::ng-deep .resize-handle-ne{top:0;right:-6px;cursor:ne-resize}:host ::ng-deep .resize-handle-w{top:50%;left:-6px;transform:translateY(-50%);cursor:w-resize}:host ::ng-deep .resize-handle-e{top:50%;right:-6px;transform:translateY(-50%);cursor:e-resize}:host ::ng-deep .resize-handle-sw{bottom:0;left:-6px;cursor:sw-resize}:host ::ng-deep .resize-handle-s{bottom:0;left:50%;transform:translate(-50%);cursor:s-resize}:host ::ng-deep .resize-handle-se{bottom:0;right:-6px;cursor:se-resize}:host ::ng-deep body.resizing{-webkit-user-select:none;user-select:none;cursor:crosshair}:host ::ng-deep body.resizing .ProseMirror{pointer-events:none}:host ::ng-deep body.resizing .ProseMirror .tiptap-image{pointer-events:none}:host ::ng-deep .image-size-info{position:absolute;bottom:-20px;left:50%;transform:translate(-50%);background:#000c;color:#fff;padding:2px 6px;border-radius:3px;font-size:11px;white-space:nowrap;opacity:0;transition:opacity .2s ease}:host ::ng-deep .image-container:hover .image-size-info{opacity:1}\n"] }]
4116
+ }], ctorParameters: () => [] });
4085
4117
 
4086
4118
  /**
4087
4119
  * Factory function pour créer les slash commands traduits
@@ -4246,5 +4278,5 @@ const SLASH_COMMAND_KEYS = {
4246
4278
  * Generated bundle index. Do not edit.
4247
4279
  */
4248
4280
 
4249
- export { AngularTiptapEditorComponent, DEFAULT_BUBBLE_MENU_CONFIG, DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, DEFAULT_SLASH_COMMANDS, DEFAULT_TOOLBAR_CONFIG, TiptapI18nService, createI18nSlashCommands };
4281
+ export { AngularTiptapEditorComponent, DEFAULT_BUBBLE_MENU_CONFIG, DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, DEFAULT_SLASH_COMMANDS, DEFAULT_TOOLBAR_CONFIG, NoopValueAccessorDirective, TiptapI18nService, createI18nSlashCommands };
4250
4282
  //# sourceMappingURL=flogeez-angular-tiptap-editor.mjs.map