@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 +30 -0
- package/README.md +135 -93
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +992 -840
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/index.d.ts +303 -263
- package/package.json +13 -21
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
|
-
|
|
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
|
[](https://www.npmjs.com/package/@flogeez/angular-tiptap-editor) [](https://flogeez.github.io/angular-tiptap-editor/) [](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
|
|
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/
|
|
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.
|
|
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
|
-
|
|
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
|
-
<
|
|
210
|
-
|
|
211
|
-
|
|
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
|
-
###
|
|
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
|
|
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
|
|
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)
|
|
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
|
-
|
|
315
|
+
Extract complex data (attributes, depth, custom logic) via specialized Calculators.
|
|
261
316
|
|
|
262
|
-
1.
|
|
317
|
+
**1. Define a Calculator**:
|
|
263
318
|
|
|
264
319
|
```typescript
|
|
265
320
|
import { AteStateCalculator } from "@flogeez/angular-tiptap-editor";
|
|
266
321
|
|
|
267
|
-
//
|
|
268
|
-
export const MyCustomCalculator: AteStateCalculator = editor => {
|
|
269
|
-
|
|
270
|
-
|
|
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.
|
|
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 [
|
|
339
|
+
<angular-tiptap-editor [config]="editorConfig" />
|
|
283
340
|
```
|
|
284
341
|
|
|
285
|
-
3.
|
|
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
|
-
|
|
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
|
-
- ✅ **
|
|
780
|
-
- ✅ **
|
|
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
|
|