@flogeez/angular-tiptap-editor 2.2.3 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@ 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.4.0] - 2026-01-29
9
+
10
+ ### Added
11
+
12
+ - **Seamless Angular Integration**: Drastically simplified editor setup and component registration.
13
+ - **Global Provider**: Added `provideAteEditor()` for automatic injector capture and application-wide configuration defaults.
14
+ - **Declarative Angular Nodes**: Support for registering Angular components directly within the `angularNodes` configuration property.
15
+ - **Exhaustive Configuration**: All editor inputs (extensions, options, state calculators) are now part of `AteEditorConfig` for centralized management.
16
+ - **Config Inheritance**: Intelligent merging of global, instance, and input-level configurations.
17
+
18
+ ### Fixed
19
+
20
+ - **NodeView Stability**: Enhanced initialization and lifecycle management for embedded Angular components.
21
+
22
+ ## [2.3.0] - 2026-01-28
23
+
24
+ ### Added
25
+
26
+ - **Advanced Angular Component Engine**: A powerful, unified engine to embed any Angular component directly into the editor as a custom TipTap node.
27
+ - **Universal Integration**: Seamlessly register both standard library components and TipTap-aware interactive components.
28
+ - **Modern Reactive Support**: Full out-of-the-box compatibility with Angular 18+ Signal-based `input()` and `output()`.
29
+ - **Editable Content Zones**: Turn any part of your Angular component into a nested, editable rich-text area.
30
+ - **Robustness**: Build-in protection against naming collisions and reserved TipTap nodes.
31
+
8
32
  ## [2.2.3] - 2026-01-27
9
33
 
10
34
  ### Added
package/README.md CHANGED
@@ -1,13 +1,16 @@
1
1
  # Angular Tiptap Editor
2
2
 
3
- A modern, customizable rich-text editor for Angular applications, built with Tiptap and featuring complete internationalization support.
3
+ A modern, customizable rich-text editor for Angular, built with Tiptap.
4
4
 
5
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
+ Angular Tiptap Editor is a high-performance WYSIWYG editor engineered for the modern Angular ecosystem. Built on top of Tiptap and powered by a native **Signals** architecture, it features a polished, professional design that feels, I think, clean and modern out of the box.
8
+ Yet, I've worked to keep it fully customizable: you can easily configure the editor, tweak the UI, or even embed your own Angular components as interactive nodes.
9
+
7
10
  ## 🚀 Features
8
11
 
9
12
  - **Modern Angular**: Built with Angular 18+ using Signals and modern patterns for peak performance.
10
- - **Full Rich Text Power**: Powered by Tiptap v2 with extensive formatting and block capabilities.
13
+ - **Full Rich Text Power**: Powered by Tiptap with extensive formatting and block capabilities.
11
14
  - **Modern UX (Notion-like)**: Intuitive slash commands and bubble menus for a keyboard-first experience.
12
15
  - **Highly Customizable**: Easily configure toolbars, bubble menus, and slash command items.
13
16
  - **Signal-Based Reactivity**: Pure Signal architecture natively compatible with `ChangeDetectionStrategy.OnPush`.
@@ -16,6 +19,9 @@ A modern, customizable rich-text editor for Angular applications, built with Tip
16
19
  - **Built-in i18n**: English & French support with a reactive, extensible locale system.
17
20
  - **Word/Character Count**: Real-time statistics with proper pluralization support.
18
21
  - **Office-Ready**: Cleaned-up pasting from Microsoft Word and Excel to maintain layout integrity.
22
+ - **Seamless Angular Integration**: Use a single `provideAteEditor()` to initialize the library and share a root injector across all nodes.
23
+ - **Universal Component Embedding**: Embed _any_ Angular component (library or custom) directly into the editor as a TipTap node.
24
+ - **Global Configuration**: Set application-wide defaults for themes, toolbars, and features with hierarchical inheritance.
19
25
  - **Service Driven**: Deep programmatic control via `AteEditorCommandsService` and isolated instances.
20
26
  - **A11y First**: Built with accessibility best practices and full keyboard navigation.
21
27
 
