@flogeez/angular-tiptap-editor 0.5.4 → 2.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 +61 -0
- package/LICENSE +1 -1
- package/README.md +203 -122
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +3978 -3264
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/index.d.ts +342 -99
- package/package.json +1 -1
- package/src/lib/styles/bubble-menu.global.css +10 -4
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,67 @@ 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).
|
|
7
7
|
|
|
8
|
+
## [0.7.0] - 2026-01-17
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Extensible I18n**: The translation system is now open. You can add any language (e.g., `es`, `it`) via `addTranslations()`, and the `SupportedLocale` type now accepts any string with autocomplete for default languages.
|
|
12
|
+
- **Per-Instance I18n Override**: Added ability to define a specific language for a given editor instance via the `[locale]` input, without affecting the global language of other editors.
|
|
13
|
+
- **Global I18n Singleton**: The translation service is now a global singleton (`providedIn: 'root'`), allowing for application-wide language switching with a single call.
|
|
14
|
+
- **Seamless Mode**: Added `[seamless]` input to remove borders, backgrounds, and paddings.
|
|
15
|
+
- **Floating Toolbar**: Added `[floatingToolbar]` option for a sticky, auto-hiding toolbar with glassmorphism that only appears on focus or hover.
|
|
16
|
+
- **Improved Read-Only**: Refined the `[editable]="false"` behavior. Clicking in the empty space of a read-only editor no longer forces focus or moves the cursor. The toolbar and footer now correctly reflect the read-only state.
|
|
17
|
+
- **Code Block Support**: Added dedicated `CodeBlock` button to the toolbar and slash commands.
|
|
18
|
+
- **Precise Inline Code**: Separated "Inline Code" and "Code Block" in menus and translations for better clarity.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
- **Inline Code Toggle**: Fixed a reactivity bug where the "Code" button in the toolbar became disabled when already inside a code mark, preventing it from being toggled off.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- **Service Isolation**: `EditorCommandsService`, `LinkService`, `ColorPickerService`, and `ImageService` are no longer global (`root`). They are now provided at the component level for each editor instance, ensuring perfect isolation in multi-editor scenarios.
|
|
25
|
+
- **Internal Refactoring**: Systemic use of `currentTranslations` (computed signal) across all internal components for perfect reactivity to language changes.
|
|
26
|
+
|
|
27
|
+
### Breaking Changes
|
|
28
|
+
- **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`).
|
|
29
|
+
|
|
30
|
+
## [0.6.0] - 2026-01-14
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
- **Reactive State Management**: New "Snapshot & Signal" architecture with optimized change detection (OnPush).
|
|
34
|
+
- **Custom Extension Tracking**: Automatic state tracking for custom Tiptap Marks and Nodes (zero-config).
|
|
35
|
+
- **Extensible State**: New `stateCalculators` input to inject custom logic into the reactive editor state.
|
|
36
|
+
- **Intelligent Color Detection**: The editor state now computes the actual visible text and background colors by inspecting the DOM (computed styles). This ensures the color picker accurately reflects the current formatting even when derived from CSS themes or inherited from parent elements.
|
|
37
|
+
- **Link & Color Bubble Menus**: Completely refactored management with dedicated bubble menus.
|
|
38
|
+
- **LinkService**: New dedicated service to manage link state and lifecycle independently.
|
|
39
|
+
- **Improved Visual Feedback**: Menus now preserve the editor's blue selection highlight while choosing colors or preparing to type a link.
|
|
40
|
+
- **Improved Image Selection**: Automatic node selection after insertion or replacement, ensuring resize handles and bubble menus appear instantly.
|
|
41
|
+
- **Danger Button Variant**: New `danger` variant for actions like "Reset Color" or "Remove Link", providing clear visual feedback for destructive operations.
|
|
42
|
+
|
|
43
|
+
### Fixed
|
|
44
|
+
- **Multi-instance Support**: Full service isolation, allowing multiple editors on the same page without shared state.
|
|
45
|
+
- **Bubble Menu Conflicts**: Fixed overlapping menus by implementing a strict priority system (specialized menus now hide the main text menu).
|
|
46
|
+
- **Image Bubble Menu Persistence**: Corrected Tippy.js behavior to prevent menus from disappearing when re-clicking an already-selected image.
|
|
47
|
+
- **Toolbar-Menu Harmony**: Bubbles now reactively hide when interacting with the main toolbar via a centralized signal.
|
|
48
|
+
- **Anti-Echo Loop**: Implemented a robust "lastEmittedHtml" logic combined with `untracked()` to prevent infinite loops and cursor reset when using two-way binding or FormControls.
|
|
49
|
+
- **Atomic Image Replacement**: Refactored image service to perform atomic updates, fixing the "extra space" bug and preventing layout shifts during asynchronous uploads.
|
|
50
|
+
|
|
51
|
+
### Changed
|
|
52
|
+
- **Architectural Refactoring**: `EditorCommandsService` is now a clean facade/proxy for specialized services (`ImageService`, `ColorPickerService`, `LinkService`).
|
|
53
|
+
- **Optimized State Performance**: Refactored state calculators (notably `MarksCalculator`) to minimize DOM access and avoid unnecessary layout recalculations (reflow).
|
|
54
|
+
- **Centralized Color Utilities**: Consolidated color normalization, luminance, and contrast calculations into a shared utility for perfect consistency.
|
|
55
|
+
- **Public API Cleanup**: Exported all modular calculators, services, and models for better extensibility.
|
|
56
|
+
- **Color Picker Stability**: Integrated selection capture and locked modes to ensure 100% reliability in color application.
|
|
57
|
+
|
|
58
|
+
## [0.5.5] - 2026-01-09
|
|
59
|
+
|
|
60
|
+
### Added
|
|
61
|
+
- **Bubble Menus Confinement**: Menus now properly respect the editor's boundaries and are clipped by the container when scrolling, specifically optimized for `fillContainer` mode.
|
|
62
|
+
- **Unified Command Execution**: Centralized all editor operations within `EditorCommandsService`, ensuring consistent behavior between the toolbar and bubble menus.
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
- **Bubble Menus Positionning**: Refactored positioning logic for all bubble menus (Text, Image, Table, Cell, Slash) using Tippy's `sticky` plugin for real-time tracking during resizing and scrolling.
|
|
66
|
+
- **Bubble Menus Performances**: Significant performance boost in `getImageRect` and `getTableRect` using direct ProseMirror DOM lookups.
|
|
67
|
+
- **Performance Optimization**: Implemented `ChangeDetectionStrategy.OnPush` across all library components to minimize change detection cycles. Improved resource management by enabling Tippy's sticky polling only while menus are visible.
|
|
68
|
+
|
|
8
69
|
## [0.5.4] - 2026-01-08
|
|
9
70
|
|
|
10
71
|
### Added
|
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -6,19 +6,35 @@ A modern, customizable rich-text editor for Angular applications, built with Tip
|
|
|
6
6
|
|
|
7
7
|
## 🚀 Features
|
|
8
8
|
|
|
9
|
-
- **Modern Angular**: Built with Angular 18+
|
|
10
|
-
- **Rich Text
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
17
|
-
- **Word/Character Count**: Real-time
|
|
18
|
-
- **Office
|
|
19
|
-
- **
|
|
20
|
-
- **
|
|
21
|
-
|
|
9
|
+
- **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.
|
|
11
|
+
- **Modern UX (Notion-like)**: Intuitive slash commands and bubble menus for a keyboard-first experience.
|
|
12
|
+
- **Highly Customizable**: Easily configure toolbars, bubble menus, and slash command items.
|
|
13
|
+
- **Signal-Based Reactivity**: Pure Signal architecture natively compatible with `ChangeDetectionStrategy.OnPush`.
|
|
14
|
+
- **Advanced Table Support**: Full table management with cell selection and context-aware bubble menus.
|
|
15
|
+
- **Professional Media**: Advanced image handling with resizing, auto-compression, and custom uploaders.
|
|
16
|
+
- **Built-in i18n**: English & French support with a reactive, extensible locale system.
|
|
17
|
+
- **Word/Character Count**: Real-time statistics with proper pluralization support.
|
|
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.
|
|
20
|
+
- **A11y First**: Built with accessibility best practices and full keyboard navigation.
|
|
21
|
+
|
|
22
|
+
## 💎 Why this editor?
|
|
23
|
+
|
|
24
|
+
Most Angular wrappers for Tiptap provide a basic component but leave the heavy lifting to you. **Angular Tiptap Editor** is built to solve common production hurdles:
|
|
25
|
+
|
|
26
|
+
- **True Scalability**: Thanks to **isolated services** provided at the component level, you can host multiple independent editors with different configurations and languages on the same page without a single state leak.
|
|
27
|
+
- **OnPush by Default**: The entire UI (toolbar, menus) is powered by **Angular Signals**. The `editorState` snapshot logic ensures that your components only re-render when necessary, even in complex `OnPush` applications.
|
|
28
|
+
- **Deep i18n & Extensibility**: Not just English/French — you can inject **custom translations** and **custom Tiptap extensions**. Our `DiscoveryCalculator` automatically tracks any new mark or node you add, making them reactive without extra code.
|
|
29
|
+
- **Clean Office UX**: Professional-grade pasting from **Word and Excel** plus smart image handling (auto-compression, resizing handles) ensures a polished experience for end-users.
|
|
30
|
+
|
|
31
|
+
## 🛠️ Extensions included
|
|
32
|
+
|
|
33
|
+
The library comes with a pre-configured set of standard and custom extensions:
|
|
34
|
+
|
|
35
|
+
- **Nodes**: `StarterKit`, `Heading`, `Table`, `Image`, `HorizontalRule`, `CodeBlock`.
|
|
36
|
+
- **Marks**: `Bold`, `Italic`, `Underline`, `Strike`, `Code`, `Link`, `Highlight`, `TextStyle`, `Color`, `Superscript`, `Subscript`.
|
|
37
|
+
- **Utilities**: `Placeholder`, `CharacterCount`, `Typography`, `Focus`, `BubbleMenu`, `Gapcursor`, `Dropcursor`, `ResizableImage` (Custom).
|
|
22
38
|
|
|
23
39
|
## 📦 Installation
|
|
24
40
|
|
|
@@ -114,20 +130,24 @@ export class AdvancedComponent {
|
|
|
114
130
|
};
|
|
115
131
|
|
|
116
132
|
// No config needed if you want all commands enabled
|
|
117
|
-
|
|
133
|
+
slashCommandsConfig = {
|
|
118
134
|
image: true,
|
|
119
135
|
table: true,
|
|
120
136
|
heading1: true
|
|
121
137
|
};
|
|
122
138
|
|
|
139
|
+
// Available keys: "heading1", "heading2", "heading3", "bulletList",
|
|
140
|
+
// "orderedList", "blockquote", "code", "image", "horizontalRule", "table"
|
|
141
|
+
|
|
123
142
|
onContentChange(newContent: string) {
|
|
124
143
|
this.content = newContent;
|
|
125
144
|
}
|
|
126
145
|
}
|
|
127
146
|
```
|
|
128
147
|
|
|
129
|
-
|
|
130
|
-
|
|
148
|
+
### 3. Registering Custom Extensions
|
|
149
|
+
|
|
150
|
+
Easily extend the editor with any standard Tiptap extension or your own custom marks/nodes via the `tiptapExtensions` input.
|
|
131
151
|
|
|
132
152
|
```typescript
|
|
133
153
|
import { Component } from "@angular/core";
|
|
@@ -156,7 +176,7 @@ export class CustomExtensionsComponent {
|
|
|
156
176
|
}
|
|
157
177
|
```
|
|
158
178
|
|
|
159
|
-
###
|
|
179
|
+
### 4. With Form Integration
|
|
160
180
|
|
|
161
181
|
```typescript
|
|
162
182
|
import { Component } from "@angular/core";
|
|
@@ -184,7 +204,7 @@ export class FormComponent {
|
|
|
184
204
|
}
|
|
185
205
|
```
|
|
186
206
|
|
|
187
|
-
###
|
|
207
|
+
### 5. Using EditorCommandsService
|
|
188
208
|
|
|
189
209
|
```typescript
|
|
190
210
|
import { Component, inject } from "@angular/core";
|
|
@@ -195,9 +215,15 @@ import { EditorCommandsService } from "@flogeez/angular-tiptap-editor";
|
|
|
195
215
|
standalone: true,
|
|
196
216
|
template: `
|
|
197
217
|
<div>
|
|
198
|
-
<
|
|
199
|
-
|
|
200
|
-
|
|
218
|
+
<div class="controls">
|
|
219
|
+
<button (click)="clearContent()">Clear Content</button>
|
|
220
|
+
<button (click)="focusEditor()">Focus Editor</button>
|
|
221
|
+
<button (click)="setContent()">Set Content</button>
|
|
222
|
+
</div>
|
|
223
|
+
|
|
224
|
+
<angular-tiptap-editor
|
|
225
|
+
(editorCreated)="onEditorCreated($event)"
|
|
226
|
+
/>
|
|
201
227
|
</div>
|
|
202
228
|
`,
|
|
203
229
|
})
|
|
@@ -232,6 +258,55 @@ export class CommandsComponent {
|
|
|
232
258
|
}
|
|
233
259
|
```
|
|
234
260
|
|
|
261
|
+
### 6. Extending Reactive Editor State
|
|
262
|
+
|
|
263
|
+
The editor features a dual-layer state architecture: **Automatic Tracking** for simple extensions and **Custom Calculators** for advanced needs.
|
|
264
|
+
|
|
265
|
+
#### A. Automatic Extension Tracking (Zero Config)
|
|
266
|
+
|
|
267
|
+
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.
|
|
268
|
+
|
|
269
|
+
* **For Marks**: `state().marks.yourExtensionName` (boolean) and `state().can.toggleYourExtensionName` (boolean).
|
|
270
|
+
* **For Nodes**: `state().nodes.yourExtensionName` (boolean).
|
|
271
|
+
|
|
272
|
+
#### B. Custom State Calculators (Advanced)
|
|
273
|
+
|
|
274
|
+
If you need to extract complex data (like attributes, depth, or custom logic), you can provide a custom `StateCalculator`.
|
|
275
|
+
|
|
276
|
+
1. **Define a Calculator**:
|
|
277
|
+
```typescript
|
|
278
|
+
import { StateCalculator } from "@flogeez/angular-tiptap-editor";
|
|
279
|
+
|
|
280
|
+
// This function will be called on every editor update
|
|
281
|
+
export const MyCustomCalculator: StateCalculator = (editor) => {
|
|
282
|
+
return {
|
|
283
|
+
custom: {
|
|
284
|
+
hasHighPriority: editor.isActive('priority'),
|
|
285
|
+
selectionDepth: editor.state.selection.$from.depth,
|
|
286
|
+
// Any data you need...
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
};
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
2. **Register it in the Template**:
|
|
293
|
+
```html
|
|
294
|
+
<angular-tiptap-editor
|
|
295
|
+
[stateCalculators]="[MyCustomCalculator]"
|
|
296
|
+
/>
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
3. **Consume it anywhere**:
|
|
300
|
+
```typescript
|
|
301
|
+
@Component({ ... })
|
|
302
|
+
export class MyToolbarComponent {
|
|
303
|
+
private editorCommands = inject(EditorCommandsService);
|
|
304
|
+
|
|
305
|
+
// Access your custom data reactively!
|
|
306
|
+
isHighPriority = computed(() => this.editorCommands.editorState().custom?.hasHighPriority);
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
235
310
|
## ✨ Key Features
|
|
236
311
|
|
|
237
312
|
### 📊 Table Management
|
|
@@ -254,6 +329,30 @@ Quick content insertion with slash commands:
|
|
|
254
329
|
- **Media**: `/image`, `/table`
|
|
255
330
|
- **Fully Internationalized**: All commands translated
|
|
256
331
|
|
|
332
|
+
#### Custom Slash Commands
|
|
333
|
+
|
|
334
|
+
The `slashCommands` object also allows you to add completely custom command items:
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
import { SlashCommandsConfig } from "@flogeez/angular-tiptap-editor";
|
|
338
|
+
|
|
339
|
+
slashCommands: SlashCommandsConfig = {
|
|
340
|
+
// Toggle native commands
|
|
341
|
+
heading1: true,
|
|
342
|
+
image: false,
|
|
343
|
+
// Add custom ones
|
|
344
|
+
custom: [
|
|
345
|
+
{
|
|
346
|
+
title: 'Magic Action',
|
|
347
|
+
description: 'Insert some AI magic',
|
|
348
|
+
icon: 'auto_fix',
|
|
349
|
+
keywords: ['magic', 'ai'],
|
|
350
|
+
command: (editor) => editor.commands.insertContent('✨ Magic happened!')
|
|
351
|
+
}
|
|
352
|
+
]
|
|
353
|
+
};
|
|
354
|
+
```
|
|
355
|
+
|
|
257
356
|
### 🖼️ Advanced Image Handling
|
|
258
357
|
|
|
259
358
|
Professional image management:
|
|
@@ -337,6 +436,8 @@ The `ImageUploadContext` provides:
|
|
|
337
436
|
|
|
338
437
|
The handler must return an `ImageUploadHandlerResult` with at least a `src` property containing the image URL.
|
|
339
438
|
|
|
439
|
+
---
|
|
440
|
+
|
|
340
441
|
|
|
341
442
|
### 📝 Word & Character Counting
|
|
342
443
|
|
|
@@ -379,127 +480,77 @@ Open [http://localhost:4200](http://localhost:4200) to view the demo.
|
|
|
379
480
|
| `height` | `number` | `undefined` | Fixed height in pixels |
|
|
380
481
|
| `maxHeight` | `number` | `undefined` | Maximum height in pixels |
|
|
381
482
|
| `minHeight` | `number` | `200` | Minimum height in pixels |
|
|
483
|
+
| `maxCharacters` | `number` | `undefined` | Character limit |
|
|
382
484
|
| `fillContainer` | `boolean` | `false` | Fill parent container height |
|
|
383
485
|
| `autofocus` | `boolean \| 'start' \| 'end' \| 'all'` | `false` | Auto-focus behavior |
|
|
384
486
|
| `showToolbar` | `boolean` | `true` | Show toolbar |
|
|
385
|
-
| `showBubbleMenu` | `boolean` | `true` | Show bubble menu
|
|
487
|
+
| `showBubbleMenu` | `boolean` | `true` | Show text bubble menu |
|
|
488
|
+
| `showImageBubbleMenu`| `boolean` | `true` | Show image bubble menu |
|
|
489
|
+
| `showTableBubbleMenu`| `boolean` | `true` | Show table bubble menu |
|
|
490
|
+
| `showCellBubbleMenu` | `boolean` | `true` | Show cell bubble menu |
|
|
491
|
+
| `enableSlashCommands`| `boolean` | `true` | Enable slash commands functionality|
|
|
492
|
+
| `enableOfficePaste` | `boolean` | `true` | Enable smart Office pasting |
|
|
386
493
|
| `showCharacterCount` | `boolean` | `true` | Show character counter |
|
|
387
494
|
| `showWordCount` | `boolean` | `true` | Show word counter |
|
|
388
495
|
| `toolbar` | `ToolbarConfig` | All enabled | Toolbar configuration |
|
|
389
496
|
| `bubbleMenu` | `BubbleMenuConfig` | All enabled | Bubble menu configuration |
|
|
497
|
+
| `imageBubbleMenu` | `ImageBubbleMenuConfig` | All enabled | Image bubble menu config |
|
|
498
|
+
| `tableBubbleMenu` | `TableBubbleMenuConfig` | All enabled | Table bubble menu config |
|
|
499
|
+
| `cellBubbleMenu` | `CellBubbleMenuConfig` | All enabled | Cell bubble menu config |
|
|
390
500
|
| `slashCommands` | `SlashCommandsConfig` | All enabled | Slash commands configuration |
|
|
391
501
|
| `imageUploadHandler` | `ImageUploadHandler` | `undefined` | Custom image upload function |
|
|
502
|
+
| `stateCalculators` | `StateCalculator[]` | `[]` | Custom reactive state logic |
|
|
392
503
|
| `tiptapExtensions` | `(Extension \| Node \| Mark)[]` | `[]` | Additional Tiptap extensions |
|
|
393
504
|
| `tiptapOptions` | `Partial<EditorOptions>` | `{}` | Additional Tiptap editor options |
|
|
394
505
|
|
|
395
506
|
|
|
396
|
-
|
|
397
507
|
#### Outputs
|
|
398
508
|
|
|
399
509
|
| Output | Type | Description |
|
|
400
510
|
| --------------- | ----------------- | ------------------------------- |
|
|
401
511
|
| `contentChange` | `string` | Emitted when content changes |
|
|
402
512
|
| `editorCreated` | `Editor` | Emitted when editor is created |
|
|
513
|
+
| `editorUpdate` | `{editor, trans}` | Emitted on every editor update |
|
|
403
514
|
| `editorFocus` | `{editor, event}` | Emitted when editor gains focus |
|
|
404
515
|
| `editorBlur` | `{editor, event}` | Emitted when editor loses focus |
|
|
405
516
|
|
|
406
|
-
### Configuration Examples
|
|
407
|
-
|
|
408
|
-
```typescript
|
|
409
|
-
import {
|
|
410
|
-
DEFAULT_TOOLBAR_CONFIG,
|
|
411
|
-
DEFAULT_BUBBLE_MENU_CONFIG,
|
|
412
|
-
SLASH_COMMAND_KEYS,
|
|
413
|
-
} from "@flogeez/angular-tiptap-editor";
|
|
414
|
-
|
|
415
|
-
// Minimal toolbar
|
|
416
|
-
const minimalToolbar = {
|
|
417
|
-
bold: true,
|
|
418
|
-
italic: true,
|
|
419
|
-
bulletList: true,
|
|
420
|
-
};
|
|
421
|
-
|
|
422
|
-
// Full toolbar with clear button
|
|
423
|
-
const fullToolbar = {
|
|
424
|
-
...DEFAULT_TOOLBAR_CONFIG,
|
|
425
|
-
clear: true, // Add clear button
|
|
426
|
-
};
|
|
427
|
-
|
|
428
|
-
// Bubble menu with table support
|
|
429
|
-
const bubbleMenuWithTable = {
|
|
430
|
-
...DEFAULT_BUBBLE_MENU_CONFIG,
|
|
431
|
-
table: true, // Enable table bubble menu
|
|
432
|
-
};
|
|
433
|
-
|
|
434
|
-
// Slash commands configuration (simple toggle)
|
|
435
|
-
// By default, all commands are enabled and localized.
|
|
436
|
-
const slashCommands = {
|
|
437
|
-
heading1: true,
|
|
438
|
-
heading2: true,
|
|
439
|
-
image: false, // Disable image command
|
|
440
|
-
};
|
|
441
|
-
|
|
442
|
-
// Available keys: "heading1", "heading2", "heading3", "bulletList",
|
|
443
|
-
// "orderedList", "blockquote", "code", "image", "horizontalRule", "table"
|
|
444
|
-
```
|
|
445
517
|
|
|
446
518
|
## 🌍 Internationalization
|
|
447
519
|
|
|
448
|
-
The editor
|
|
520
|
+
The editor comes with built-in support for **English (en)** and **French (fr)**, featuring automatic browser language detection.
|
|
449
521
|
|
|
450
|
-
|
|
451
|
-
// Force English
|
|
452
|
-
<angular-tiptap-editor [locale]="'en'" />
|
|
522
|
+
### Basic Usage
|
|
453
523
|
|
|
454
|
-
|
|
524
|
+
```typescript
|
|
525
|
+
// Force a specific language
|
|
455
526
|
<angular-tiptap-editor [locale]="'fr'" />
|
|
456
527
|
|
|
457
528
|
// Auto-detect (default)
|
|
458
529
|
<angular-tiptap-editor />
|
|
459
530
|
```
|
|
460
531
|
|
|
461
|
-
###
|
|
532
|
+
### Adding Custom Languages
|
|
462
533
|
|
|
463
|
-
|
|
464
|
-
- **French (fr)**: Full French translation including:
|
|
465
|
-
- Toolbar buttons
|
|
466
|
-
- Bubble menu items
|
|
467
|
-
- Slash commands
|
|
468
|
-
- Placeholder text
|
|
469
|
-
- Error messages
|
|
470
|
-
- Word/character count (with proper pluralization)
|
|
471
|
-
|
|
472
|
-
### Custom Slash Commands
|
|
473
|
-
|
|
474
|
-
For advanced usage, you can provide entirely custom command items (titles, icons, logic):
|
|
534
|
+
You can easily extend the editor with new languages or override existing labels using the `TiptapI18nService`:
|
|
475
535
|
|
|
476
536
|
```typescript
|
|
477
|
-
import {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
//
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
537
|
+
import { TiptapI18nService } from "@flogeez/angular-tiptap-editor";
|
|
538
|
+
|
|
539
|
+
@Component({ ... })
|
|
540
|
+
export class MyComponent {
|
|
541
|
+
constructor(private i18nService: TiptapI18nService) {
|
|
542
|
+
// Add Spanish support
|
|
543
|
+
this.i18nService.addTranslations('es', {
|
|
544
|
+
toolbar: { bold: 'Negrita', italic: 'Cursiva', ... },
|
|
545
|
+
editor: { placeholder: 'Empieza a escribir...' }
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
// Switch to Spanish
|
|
549
|
+
this.i18nService.setLocale('es');
|
|
490
550
|
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
// Use in template
|
|
494
|
-
customSlashCommands = {
|
|
495
|
-
commands: myCommands,
|
|
496
|
-
};
|
|
551
|
+
}
|
|
497
552
|
```
|
|
498
553
|
|
|
499
|
-
And in template:
|
|
500
|
-
```html
|
|
501
|
-
<angular-tiptap-editor [customSlashCommands]="customSlashCommands" />
|
|
502
|
-
```
|
|
503
554
|
|
|
504
555
|
### 🎨 CSS Custom Properties
|
|
505
556
|
|
|
@@ -571,23 +622,56 @@ angular-tiptap-editor {
|
|
|
571
622
|
```
|
|
572
623
|
|
|
573
624
|
|
|
625
|
+
### ⚡ Reactive State & OnPush
|
|
626
|
+
|
|
627
|
+
The library exposes a reactive `editorState` signal via the `EditorCommandsService`. This signal contains everything you need to build custom UIs around the editor:
|
|
628
|
+
|
|
629
|
+
- **Active State**: Check if `bold`, `italic`, or custom marks are active.
|
|
630
|
+
- **Commands Availability**: Check if `undo`, `redo`, or custom commands can be executed.
|
|
631
|
+
- **Structural Data**: Access table status, image attributes, or selection details.
|
|
632
|
+
|
|
633
|
+
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.
|
|
634
|
+
|
|
635
|
+
---
|
|
636
|
+
|
|
637
|
+
### 🧩 Custom Tiptap Extensions
|
|
638
|
+
|
|
639
|
+
You are not limited to the built-in extensions. Pass any Tiptap extension, mark, or node:
|
|
640
|
+
|
|
641
|
+
```html
|
|
642
|
+
<angular-tiptap-editor [tiptapExtensions]="[MyCustomExtension]" />
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
Any custom extension is automatically detected and its state (active/can) is added to the reactive `editorState` snapshot.
|
|
646
|
+
|
|
647
|
+
---
|
|
648
|
+
|
|
574
649
|
## 🏗️ Architecture
|
|
575
650
|
|
|
576
|
-
###
|
|
651
|
+
### Reactive State Management
|
|
652
|
+
|
|
653
|
+
The library uses a **Snapshot & Signal** pattern to bridge Tiptap and Angular.
|
|
654
|
+
|
|
655
|
+
1. **State Snapshot**: Every editor transaction triggers a set of "Calculators" that produce a single immutable state object.
|
|
656
|
+
2. **Specialized Calculators**: Logic is modularized into specialized functions (Marks, Table, Image, etc.) and a **Discovery Calculator** for automatic extension detection.
|
|
657
|
+
3. **Signals Integration**: This snapshot is stored in a single Angular Signal. Sub-components (toolbar, menus) consume this signal only where needed.
|
|
658
|
+
4. **Change Detection Optimization**: A custom equality check on the signal prevents unnecessary re-renders when the visual state of the editor hasn't changed.
|
|
659
|
+
|
|
660
|
+
### Core Services
|
|
661
|
+
|
|
662
|
+
- **`EditorCommandsService`**: Exposes the `editorState` signal and provides a centralized API for executing Tiptap commands.
|
|
663
|
+
- **`ImageService`**: Manages the image processing pipeline (selection, compression, and server-side upload handling).
|
|
664
|
+
- **`TiptapI18nService`**: Reactive translation service with support for browser locale auto-detection.
|
|
577
665
|
|
|
578
|
-
|
|
666
|
+
### Isolated Instances
|
|
579
667
|
|
|
580
|
-
|
|
581
|
-
- **`TiptapI18nService`**: Internationalization service with automatic language detection
|
|
582
|
-
- **`ImageService`**: Advanced image handling with compression and resizing
|
|
583
|
-
- **`filterSlashCommands()`**: Utility function for managing slash commands
|
|
668
|
+
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.
|
|
584
669
|
|
|
585
|
-
### Modern Angular
|
|
670
|
+
### Modern Angular Integration
|
|
586
671
|
|
|
587
|
-
- **Signals**:
|
|
588
|
-
- **
|
|
589
|
-
- **
|
|
590
|
-
- **TypeScript**: Strict typing with comprehensive interfaces
|
|
672
|
+
- **Signals**: Native reactivity for efficient UI updates.
|
|
673
|
+
- **OnPush**: Designed for `ChangeDetectionStrategy.OnPush` throughout.
|
|
674
|
+
- **Typed State**: Fully typed interfaces for the editor state and configurations.
|
|
591
675
|
|
|
592
676
|
### Default Configurations
|
|
593
677
|
|
|
@@ -649,14 +733,11 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
649
733
|
|
|
650
734
|
### Latest Updates
|
|
651
735
|
|
|
652
|
-
- ✅ **
|
|
653
|
-
- ✅ **
|
|
654
|
-
- ✅ **
|
|
655
|
-
- ✅ **
|
|
656
|
-
- ✅ **
|
|
657
|
-
- ✅ **Default Configurations**: Importable default configs for easy customization
|
|
658
|
-
- ✅ **Office Paste**: Clean pasting from Microsoft Office applications
|
|
659
|
-
- ✅ **Enhanced i18n**: Improved internationalization with better architecture
|
|
736
|
+
- ✅ **Reactive State & Signals**: Optimized state management for a faster, smoother experience.
|
|
737
|
+
- ✅ **Zero-Config Extensions**: Custom Tiptap Marks and Nodes are tracked automatically.
|
|
738
|
+
- ✅ **Multi-Instance Support**: Use multiple independent editors on the same page without state leaks.
|
|
739
|
+
- ✅ **Clean Service Architecture**: Decoupled configurations and isolated services for better stability.
|
|
740
|
+
- ✅ **Refactored Link Management**: Dedicated link bubble menu with smart UI anchoring and real-time URL sync.
|
|
660
741
|
|
|
661
742
|
---
|
|
662
743
|
|