@flogeez/angular-tiptap-editor 2.3.0 → 3.0.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,36 @@ 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
+ ## [3.0.0] - 2026-02-05
9
+
10
+ ### Changed
11
+
12
+ - **Upgrade to Tiptap v3**: Full migration from Tiptap v2 to v3, aligning with the latest stable ecosystem.
13
+ - **Consolidated Dependencies**: Transitioned to the unified `@tiptap/extensions` package instead of individual packages, simplifying dependency management and improving performance.
14
+ - **Refined Configuration Hierarchy**: Implemented a more intuitive configuration cascade: **Component Inputs > [config] Object > Global Configuration > Defaults**. Direct inputs now have absolute priority for better DX.
15
+ - **Flexible Height Types**: `height`, `minHeight`, and `maxHeight` inputs now accept both `number` (pixels) and `string` (CSS values like '80vh') interchangeably.
16
+
17
+ ### Breaking Changes
18
+
19
+ - **Peer Dependencies**: The library now requires `@tiptap/core`, `@tiptap/pm`, and associated extensions to be at version `^3.0.0`.
20
+ - **Input Defaults**: All optional component inputs (except `content`) now default to `undefined` to allow proper inheritance from global or instance-level configurations.
21
+ - **Removal of Deprecated Aliases**: Definitive removal of legacy exported names (without the `Ate` prefix) that were deprecated in v2.2.0.
22
+ - **Office Paste**: Updated `@intevation/tiptap-extension-office-paste` to `^0.1.2` for Tiptap v3 compatibility.
23
+
24
+ ## [2.4.0] - 2026-01-29
25
+
26
+ ### Added
27
+
28
+ - **Seamless Angular Integration**: Drastically simplified editor setup and component registration.
29
+ - **Global Provider**: Added `provideAteEditor()` for automatic injector capture and application-wide configuration defaults.
30
+ - **Declarative Angular Nodes**: Support for registering Angular components directly within the `angularNodes` configuration property.
31
+ - **Exhaustive Configuration**: All editor inputs (extensions, options, state calculators) are now part of `AteEditorConfig` for centralized management.
32
+ - **Config Inheritance**: Intelligent merging of global, instance, and input-level configurations.
33
+
34
+ ### Fixed
35
+
36
+ - **NodeView Stability**: Enhanced initialization and lifecycle management for embedded Angular components.
37
+
8
38
  ## [2.3.0] - 2026-01-28
9
39
 
10
40
  ### Added
package/README.md CHANGED
@@ -1,13 +1,19 @@
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
+ > [!IMPORTANT]
4
+ > **New Version Available**: v3.0.0 uses Tiptap v3. If you need to stay on Tiptap v2, please use version `^2.4.0`.
5
+
6
+ A modern, customizable rich-text editor for Angular, built with Tiptap.
4
7
 