@@ -51,7 +57,7 @@ Add the required CSS to your `angular.json` file in the `styles` array:
51
57
  "styles": [
52
58
  ...
53
59
  "node_modules/@fontsource/material-symbols-outlined/index.css",
54
- "node_modules/@flogeez/angular-tiptap-editor/src/lib/styles/index.css",
60
+ "node_modules/@flogeez/angular-tiptap-editor/styles/index.css",
55
61
  ...
56
62
  ]
57
63
  }
@@ -138,37 +144,7 @@ export class AdvancedComponent {
138
144
  }
139
145
  ```
140
146
 
141
- ### 3. Registering Custom Extensions
142
-
143
- Easily extend the editor with any standard Tiptap extension or your own custom marks/nodes via the `tiptapExtensions` input.
144
-
145
- ```typescript
146
- import { Component } from "@angular/core";
147
- import { AngularTiptapEditorComponent } from "@flogeez/angular-tiptap-editor";
148
-
149
- @Component({
150
- selector: "app-custom-extensions",
151
- standalone: true,
152
- imports: [AngularTiptapEditorComponent],
153
- template: `
154
- <angular-tiptap-editor
155
- [content]="content"
156
- [tiptapExtensions]="extensions"
157
- (contentChange)="content = $event" />
158
- `,
159
- })
160
- export class CustomExtensionsComponent {
161
- content = "<p>Custom extensions example</p>";
162
-
163
- extensions = [
164
- // Add your custom TipTap extensions here
165
- // Example: Custom extension configuration
166
- // MyCustomExtension.configure({ /* options */ })
167
- ];
168
- }
169
- ```
170
-
171
- ### 4. With Form Integration
147
+ ### 3. With Form Integration
172
148
 
173
149
  ```typescript
174
150
  import { Component } from "@angular/core";
@@ -183,9 +159,7 @@ import { AngularTiptapEditorComponent } from "@flogeez/angular-tiptap-editor";
183
159
  <form>
184
160
  <angular-tiptap-editor
185
161
  [formControl]="contentControl"
186
- placeholder="Enter your content here..."
187
- [showCharacterCount]="true"
188
- [showWordCount]="true" />
162
+ placeholder="Enter your content here..." />
189
163
  <button type="submit">Submit</button>
190
164
  </form>
191
165
  `,
@@ -195,25 +169,90 @@ export class FormComponent {
195
169
  }
196
170
  ```
197
171
 
198
- ### 5. Using EditorCommandsService
172
+ ## ⚙️ Advanced Setup & Extensions
173
+
174
+ ### 1. Global Setup (Recommended)
175
+
176
+ Initialize the library globally in your `app.config.ts` or `main.ts` to capture the root injector and set application-wide defaults.
177
+
178
+ ```typescript
179
+ import { ApplicationConfig } from "@angular/core";
180
+ import { provideAteEditor } from "@flogeez/angular-tiptap-editor";
181
+
182
+ export const appConfig: ApplicationConfig = {
183
+ providers: [
184
+ provideAteEditor({
185
+ theme: "auto",
186
+ mode: "seamless",
187
+ tiptapExtensions: [
188
+ /* Global TipTap Extensions */
189
+ ],
190
+ stateCalculators: [
191
+ /* Global State Calculators */
192
+ ],
193
+ }),
194
+ ],
195
+ };
196
+ ```
197
+
198
+ ### 2. Embedding Angular Components (Angular Nodes)
199
+
200
+ Turn any Angular component into a TipTap node without writing extension code. This project makes it easy to map your existing Angular components directly to the editor's document structure.
201
+
202
+ ```typescript
203
+ import { Component } from "@angular/core";
204
+ import {
205
+ AngularTiptapEditorComponent,
206
+ AteEditorConfig,
207
+ AteAngularNode,
208
+ } from "@flogeez/angular-tiptap-editor";
209
+ import { MyCounterComponent } from "./my-counter.component";
210
+
211
+ @Component({
212
+ selector: "app-custom-nodes",
213
+ standalone: true,
214
+ imports: [AngularTiptapEditorComponent],
215
+ template: ` <angular-tiptap-editor [config]="editorConfig" /> `,
216
+ })
217
+ export class CustomNodesComponent {
218
+ // Use AteAngularNode for explicit typing if needed
219
+ myNodes: AteAngularNode[] = [
220
+ {
221
+ component: MyCounterComponent,
222
+ name: "counter",
223
+ attributes: { count: { default: 0 } },
224
+ group: "block",
225
+ draggable: true,
226
+ },
227
+ ];
228
+
229
+ editorConfig: AteEditorConfig = {
230
+ angularNodes: this.myNodes,
231
+ };
232
+ }
233
+ ```
234
+
235
+ > **Note**: Your component can inherit from `AteAngularNodeView` to access the full TipTap API (`editor`, `node`, `updateAttributes`) via Signals!
236
+
237
+ ### 3. Using EditorCommandsService
238
+
239
+ Deep programmatic control over any editor instance.
199
240
 
