@flogeez/angular-tiptap-editor 0.3.1 → 0.3.2

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.
@@ -2338,7 +2338,20 @@ class EditorCommandsService {
2338
2338
  }
2339
2339
  // Méthode pour vider le contenu
2340
2340
  clearContent(editor) {
2341
- editor.chain().focus().clearContent().run();
2341
+ editor.chain().focus().setContent("", true).run(); // ✅ Forcer l'émission de l'événement
2342
+ }
2343
+ // Méthodes de base de l'éditeur
2344
+ focus(editor) {
2345
+ editor.chain().focus().run();
2346
+ }
2347
+ blur(editor) {
2348
+ editor.chain().blur().run();
2349
+ }
2350
+ setContent(editor, content, emitUpdate = true) {
2351
+ editor.chain().focus().setContent(content, emitUpdate).run();
2352
+ }
2353
+ setEditable(editor, editable) {
2354
+ editor.setEditable(editable);
2342
2355
  }
2343
2356
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: EditorCommandsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2344
2357
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: EditorCommandsService, providedIn: "root" }); }
@@ -4469,12 +4482,18 @@ class AngularTiptapEditorComponent {
4469
4482
  this.editorBlur = output();
4470
4483
  // ViewChild avec signal
4471
4484
  this.editorElement = viewChild.required("editorElement");
4472
- // Signals pour l'état interne
4473
- this.editor = signal(null);
4474
- this.characterCount = signal(0);
4475
- this.wordCount = signal(0);
4476
- this.isDragOver = signal(false);
4477
- this.editorFullyInitialized = signal(false);
4485
+ // Signals privés pour l'état interne
4486
+ this._editor = signal(null);
4487
+ this._characterCount = signal(0);
4488
+ this._wordCount = signal(0);
4489
+ this._isDragOver = signal(false);
4490
+ this._editorFullyInitialized = signal(false);
4491
+ // Accès en lecture seule aux signaux
4492
+ this.editor = this._editor.asReadonly();
4493
+ this.characterCount = this._characterCount.asReadonly();
4494
+ this.wordCount = this._wordCount.asReadonly();
4495
+ this.isDragOver = this._isDragOver.asReadonly();
4496
+ this.editorFullyInitialized = this._editorFullyInitialized.asReadonly();
4478
4497
  // Computed pour les états de l'éditeur
4479
4498
  this.isEditorReady = computed(() => this.editor() !== null);
4480
4499
  // Computed pour la configuration de la toolbar
@@ -4526,6 +4545,7 @@ class AngularTiptapEditorComponent {
4526
4545
  this.ngControl = inject(NgControl, { self: true, optional: true });
4527
4546
  this.i18nService = inject(TiptapI18nService);
4528
4547
  this.imageService = inject(ImageService);
4548
+ this.editorCommandsService = inject(EditorCommandsService);
4529
4549
  // Effet pour gérer le changement de langue
4530
4550
  effect(() => {
4531
4551
  const locale = this.locale();
@@ -4566,7 +4586,7 @@ class AngularTiptapEditorComponent {
4566
4586
  const currentEditor = this.editor();
4567
4587
  const isEditable = this.editable();
4568
4588
  if (currentEditor) {
4569
- currentEditor.setEditable(isEditable);
4589
+ this.editorCommandsService.setEditable(currentEditor, isEditable);
4570
4590
  }
4571
4591
  });
4572
4592
  // Effect pour la détection du survol des tables
@@ -4588,7 +4608,7 @@ class AngularTiptapEditorComponent {
4588
4608
  if (currentEditor) {
4589
4609
  currentEditor.destroy();
4590
4610
  }
4591
- this.editorFullyInitialized.set(false);
4611
+ this._editorFullyInitialized.set(false);
4592
4612
  }
4593
4613
  initEditor() {
4594
4614
  const extensions = [
@@ -4666,7 +4686,7 @@ class AngularTiptapEditorComponent {
4666
4686
  // Marquer l'éditeur comme complètement initialisé après un court délai
4667
4687
  // pour s'assurer que tous les plugins et extensions sont prêts
4668
4688
  setTimeout(() => {
4669
- this.editorFullyInitialized.set(true);
4689
+ this._editorFullyInitialized.set(true);
4670
4690
  }, 100);
4671
4691
  },
4672
4692
  onFocus: ({ editor, event }) => {
@@ -4681,13 +4701,13 @@ class AngularTiptapEditorComponent {
4681
4701
  },
4682
4702
  });
4683
4703
  // Stocker la référence de l'éditeur immédiatement
4684
- this.editor.set(newEditor);
4704
+ this._editor.set(newEditor);
4685
4705
  }
4686
4706
  updateCharacterCount(editor) {
4687
4707
  if (this.showCharacterCount() && editor.storage["characterCount"]) {
4688
4708
  const storage = editor.storage["characterCount"];
4689
- this.characterCount.set(storage.characters());
4690
- this.wordCount.set(storage.words());
4709
+ this._characterCount.set(storage.characters());
4710
+ this._wordCount.set(storage.words());
4691
4711
  }
4692
4712
  }
4693
4713
  // Méthodes pour l'upload d'images
@@ -4721,12 +4741,12 @@ class AngularTiptapEditorComponent {
4721
4741
  onDragOver(event) {
4722
4742
  event.preventDefault();
4723
4743
  event.stopPropagation();
4724
- this.isDragOver.set(true);
4744
+ this._isDragOver.set(true);
4725
4745
  }
4726
4746
  onDrop(event) {
4727
4747
  event.preventDefault();
4728
4748
  event.stopPropagation();
4729
- this.isDragOver.set(false);
4749
+ this._isDragOver.set(false);
4730
4750
  const files = event.dataTransfer?.files;
4731
4751
  if (files && files.length > 0) {
4732
4752
  const file = files[0];
@@ -4757,22 +4777,33 @@ class AngularTiptapEditorComponent {
4757
4777
  return this.editor()?.getText() || "";
4758
4778
  }
4759
4779
  setContent(content, emitUpdate = true) {
4760
- this.editor()?.commands.setContent(content, emitUpdate);
4780
+ const editor = this.editor();
4781
+ if (editor) {
4782
+ this.editorCommandsService.setContent(editor, content, emitUpdate);
4783
+ }
4761
4784
  }
4762
4785
  focus() {
4763
- this.editor()?.commands.focus();
4786
+ const editor = this.editor();
4787
+ if (editor) {
4788
+ this.editorCommandsService.focus(editor);
4789
+ }
4764
4790
  }
4765
4791
  blur() {
4766
- this.editor()?.commands.blur();
4792
+ const editor = this.editor();
4793
+ if (editor) {
4794
+ this.editorCommandsService.blur(editor);
4795
+ }
4767
4796
  }
4768
4797
  clearContent() {
4769
4798
  const editor = this.editor();
4770
4799
  if (editor) {
4771
- editor.commands.clearContent();
4772
- // Mettre à jour les compteurs après avoir vidé le contenu
4773
- this.updateCharacterCount(editor);
4800
+ this.editorCommandsService.clearContent(editor);
4774
4801
  }
4775
4802
  }
4803
+ // Méthode publique pour obtenir l'éditeur
4804
+ getEditor() {
4805
+ return this.editor();
4806
+ }
4776
4807
  setupFormControlSubscription() {
4777
4808
  const control = this.ngControl?.control;
4778
4809
  if (control) {
@@ -4791,7 +4822,7 @@ class AngularTiptapEditorComponent {
4791
4822
  setDisabledState(isDisabled) {
4792
4823
  const currentEditor = this.editor();
4793
4824
  if (currentEditor) {
4794
- currentEditor.setEditable(!isDisabled);
4825
+ this.editorCommandsService.setEditable(currentEditor, !isDisabled);
4795
4826
  }
4796
4827
  }
4797
4828
  onEditorClick(event) {
@@ -5000,6 +5031,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
5000
5031
  `, styles: [".tiptap-editor{border:2px solid #e2e8f0;border-radius:8px;background:#fff;overflow:hidden;transition:border-color .2s ease}.tiptap-editor:focus-within{border-color:#3182ce}.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}:host ::ng-deep .ProseMirror table{border-collapse:separate;border-spacing:0;margin:0;table-layout:fixed;width:100%;border-radius:8px;overflow:hidden}:host ::ng-deep .ProseMirror table td,:host ::ng-deep .ProseMirror table th{border:none;border-right:1px solid #e2e8f0;border-bottom:1px solid #e2e8f0;box-sizing:border-box;min-width:1em;padding:8px 12px;position:relative;vertical-align:top;background:#fff}:host ::ng-deep .ProseMirror table td:first-child,:host ::ng-deep .ProseMirror table th:first-child{border-left:1px solid #e2e8f0}:host ::ng-deep .ProseMirror table tr:first-child td,:host ::ng-deep .ProseMirror table tr:first-child th{border-top:1px solid #e2e8f0}:host ::ng-deep .ProseMirror table tr:first-child th:first-child{border-top-left-radius:8px}:host ::ng-deep .ProseMirror table tr:first-child th:last-child{border-top-right-radius:8px}:host ::ng-deep .ProseMirror table tr:last-child td:first-child{border-bottom-left-radius:8px}:host ::ng-deep .ProseMirror table tr:last-child td:last-child{border-bottom-right-radius:8px}:host ::ng-deep .ProseMirror table th{background:#f8f9fa;font-weight:600;color:#374151}:host ::ng-deep .ProseMirror table .selectedCell:after{background:#c8c8ff66;content:\"\";inset:0;pointer-events:none;position:absolute;z-index:2}:host ::ng-deep .ProseMirror table .column-resize-handle{position:absolute;right:-2px;top:0;bottom:0;width:4px;background-color:#6366f1;opacity:0;transition:opacity .2s ease}:host ::ng-deep .ProseMirror table:hover .column-resize-handle{opacity:1}:host ::ng-deep .ProseMirror table .column-resize-handle:hover{background-color:#4f46e5}:host ::ng-deep .ProseMirror .tableWrapper{overflow-x:auto;margin:1em 0;border-radius:8px}:host ::ng-deep .ProseMirror .tableWrapper table{margin:0;border-radius:8px;min-width:600px;overflow:hidden}:host ::ng-deep .ProseMirror table p{margin:0}:host ::ng-deep .ProseMirror table .selectedCell{background-color:#6366f11a}:host ::ng-deep .ProseMirror table th{background-color:#f8f9fa;font-weight:600;color:#374151;text-align:left}:host ::ng-deep .ProseMirror table tbody tr:nth-child(2n){background-color:#fafbfc}:host ::ng-deep .ProseMirror table tbody tr:hover{background-color:#f1f5f9}\n"] }]
5001
5032
  }], ctorParameters: () => [] });
5002
5033
 
5034
+ /**
5035
+ * Clés des commandes dans l'ordre de création
5036
+ */
5037
+ const SLASH_COMMAND_KEYS = [
5038
+ "heading1",
5039
+ "heading2",
5040
+ "heading3",
5041
+ "bulletList",
5042
+ "orderedList",
5043
+ "blockquote",
5044
+ "code",
5045
+ "image",
5046
+ "horizontalRule",
5047
+ "table",
5048
+ ];
5003
5049
  /**
5004
5050
  * Factory function pour créer les slash commands traduits
5005
5051
  */
@@ -5147,20 +5193,18 @@ function createI18nSlashCommands(i18nService) {
5147
5193
  ];
5148
5194
  }
5149
5195
  /**
5150
- * Mapping des clés de commandes pour la compatibilité
5196
+ * Fonction utilitaire pour filtrer les slash commands selon les commandes actives
5197
+ * Utilise le service i18n injecté en interne
5151
5198
  */
5152
- const SLASH_COMMAND_KEYS = {
5153
- heading1: "heading1",
5154
- heading2: "heading2",
5155
- heading3: "heading3",
5156
- bulletList: "bulletList",
5157
- orderedList: "orderedList",
5158
- blockquote: "blockquote",
5159
- code: "code",
5160
- image: "image",
5161
- horizontalRule: "horizontalRule",
5162
- table: "table",
5163
- };
5199
+ function filterSlashCommands(activeCommands) {
5200
+ // Injecter le service i18n en interne
5201
+ const i18nService = inject(TiptapI18nService);
5202
+ const allCommands = createI18nSlashCommands(i18nService);
5203
+ return allCommands.filter((command, index) => {
5204
+ const commandKey = SLASH_COMMAND_KEYS[index];
5205
+ return commandKey && activeCommands.has(commandKey);
5206
+ });
5207
+ }
5164
5208
 
5165
5209
  /*
5166
5210
  * Public API Surface of tiptap-editor
@@ -5171,5 +5215,5 @@ const SLASH_COMMAND_KEYS = {
5171
5215
  * Generated bundle index. Do not edit.
5172
5216
  */
5173
5217
 
5174
- export { AngularTiptapEditorComponent, DEFAULT_BUBBLE_MENU_CONFIG, DEFAULT_CELL_MENU_CONFIG, DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, DEFAULT_SLASH_COMMANDS, DEFAULT_TABLE_MENU_CONFIG, DEFAULT_TOOLBAR_CONFIG, NoopValueAccessorDirective, TiptapI18nService, createI18nSlashCommands };
5218
+ export { AngularTiptapEditorComponent, DEFAULT_BUBBLE_MENU_CONFIG, DEFAULT_CELL_MENU_CONFIG, DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, DEFAULT_SLASH_COMMANDS, DEFAULT_TABLE_MENU_CONFIG, DEFAULT_TOOLBAR_CONFIG, EditorCommandsService, ImageService, NoopValueAccessorDirective, SLASH_COMMAND_KEYS, TiptapI18nService, createI18nSlashCommands, filterSlashCommands };
5175
5219
  //# sourceMappingURL=flogeez-angular-tiptap-editor.mjs.map