@flogeez/angular-tiptap-editor 2.3.0 → 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 +14 -0
- package/README.md +132 -93
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +1225 -1114
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/index.d.ts +265 -154
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,20 @@ 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
|
+
|
|
8
22
|
## [2.3.0] - 2026-01-28
|
|
9
23
|
|
|
10
24
|
### 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
|
|
3
|
+
A modern, customizable rich-text editor for Angular, built with Tiptap.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@flogeez/angular-tiptap-editor) [](https://flogeez.github.io/angular-tiptap-editor/) [](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
|
|
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/
|
|
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.
|
|
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
|
-
|
|
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
|
-
<
|
|
210
|
-
|
|
211
|
-
|
|
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
|
-
###
|
|
280
|
+
### 4. Custom Tiptap Extensions (Low Level)
|
|
248
281
|
|
|
249
|
-
|
|
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
|
|
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)
|
|
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
|
-
|
|
312
|
+
Extract complex data (attributes, depth, custom logic) via specialized Calculators.
|
|
261
313
|
|
|
262
|
-
1.
|
|
314
|
+
**1. Define a Calculator**:
|
|
263
315
|
|
|
264
316
|
```typescript
|
|
265
317
|
import { AteStateCalculator } from "@flogeez/angular-tiptap-editor";
|
|
266
318
|
|
|
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
|
-
};
|
|
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.
|
|
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 [
|
|
336
|
+
<angular-tiptap-editor [config]="editorConfig" />
|
|
283
337
|
```
|
|
284
338
|
|
|
285
|
-
3.
|
|
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
|
-
|
|
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
|
-
- ✅ **
|
|
780
|
-
- ✅ **
|
|
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
|
|