200
241
  ```typescript
201
242
  import { Component, inject } from "@angular/core";
202
243
  import { AteEditorCommandsService } from "@flogeez/angular-tiptap-editor";
244
+ import { Editor } from "@tiptap/core";
203
245
 
204
246
  @Component({
205
247
  selector: "app-commands",
206
248
  standalone: true,
207
249
  template: `
208
- <div>
209
- <div class="controls">
210
- <button (click)="clearContent()">Clear Content</button>
211
- <button (click)="focusEditor()">Focus Editor</button>
212
- <button (click)="setContent()">Set Content</button>
213
- </div>
214
-
215
- <angular-tiptap-editor (editorCreated)="onEditorCreated($event)" />
250
+ <div class="controls">
251
+ <button (click)="clearContent()">Clear</button>
252
+ <button (click)="focusEditor()">Focus</button>
253
+ <button (click)="setContent()">Set Content</button>
216
254
  </div>
255
+ <angular-tiptap-editor (editorCreated)="onEditorCreated($event)" />
217
256
  `,
218
257
  })
219
258
  export class CommandsComponent {
@@ -225,72 +264,87 @@ export class CommandsComponent {
225
264
  }
226
265
 
227
266
  clearContent() {
228
- if (this.editor) {
229
- this.editorCommandsService.clearContent(this.editor);
230
- }
267
+ if (this.editor) this.editorCommandsService.clearContent(this.editor);
231
268
  }
232
269
 
233
270
  focusEditor() {
234
- if (this.editor) {
235
- this.editorCommandsService.focus(this.editor);
236
- }
271
+ if (this.editor) this.editorCommandsService.focus(this.editor);
237
272
  }
238
273
 
239
274
  setContent() {
240
- if (this.editor) {
241
- this.editorCommandsService.setContent(this.editor, "<h1>New Content</h1>");
242
- }
275
+ if (this.editor) this.editorCommandsService.setContent(this.editor, "<h1>New!</h1>");
243
276
  }
244
277
  }
245
278
  ```
246
279
 
247
- ### 6. Extending Reactive Editor State
280
+ ### 4. Custom Tiptap Extensions (Low Level)
248
281
 
249
- The editor features a dual-layer state architecture: **Automatic Tracking** for simple extensions and **Custom Calculators** for advanced needs.
282
+ Standard TipTap extensions can be passed via the `tiptapExtensions` property in your config.
283
+
284
+ ```typescript
285
+ import { AteEditorConfig } from "@flogeez/angular-tiptap-editor";
286
+
287
+ @Component({
288
+ template: ` <angular-tiptap-editor [config]="editorConfig" /> `,
289
+ })
290
+ export class CustomExtensionsComponent {
291
+ editorConfig: AteEditorConfig = {
292
+ tiptapExtensions: [
293
+ /* Standard TipTap extensions (Highlight, Link, etc.) */
294
+ ],
295
+ };
296
+ }
297
+ ```
298
+
299
+ ### 5. Extending Reactive Editor State (Calculators)
300
+
301
+ The editor features a dual-layer state architecture for maximum reactivity.
250
302
 
251
303
  #### A. Automatic Extension Tracking (Zero Config)
252
304
 
253
- Any TipTap **Mark** or **Node** you add to `tiptapExtensions` is automatically tracked by our `DiscoveryCalculator`. You don't need to write any extra code to make them reactive.
305
+ Any TipTap **Mark** or **Node** you add to `tiptapExtensions` is automatically tracked. You don't need extra code to make them reactive.
254
306
 