5
8
  [![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
9
 
10
+ 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.
11
+ 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.
12
+
7
13
  ## 🚀 Features
8
14
 
9
15
  - **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.
16
+ - **Full Rich Text Power**: Powered by Tiptap with extensive formatting and block capabilities.
11
17
  - **Modern UX (Notion-like)**: Intuitive slash commands and bubble menus for a keyboard-first experience.
12
18
  - **Highly Customizable**: Easily configure toolbars, bubble menus, and slash command items.
13
19
  - **Signal-Based Reactivity**: Pure Signal architecture natively compatible with `ChangeDetectionStrategy.OnPush`.
@@ -16,6 +22,9 @@ A modern, customizable rich-text editor for Angular applications, built with Tip
16
22
  - **Built-in i18n**: English & French support with a reactive, extensible locale system.
17
23
  - **Word/Character Count**: Real-time statistics with proper pluralization support.
18
24
  - **Office-Ready**: Cleaned-up pasting from Microsoft Word and Excel to maintain layout integrity.
25
+ - **Seamless Angular Integration**: Use a single `provideAteEditor()` to initialize the library and share a root injector across all nodes.
26
+ - **Universal Component Embedding**: Embed _any_ Angular component (library or custom) directly into the editor as a TipTap node.
27
+ - **Global Configuration**: Set application-wide defaults for themes, toolbars, and features with hierarchical inheritance.
19
28
  - **Service Driven**: Deep programmatic control via `AteEditorCommandsService` and isolated instances.
20
29
  - **A11y First**: Built with accessibility best practices and full keyboard navigation.
21
30
 
@@ -51,7 +60,7 @@ Add the required CSS to your `angular.json` file in the `styles` array:
51
60
  "styles": [
52
61
  ...
53
62
  "node_modules/@fontsource/material-symbols-outlined/index.css",
54
- "node_modules/@flogeez/angular-tiptap-editor/src/lib/styles/index.css",
63
+ "node_modules/@flogeez/angular-tiptap-editor/styles/index.css",
55
64
  ...
56
65
  ]
57
66
  }
@@ -138,37 +147,7 @@ export class AdvancedComponent {
138
147
  }
139
148
  ```
140
149
 
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
150
+ ### 3. With Form Integration
172
151
 
173
152
  ```typescript
174
153
  import { Component } from "@angular/core";
@@ -183,9 +162,7 @@ import { AngularTiptapEditorComponent } from "@flogeez/angular-tiptap-editor";
183
162
  <form>
184
163
  <angular-tiptap-editor
185
164
  [formControl]="contentControl"
186
- placeholder="Enter your content here..."
187
- [showCharacterCount]="true"
188
- [showWordCount]="true" />
165
+ placeholder="Enter your content here..." />
189
166
  <button type="submit">Submit</button>
190
167
  </form>
191
168
  `,
@@ -195,25 +172,90 @@ export class FormComponent {
195
172
  }
196
173
  ```
197
174
 
198
- ### 5. Using EditorCommandsService
175
+ ## ⚙️ Advanced Setup & Extensions
176
+
177
+ ### 1. Global Setup (Recommended)
178
+
179
+ Initialize the library globally in your `app.config.ts` or `main.ts` to capture the root injector and set application-wide defaults.
180
+
181
+ ```typescript
182
+ import { ApplicationConfig } from "@angular/core";
183
+ import { provideAteEditor } from "@flogeez/angular-tiptap-editor";
184
+
185
+ export const appConfig: ApplicationConfig = {
186
+ providers: [
187
+ provideAteEditor({
188
+ theme: "auto",
189
+ mode: "seamless",
190
+ tiptapExtensions: [
191
+ /* Global TipTap Extensions */
192
+ ],
193
+ stateCalculators: [
194
+ /* Global State Calculators */
195
+ ],
196
+ }),
197
+ ],
198
+ };
199
+ ```
200
+
201
+ ### 2. Embedding Angular Components (Angular Nodes)
202
+
203
+ 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.
204
+
205
+ ```typescript
206
+ import { Component } from "@angular/core";
207
+ import {
208
+ AngularTiptapEditorComponent,
209
+ AteEditorConfig,
210
+ AteAngularNode,
211
+ } from "@flogeez/angular-tiptap-editor";
212
+ import { MyCounterComponent } from "./my-counter.component";
213
+
214
+ @Component({
215
+ selector: "app-custom-nodes",
216
+ standalone: true,
217
+ imports: [AngularTiptapEditorComponent],
218
+ template: ` <angular-tiptap-editor [config]="editorConfig" /> `,
219
+ })
220
+ export class CustomNodesComponent {
221
+ // Use AteAngularNode for explicit typing if needed
222
+ myNodes: AteAngularNode[] = [
223
+ {
224
+ component: MyCounterComponent,
225
+ name: "counter",
226
+ attributes: { count: { default: 0 } },
227
+ group: "block",
228
+ draggable: true,
229
+ },
230
+ ];
231
+
232
+ editorConfig: AteEditorConfig = {
233
+ angularNodes: this.myNodes,
234
+ };
235
+ }
236
+ ```
237
+
238
+ > **Note**: Your component can inherit from `AteAngularNodeView` to access the full TipTap API (`editor`, `node`, `updateAttributes`) via Signals!
239
+
240
+ ### 3. Using EditorCommandsService
241
+
242
+ Deep programmatic control over any editor instance.
199
243
 
200
244
  ```typescript
201
245
  import { Component, inject } from "@angular/core";
202
246
  import { AteEditorCommandsService } from "@flogeez/angular-tiptap-editor";
247
+ import { Editor } from "@tiptap/core";
203
248
 
204
249
  @Component({
205
250
  selector: "app-commands",
206
251
  standalone: true,
207
252
  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)" />
253
+ <div class="controls">
254
+ <button (click)="clearContent()">Clear</button>
255
+ <button (click)="focusEditor()">Focus</button>
256
+ <button (click)="setContent()">Set Content</button>
216
257
  </div>
258
+ <angular-tiptap-editor (editorCreated)="onEditorCreated($event)" />
217
259
  `,
218
260
  })
219
261
  export class CommandsComponent {
@@ -225,72 +267,87 @@ export class CommandsComponent {
225
267
  }
226
268
 
227
269
  clearContent() {
228
- if (this.editor) {
229
- this.editorCommandsService.clearContent(this.editor);
230
- }
270
+ if (this.editor) this.editorCommandsService.clearContent(this.editor);
231
271
  }
232
272
 
233
273
  focusEditor() {
234
- if (this.editor) {
235
- this.editorCommandsService.focus(this.editor);
236
- }
274
+ if (this.editor) this.editorCommandsService.focus(this.editor);
237
275
  }
238
276
 
239
277
  setContent() {
240
- if (this.editor) {
241
- this.editorCommandsService.setContent(this.editor, "<h1>New Content</h1>");
242
- }
278
+ if (this.editor) this.editorCommandsService.setContent(this.editor, "<h1>New!</h1>");
243
279
  }
244
280
  }
