@flogeez/angular-tiptap-editor 2.2.0 → 2.2.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ All notable changes to `@flogeez/angular-tiptap-editor` will be documented in th
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), with the exception that the major version is specifically aligned with the major version of [Tiptap](https://tiptap.dev).
7
7
 
8
+ ## [2.2.2] - 2026-01-26
9
+
10
+ ### Refactored
11
+
12
+ - **Sub-Bubble Menus**: Introduced a new dedicated base class `AteBaseSubBubbleMenu` for specialized menus (link and color). This refactoring centralizes common Tippy.js logic and transition behaviors while preserving the unique anchoring and state-locking requirements of each sub-menu.
13
+
14
+ ## [2.2.1] - 2026-01-25
15
+
16
+ ### Added
17
+
18
+ - **Custom Menu Items**: Added support for custom items in both the `Toolbar` and the `Bubble Menu` via the `custom` property in `AteToolbarConfig` and `AteBubbleMenuConfig`. This allows developers to easily extend the editor's UI with project-specific actions.
19
+
8
20
  ## [2.2.0] - 2026-01-21
9
21
 
10
22
  ### Changed
@@ -122,7 +134,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
122
134
 
123
135
  ### Breaking Changes
124
136
 
125
- - **Service Injection**: If you were injecting `EditorCommandsService` (or other internal services) directly into your own global services/components, it will no longer work. You must now interact with the editor via its public API (`@ViewChild`).
137
+ - **Service Injection**: If you were injecting `EditorCommandsService` (or other internal services) directly into your own global services/components, it will no longer work. You must now interact with the editor via its public API (`@ViewChild or viewChild()`).
126
138
 
127
139
  ## [0.6.0] - 2026-01-14
128
140
 
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  A modern, customizable rich-text editor for Angular applications, built with Tiptap and featuring complete internationalization support.
4
4
 
5
- [![Demo](https://img.shields.io/badge/Demo-Live-brightgreen?style=for-the-badge&logo=google-chrome)](https://flogeez.github.io/angular-tiptap-editor/) [![Try it on StackBlitz](https://img.shields.io/badge/Try%20it-StackBlitz-blue?style=for-the-badge&logo=stackblitz)](https://stackblitz.com/edit/angular-tiptap-editor)
5
+ [![NPM Version](https://img.shields.io/npm/v/@flogeez/angular-tiptap-editor?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@flogeez/angular-tiptap-editor) [![Demo](https://img.shields.io/badge/Demo-Live-brightgreen?style=for-the-badge&logo=google-chrome)](https://flogeez.github.io/angular-tiptap-editor/) [![Try it on StackBlitz](https://img.shields.io/badge/Try%20it-StackBlitz-blue?style=for-the-badge&logo=stackblitz)](https://stackblitz.com/edit/angular-tiptap-editor)
6
6
 
7
7
  ## 🚀 Features
8
8
 
@@ -16,7 +16,7 @@ A modern, customizable rich-text editor for Angular applications, built with Tip
16
16
  - **Built-in i18n**: English & French support with a reactive, extensible locale system.
17
17
  - **Word/Character Count**: Real-time statistics with proper pluralization support.
18
18
  - **Office-Ready**: Cleaned-up pasting from Microsoft Word and Excel to maintain layout integrity.
19
- - **Service Driven**: Deep programmatic control via `EditorCommandsService` and isolated instances.
19
+ - **Service Driven**: Deep programmatic control via `AteEditorCommandsService` and isolated instances.
20
20
  - **A11y First**: Built with accessibility best practices and full keyboard navigation.
21
21
 
22
22
  ## 💎 Why this editor?
@@ -69,7 +69,9 @@ import { AngularTiptapEditorComponent } from "@flogeez/angular-tiptap-editor";
69
69
  selector: "app-example",
70
70
  standalone: true,
71
71
  imports: [AngularTiptapEditorComponent],
72
- template: ` <angular-tiptap-editor [content]="content" (contentChange)="onContentChange($event)" /> `,
72
+ template: `
73
+ <angular-tiptap-editor [content]="content" (contentChange)="onContentChange($event)" />
74
+ `,
73
75
  })
74
76
  export class ExampleComponent {
75
77
  content = "<p>Hello <strong>World</strong>!</p>";
@@ -87,14 +89,21 @@ The editor can be fully configured using a single `[config]` object, which provi
87
89
 
88
90
  ```typescript
89
91
  import { Component } from "@angular/core";
90
- import { AngularTiptapEditorComponent, AteEditorConfig, DEFAULT_TOOLBAR_CONFIG } from "@flogeez/angular-tiptap-editor";
92
+ import {
93
+ AngularTiptapEditorComponent,
94
+ AteEditorConfig,
95
+ ATE_DEFAULT_TOOLBAR_CONFIG,
96
+ } from "@flogeez/angular-tiptap-editor";
91
97
 
92
98
  @Component({
93
99
  selector: "app-advanced",
94
100
  standalone: true,
95
101
  imports: [AngularTiptapEditorComponent],
96
102
  template: `
97
- <angular-tiptap-editor [content]="content" [config]="editorConfig" (contentChange)="onContentChange($event)" />
103
+ <angular-tiptap-editor
104
+ [content]="content"
105
+ [config]="editorConfig"
106
+ (contentChange)="onContentChange($event)" />
98
107
  `,
99
108
  })
100
109
  export class AdvancedComponent {
@@ -109,7 +118,7 @@ export class AdvancedComponent {
109
118
 
110
119
  // Customize the toolbar by enabling specific features
111
120
  toolbar: {
112
- ...DEFAULT_TOOLBAR_CONFIG,
121
+ ...ATE_DEFAULT_TOOLBAR_CONFIG,
113
122
  clear: true, // Enable the 'Clear' button
114
123
  highlight: false, // Disable the highlight button
115
124
  },
@@ -142,7 +151,10 @@ import { AngularTiptapEditorComponent } from "@flogeez/angular-tiptap-editor";
142
151
  standalone: true,
143
152
  imports: [AngularTiptapEditorComponent],
144
153
  template: `
145
- <angular-tiptap-editor [content]="content" [tiptapExtensions]="extensions" (contentChange)="content = $event" />
154
+ <angular-tiptap-editor
155
+ [content]="content"
156
+ [tiptapExtensions]="extensions"
157
+ (contentChange)="content = $event" />
146
158
  `,
147
159
  })
148
160
  export class CustomExtensionsComponent {
@@ -187,7 +199,7 @@ export class FormComponent {
187
199
 
188
200
  ```typescript
189
201
  import { Component, inject } from "@angular/core";
190
- import { EditorCommandsService } from "@flogeez/angular-tiptap-editor";
202
+ import { AteEditorCommandsService } from "@flogeez/angular-tiptap-editor";
191
203
 
192
204
  @Component({
193
205
  selector: "app-commands",
@@ -205,7 +217,7 @@ import { EditorCommandsService } from "@flogeez/angular-tiptap-editor";
205
217
  `,
206
218
  })
207
219
  export class CommandsComponent {
208
- private editorCommandsService = inject(EditorCommandsService);
220
+ private editorCommandsService = inject(AteEditorCommandsService);
209
221
  private editor: Editor | null = null;
210
222
 
211
223
  onEditorCreated(editor: Editor) {
@@ -247,13 +259,13 @@ Any TipTap **Mark** or **Node** you add to `tiptapExtensions` is automatically t
247
259
 
248
260
  If you need to extract complex data (like attributes, depth, or custom logic), you can provide a custom `StateCalculator`.
249
261
 
250
- 1. **Define a Calculator**:
262
+ 1. **Define a Calculator**:
251
263
 
252
264
  ```typescript
253
- import { StateCalculator } from "@flogeez/angular-tiptap-editor";
265
+ import { AteStateCalculator } from "@flogeez/angular-tiptap-editor";
254
266
 
255
267
  // This function will be called on every editor update
256
- export const MyCustomCalculator: StateCalculator = editor => {
268
+ export const MyCustomCalculator: AteStateCalculator = editor => {
257
269
  return {
258
270
  custom: {
259
271
  hasHighPriority: editor.isActive("priority"),
@@ -264,18 +276,18 @@ export const MyCustomCalculator: StateCalculator = editor => {
264
276
  };
265
277
  ```
266
278
 
267
- 2. **Register it in the Template**:
279
+ 2. **Register it in the Template**:
268
280
 
269
281
  ```html
270
282
  <angular-tiptap-editor [stateCalculators]="[MyCustomCalculator]" />
271
283
  ```
272
284
 
273
- 3. **Consume it anywhere**:
285
+ 3. **Consume it anywhere**:
274
286
 
275
287
  ```typescript
276
288
  @Component({ ... })
277
289
  export class MyToolbarComponent {
278
- private editorCommands = inject(EditorCommandsService);
290
+ private editorCommands = inject(AteEditorCommandsService);
279
291
 
280
292
  // Access your custom data reactively!
281
293
  isHighPriority = computed(() => this.editorCommands.editorState().custom?.hasHighPriority);
@@ -309,9 +321,9 @@ Quick content insertion with slash commands:
309
321
  The `slashCommands` object also allows you to add completely custom command items:
310
322
 
311
323
  ```typescript
312
- import { SlashCommandsConfig } from "@flogeez/angular-tiptap-editor";
324
+ import { AteSlashCommandsConfig } from "@flogeez/angular-tiptap-editor";
313
325
 
314
- slashCommands: SlashCommandsConfig = {
326
+ slashCommands: AteSlashCommandsConfig = {
315
327
  // Toggle native commands
316
328
  heading1: true,
317
329
  image: false,
@@ -351,7 +363,10 @@ The handler can return either an **Observable** or a **Promise**.
351
363
  import { Component, inject } from "@angular/core";
352
364
  import { HttpClient } from "@angular/common/http";
353
365
  import { map } from "rxjs/operators";
354
- import { AngularTiptapEditorComponent, ImageUploadHandler } from "@flogeez/angular-tiptap-editor";
366
+ import {
367
+ AngularTiptapEditorComponent,
368
+ AteImageUploadHandler,
369
+ } from "@flogeez/angular-tiptap-editor";
355
370
 
356
371
  @Component({
357
372
  selector: "app-custom-upload",
@@ -368,11 +383,13 @@ export class CustomUploadComponent {
368
383
  private http = inject(HttpClient);
369
384
  content = "";
370
385
 
371
- uploadHandler: ImageUploadHandler = ctx => {
386
+ uploadHandler: AteImageUploadHandler = ctx => {
372
387
  const formData = new FormData();
373
388
  formData.append("image", ctx.file);
374
389
 
375
- return this.http.post<{ url: string }>("/api/upload", formData).pipe(map(result => ({ src: result.url })));
390
+ return this.http
391
+ .post<{ url: string }>("/api/upload", formData)
392
+ .pipe(map(result => ({ src: result.url })));
376
393
  };
377
394
 
378
395
  onContentChange(newContent: string) {
@@ -384,7 +401,7 @@ export class CustomUploadComponent {
384
401
  #### Using Promise (async/await)
385
402
 
386
403
  ```typescript
387
- uploadHandler: ImageUploadHandler = async ctx => {
404
+ uploadHandler: AteImageUploadHandler = async ctx => {
388
405
  const formData = new FormData();
389
406
  formData.append("image", ctx.file);
390
407
 
@@ -463,11 +480,11 @@ Open [http://localhost:4200](http://localhost:4200) to view the demo.
463
480
  | `enableOfficePaste` | `boolean` | `true` | Enable smart Office pasting |
464
481
  | `showCharacterCount` | `boolean` | `true` | Show character counter |
465
482
  | `showWordCount` | `boolean` | `true` | Show word counter |
466
- | `toolbar` | `ToolbarConfig` | All enabled | Detailed toolbar configuration |
467
- | `bubbleMenu` | `BubbleMenuConfig` | All enabled | Detailed bubble menu configuration |
468
- | `slashCommands` | `SlashCommandsConfig` | All enabled | Detailed slash commands config |
469
- | `imageUploadHandler` | `ImageUploadHandler` | `undefined` | Custom image upload function |
470
- | `stateCalculators` | `StateCalculator[]` | `[]` | Custom reactive state logic |
483
+ | `toolbar` | `AteToolbarConfig` | All enabled | Detailed toolbar configuration |
484
+ | `bubbleMenu` | `AteBubbleMenuConfig` | All enabled | Detailed bubble menu configuration |
485
+ | `slashCommands` | `AteSlashCommandsConfig` | All enabled | Detailed slash commands config |
486
+ | `imageUploadHandler` | `AteImageUploadHandler` | `undefined` | Custom image upload function |
487
+ | `stateCalculators` | `AteStateCalculator[]` | `[]` | Custom reactive state logic |
471
488
  | `tiptapExtensions` | `(Extension \| Node \| Mark)[]` | `[]` | Additional Tiptap extensions |
472
489
  | `tiptapOptions` | `Partial<EditorOptions>` | `{}` | Additional Tiptap editor options |
473
490
 
@@ -507,12 +524,12 @@ export interface AteEditorConfig {
507
524
  maxCharacters?: number;
508
525
 
509
526
  // Complex Modules
510
- toolbar?: ToolbarConfig;
511
- bubbleMenu?: BubbleMenuConfig;
512
- imageBubbleMenu?: ImageBubbleMenuConfig;
513
- tableBubbleMenu?: TableBubbleMenuConfig;
514
- cellBubbleMenu?: CellBubbleMenuConfig;
515
- slashCommands?: SlashCommandsConfig;
527
+ toolbar?: AteToolbarConfig;
528
+ bubbleMenu?: AteBubbleMenuConfig;
529
+ imageBubbleMenu?: AteImageBubbleMenuConfig;
530
+ tableBubbleMenu?: AteTableBubbleMenuConfig;
531
+ cellBubbleMenu?: AteCellBubbleMenuConfig;
532
+ slashCommands?: AteSlashCommandsConfig;
516
533
  imageUpload?: AteImageUploadConfig;
517
534
  }
518
535
  ```
@@ -524,7 +541,7 @@ The `imageUpload` property in `AteEditorConfig` provides fine-grained control ov
524
541
  ```typescript
525
542
  export interface AteImageUploadConfig {
526
543
  /** Custom handler to upload files to a server */
527
- handler?: ImageUploadHandler;
544
+ handler?: AteImageUploadHandler;
528
545
  /** Maximum file size in bytes (default: 10MB) */
529
546
  maxFileSize?: number;
530
547
  /** Accepted file types (default: 'image/*') */
@@ -560,14 +577,14 @@ The editor comes with built-in support for **English (en)** and **French (fr)**,
560
577
 
561
578
  ### Adding Custom Languages
562
579
 
563
- You can easily extend the editor with new languages or override existing labels using the `TiptapI18nService`:
580
+ You can easily extend the editor with new languages or override existing labels using the `AteI18nService`:
564
581
 
565
582
  ```typescript
566
- import { TiptapI18nService } from "@flogeez/angular-tiptap-editor";
583
+ import { AteI18nService } from "@flogeez/angular-tiptap-editor";
567
584
 
568
585
  @Component({ ... })
569
586
  export class MyComponent {
570
- constructor(private i18nService: TiptapI18nService) {
587
+ constructor(private i18nService: AteI18nService) {
571
588
  // Add Spanish support
572
589
  this.i18nService.addTranslations('es', {
573
590
  toolbar: { bold: 'Negrita', italic: 'Cursiva', ... },
@@ -651,7 +668,7 @@ angular-tiptap-editor {
651
668
 
652
669
  ### ⚡ Reactive State & OnPush
653
670
 
654
- The library exposes a reactive `editorState` signal via the `EditorCommandsService`. This signal contains everything you need to build custom UIs around the editor:
671
+ The library exposes a reactive `editorState` signal via the `AteEditorCommandsService`. This signal contains everything you need to build custom UIs around the editor:
655
672
 
656
673
  - **Active State**: Check if `bold`, `italic`, or custom marks are active.
657
674
  - **Commands Availability**: Check if `undo`, `redo`, or custom commands can be executed.
@@ -686,13 +703,13 @@ The library uses a **Snapshot & Signal** pattern to bridge Tiptap and Angular.
686
703
 
687
704
  ### Core Services
688
705
 
689
- - **`EditorCommandsService`**: Exposes the `editorState` signal and provides a centralized API for executing Tiptap commands.
690
- - **`ImageService`**: Manages the image processing pipeline (selection, compression, and server-side upload handling).
691
- - **`TiptapI18nService`**: Reactive translation service with support for browser locale auto-detection.
706
+ - **`AteEditorCommandsService`**: Exposes the `editorState` signal and provides a centralized API for executing Tiptap commands.
707
+ - **`AteImageService`**: Manages the image processing pipeline (selection, compression, and server-side upload handling).
708
+ - **`AteI18nService`**: Reactive translation service with support for browser locale auto-detection.
692
709
 
693
710
  ### Isolated Instances
694
711
 
695
- Each component instance provides its own set of services (`EditorCommandsService`, `ImageService`, etc.) at the component level. This ensures that multiple editors on the same page maintain independent states and configurations without interference.
712
+ Each component instance provides its own set of services (`AteEditorCommandsService`, `AteImageService`, etc.) at the component level. This ensures that multiple editors on the same page maintain independent states and configurations without interference.
696
713
 
697
714
  ### Modern Angular Integration
698
715
 
@@ -706,11 +723,11 @@ The library provides default configurations that can be imported and customized:
706
723
 
707
724
  ```typescript
708
725
  import {
709
- DEFAULT_TOOLBAR_CONFIG,
710
- DEFAULT_BUBBLE_MENU_CONFIG,
711
- DEFAULT_IMAGE_BUBBLE_MENU_CONFIG,
712
- DEFAULT_TABLE_MENU_CONFIG,
713
- SLASH_COMMAND_KEYS,
726
+ ATE_DEFAULT_TOOLBAR_CONFIG,
727
+ ATE_DEFAULT_BUBBLE_MENU_CONFIG,
728
+ ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG,
729
+ ATE_DEFAULT_TABLE_MENU_CONFIG,
730
+ ATE_DEFAULT_SLASH_COMMANDS_CONFIG,
714
731
  } from "@flogeez/angular-tiptap-editor";
715
732
  ```
716
733