255
- - **For Marks**: `state().marks.yourExtensionName` (boolean) and `state().can.toggleYourExtensionName` (boolean).
307
+ - **For Marks**: `state().marks.yourExtensionName` (boolean).
256
308
  - **For Nodes**: `state().nodes.yourExtensionName` (boolean).
257
309
 
258
310
  #### B. Custom State Calculators (Advanced)
259
311
 
260
- If you need to extract complex data (like attributes, depth, or custom logic), you can provide a custom `StateCalculator`.
312
+ Extract complex data (attributes, depth, custom logic) via specialized Calculators.
261
313
 
262
- 1. **Define a Calculator**:
314
+ **1. Define a Calculator**:
263
315
 
264
316
  ```typescript
265
317
  import { AteStateCalculator } from "@flogeez/angular-tiptap-editor";
266
318
 
267
- // This function will be called on every editor update
268
- export const MyCustomCalculator: AteStateCalculator = editor => {
269
- return {
270
- custom: {
271
- hasHighPriority: editor.isActive("priority"),
272
- selectionDepth: editor.state.selection.$from.depth,
273
- // Any data you need...
274
- },
275
- };
276
- };
319
+ // Called on every editor update
320
+ export const MyCustomCalculator: AteStateCalculator = editor => ({
321
+ custom: { selectionDepth: editor.state.selection.$from.depth },
322
+ });
277
323
  ```
278
324
 
279
- 2. **Register it in the Template**:
325
+ **2. Register in the Config**:
326
+
327
+ ```typescript
328
+ import { AteEditorConfig } from "@flogeez/angular-tiptap-editor";
329
+
330
+ editorConfig: AteEditorConfig = {
331
+ stateCalculators: [MyCustomCalculator],
332
+ };
333
+ ```
280
334
 
281
335
  ```html
282
- <angular-tiptap-editor [stateCalculators]="[MyCustomCalculator]" />
336
+ <angular-tiptap-editor [config]="editorConfig" />
283
337
  ```
284
338
 
285
- 3. **Consume it anywhere**:
339
+ **3. Consume the State**:
286
340
 
287
341
  ```typescript
288
342
  @Component({ ... })
289
343
  export class MyToolbarComponent {
290
344
  private editorCommands = inject(AteEditorCommandsService);
291
345
 
292
- // Access your custom data reactively!
293
- isHighPriority = computed(() => this.editorCommands.editorState().custom?.hasHighPriority);
346
+ // Access your custom data reactively via Signals!
347
+ depth = computed(() => this.editorCommands.editorState().custom?.selectionDepth);
294
348
  }
295
349
  ```
296
350
 
@@ -676,20 +730,6 @@ The library exposes a reactive `editorState` signal via the `AteEditorCommandsSe
676
730
 
677
731
  Since it's built with Signals, your custom toolbar items or UI overlays will only re-render when the specific data they consume changes, making it extremely efficient for `OnPush` applications.
678
732
 
679
- ---
680
-
681
- ### 🧩 Custom Tiptap Extensions
682
-
683
- You are not limited to the built-in extensions. Pass any Tiptap extension, mark, or node:
684
-
685
- ```html
686
- <angular-tiptap-editor [tiptapExtensions]="[MyCustomExtension]" />
687
- ```
688
-
689
- Any custom extension is automatically detected and its state (active/can) is added to the reactive `editorState` snapshot.
690
-
691
- ---
692
-
693
733
  ## 🏗️ Architecture
694
734
 
695
735
  ### Reactive State Management
@@ -776,9 +816,8 @@ Contributions are welcome! Please feel free to submit a Pull Request.
776
816
 
777
817
  ### Latest Updates
778
818
 
779
- - ✅ **Unified Configuration**: New unified `AteEditorConfig` system for cleaner, type-safe editor setup.
780
- - ✅ **Enhanced Image Upload**: Advanced image handling with custom upload handlers and auto-compression.
781
- - ✅ **Refactored Link Management**: Dedicated link bubble menu with smart UI anchoring and real-time URL sync.
819
+ - ✅ **Seamless Integration**: Drastically simplified setup with `provideAteEditor()` and declarative `nodeViews`.
820
+ - ✅ **Universal Component Engine**: Embed any Angular component as an editor node.
782
821
 
783
822
  ---
784
823