245
281
  ```
246
282
 
247
- ### 6. Extending Reactive Editor State
283
+ ### 4. Custom Tiptap Extensions (Low Level)
284
+
285
+ Standard TipTap extensions can be passed via the `tiptapExtensions` property in your config.
286
+
287
+ ```typescript
288
+ import { AteEditorConfig } from "@flogeez/angular-tiptap-editor";
289
+
290
+ @Component({
291
+ template: ` <angular-tiptap-editor [config]="editorConfig" /> `,
292
+ })
293
+ export class CustomExtensionsComponent {
294
+ editorConfig: AteEditorConfig = {
295
+ tiptapExtensions: [
296
+ /* Standard TipTap extensions (Highlight, Link, etc.) */
297
+ ],
298
+ };
299
+ }
300
+ ```
301
+
302
+ ### 5. Extending Reactive Editor State (Calculators)
248
303
 
249
- The editor features a dual-layer state architecture: **Automatic Tracking** for simple extensions and **Custom Calculators** for advanced needs.
304
+ The editor features a dual-layer state architecture for maximum reactivity.
250
305
 
251
306
  #### A. Automatic Extension Tracking (Zero Config)
252
307
 
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.
308
+ Any TipTap **Mark** or **Node** you add to `tiptapExtensions` is automatically tracked. You don't need extra code to make them reactive.
254
309
 
255
- - **For Marks**: `state().marks.yourExtensionName` (boolean) and `state().can.toggleYourExtensionName` (boolean).
310
+ - **For Marks**: `state().marks.yourExtensionName` (boolean).
256
311
  - **For Nodes**: `state().nodes.yourExtensionName` (boolean).
257
312
 
258
313
  #### B. Custom State Calculators (Advanced)
259
314
 
260
- If you need to extract complex data (like attributes, depth, or custom logic), you can provide a custom `StateCalculator`.
315
+ Extract complex data (attributes, depth, custom logic) via specialized Calculators.
261
316
 
262
- 1. **Define a Calculator**:
317
+ **1. Define a Calculator**:
263
318
 
264
319
  ```typescript
265
320
  import { AteStateCalculator } from "@flogeez/angular-tiptap-editor";
266
321
 
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
- };
322
+ // Called on every editor update
323
+ export const MyCustomCalculator: AteStateCalculator = editor => ({
324
+ custom: { selectionDepth: editor.state.selection.$from.depth },
325
+ });
277
326
  ```
278
327
 
279
- 2. **Register it in the Template**:
328
+ **2. Register in the Config**:
329
+
330
+ ```typescript
331
+ import { AteEditorConfig } from "@flogeez/angular-tiptap-editor";
332
+
333
+ editorConfig: AteEditorConfig = {
334
+ stateCalculators: [MyCustomCalculator],
335
+ };
336
+ ```
280
337
 
281
338
  ```html
282
- <angular-tiptap-editor [stateCalculators]="[MyCustomCalculator]" />
339
+ <angular-tiptap-editor [config]="editorConfig" />
283
340
  ```
284
341
 
285
- 3. **Consume it anywhere**:
342
+ **3. Consume the State**:
286
343
 
287
344
  ```typescript
288
345
  @Component({ ... })
289
346
  export class MyToolbarComponent {
290
347
  private editorCommands = inject(AteEditorCommandsService);
291
348
 
292
- // Access your custom data reactively!
293
- isHighPriority = computed(() => this.editorCommands.editorState().custom?.hasHighPriority);
349
+ // Access your custom data reactively via Signals!
350
+ depth = computed(() => this.editorCommands.editorState().custom?.selectionDepth);
294
351
  }
295
352
  ```
296
353
 
@@ -676,20 +733,6 @@ The library exposes a reactive `editorState` signal via the `AteEditorCommandsSe
676
733
 
677
734
  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
735
 
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
736
  ## 🏗️ Architecture
694
737
 
695
738
  ### Reactive State Management
@@ -776,9 +819,8 @@ Contributions are welcome! Please feel free to submit a Pull Request.
776
819
 
777
820
  ### Latest Updates
778
821
 
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.
822
+ - ✅ **Seamless Integration**: Drastically simplified setup with `provideAteEditor()` and declarative `nodeViews`.
823
+ - ✅ **Universal Component Engine**: Embed any Angular component as an editor node.
782
824
 
783
825
  ---
784
826