@flogeez/angular-tiptap-editor 0.5.3 → 0.6.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 +45 -0
- package/LICENSE +1 -1
- package/README.md +115 -96
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +3588 -2741
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/index.d.ts +329 -77
- package/package.json +1 -1
- package/src/lib/styles/bubble-menu.global.css +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,51 @@ 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.6.0] - 2026-01-14
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Reactive State Management**: New "Snapshot & Signal" architecture with optimized change detection (OnPush).
|
|
12
|
+
- **Custom Extension Tracking**: Automatic state tracking for custom Tiptap Marks and Nodes (zero-config).
|
|
13
|
+
- **Extensible State**: New `stateCalculators` input to inject custom logic into the reactive editor state.
|
|
14
|
+
- **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.
|
|
15
|
+
- **Link & Color Bubble Menus**: Completely refactored management with dedicated bubble menus.
|
|
16
|
+
- **LinkService**: New dedicated service to manage link state and lifecycle independently.
|
|
17
|
+
- **Improved Visual Feedback**: Menus now preserve the editor's blue selection highlight while choosing colors or preparing to type a link.
|
|
18
|
+
- **Improved Image Selection**: Automatic node selection after insertion or replacement, ensuring resize handles and bubble menus appear instantly.
|
|
19
|
+
- **Danger Button Variant**: New `danger` variant for actions like "Reset Color" or "Remove Link", providing clear visual feedback for destructive operations.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- **Multi-instance Support**: Full service isolation, allowing multiple editors on the same page without shared state.
|
|
23
|
+
- **Bubble Menu Conflicts**: Fixed overlapping menus by implementing a strict priority system (specialized menus now hide the main text menu).
|
|
24
|
+
- **Image Bubble Menu Persistence**: Corrected Tippy.js behavior to prevent menus from disappearing when re-clicking an already-selected image.
|
|
25
|
+
- **Toolbar-Menu Harmony**: Bubbles now reactively hide when interacting with the main toolbar via a centralized signal.
|
|
26
|
+
- **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.
|
|
27
|
+
- **Atomic Image Replacement**: Refactored image service to perform atomic updates, fixing the "extra space" bug and preventing layout shifts during asynchronous uploads.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
- **Architectural Refactoring**: `EditorCommandsService` is now a clean facade/proxy for specialized services (`ImageService`, `ColorPickerService`, `LinkService`).
|
|
31
|
+
- **Optimized State Performance**: Refactored state calculators (notably `MarksCalculator`) to minimize DOM access and avoid unnecessary layout recalculations (reflow).
|
|
32
|
+
- **Centralized Color Utilities**: Consolidated color normalization, luminance, and contrast calculations into a shared utility for perfect consistency.
|
|
33
|
+
- **Public API Cleanup**: Exported all modular calculators, services, and models for better extensibility.
|
|
34
|
+
- **Color Picker Stability**: Integrated selection capture and locked modes to ensure 100% reliability in color application.
|
|
35
|
+
|
|
36
|
+
## [0.5.5] - 2026-01-09
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
- **Bubble Menus Confinement**: Menus now properly respect the editor's boundaries and are clipped by the container when scrolling, specifically optimized for `fillContainer` mode.
|
|
40
|
+
- **Unified Command Execution**: Centralized all editor operations within `EditorCommandsService`, ensuring consistent behavior between the toolbar and bubble menus.
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
- **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.
|
|
44
|
+
- **Bubble Menus Performances**: Significant performance boost in `getImageRect` and `getTableRect` using direct ProseMirror DOM lookups.
|
|
45
|
+
- **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.
|
|
46
|
+
|
|
47
|
+
## [0.5.4] - 2026-01-08
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
- **Enhanced Color Pickers**: Refactored text and highlight pickers with a curated palette of predefined colors for faster styling.
|
|
51
|
+
- **Intelligent Bubble Menus**: Automatic hiding when approaching the toolbar and smart restoration when leaving, ensuring a non-obstructive editing experience.
|
|
52
|
+
|
|
8
53
|
## [0.5.3] - 2026-01-08
|
|
9
54
|
|
|
10
55
|
### Added
|
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -114,20 +114,24 @@ export class AdvancedComponent {
|
|
|
114
114
|
};
|
|
115
115
|
|
|
116
116
|
// No config needed if you want all commands enabled
|
|
117
|
-
|
|
117
|
+
slashCommandsConfig = {
|
|
118
118
|
image: true,
|
|
119
119
|
table: true,
|
|
120
120
|
heading1: true
|
|
121
121
|
};
|
|
122
122
|
|
|
123
|
+
// Available keys: "heading1", "heading2", "heading3", "bulletList",
|
|
124
|
+
// "orderedList", "blockquote", "code", "image", "horizontalRule", "table"
|
|
125
|
+
|
|
123
126
|
onContentChange(newContent: string) {
|
|
124
127
|
this.content = newContent;
|
|
125
128
|
}
|
|
126
129
|
}
|
|
127
130
|
```
|
|
128
131
|
|
|
129
|
-
|
|
130
|
-
|
|
132
|
+
### 3. Registering Custom Extensions
|
|
133
|
+
|
|
134
|
+
Easily extend the editor with any standard Tiptap extension or your own custom marks/nodes via the `tiptapExtensions` input.
|
|
131
135
|
|
|
132
136
|
```typescript
|
|
133
137
|
import { Component } from "@angular/core";
|
|
@@ -156,7 +160,7 @@ export class CustomExtensionsComponent {
|
|
|
156
160
|
}
|
|
157
161
|
```
|
|
158
162
|
|
|
159
|
-
###
|
|
163
|
+
### 4. With Form Integration
|
|
160
164
|
|
|
161
165
|
```typescript
|
|
162
166
|
import { Component } from "@angular/core";
|
|
@@ -195,9 +199,15 @@ import { EditorCommandsService } from "@flogeez/angular-tiptap-editor";
|
|
|
195
199
|
standalone: true,
|
|
196
200
|
template: `
|
|
197
201
|
<div>
|
|
198
|
-
<
|
|
199
|
-
|
|
200
|
-
|
|
202
|
+
<div class="controls">
|
|
203
|
+
<button (click)="clearContent()">Clear Content</button>
|
|
204
|
+
<button (click)="focusEditor()">Focus Editor</button>
|
|
205
|
+
<button (click)="setContent()">Set Content</button>
|
|
206
|
+
</div>
|
|
207
|
+
|
|
208
|
+
<angular-tiptap-editor
|
|
209
|
+
(editorCreated)="onEditorCreated($event)"
|
|
210
|
+
/>
|
|
201
211
|
</div>
|
|
202
212
|
`,
|
|
203
213
|
})
|
|
@@ -232,6 +242,55 @@ export class CommandsComponent {
|
|
|
232
242
|
}
|
|
233
243
|
```
|
|
234
244
|
|
|
245
|
+
### 5. Extending Reactive Editor State
|
|
246
|
+
|
|
247
|
+
The editor features a dual-layer state architecture: **Automatic Tracking** for simple extensions and **Custom Calculators** for advanced needs.
|
|
248
|
+
|
|
249
|
+
#### A. Automatic Extension Tracking (Zero Config)
|
|
250
|
+
|
|
251
|
+
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.
|
|
252
|
+
|
|
253
|
+
* **For Marks**: `state().marks.yourExtensionName` (boolean) and `state().can.toggleYourExtensionName` (boolean).
|
|
254
|
+
* **For Nodes**: `state().nodes.yourExtensionName` (boolean).
|
|
255
|
+
|
|
256
|
+
#### B. Custom State Calculators (Advanced)
|
|
257
|
+
|
|
258
|
+
If you need to extract complex data (like attributes, depth, or custom logic), you can provide a custom `StateCalculator`.
|
|
259
|
+
|
|
260
|
+
1. **Define a Calculator**:
|
|
261
|
+
```typescript
|
|
262
|
+
import { StateCalculator } from "@flogeez/angular-tiptap-editor";
|
|
263
|
+
|
|
264
|
+
// This function will be called on every editor update
|
|
265
|
+
export const MyCustomCalculator: StateCalculator = (editor) => {
|
|
266
|
+
return {
|
|
267
|
+
custom: {
|
|
268
|
+
hasHighPriority: editor.isActive('priority'),
|
|
269
|
+
selectionDepth: editor.state.selection.$from.depth,
|
|
270
|
+
// Any data you need...
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
};
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
2. **Register it in the Template**:
|
|
277
|
+
```html
|
|
278
|
+
<angular-tiptap-editor
|
|
279
|
+
[stateCalculators]="[MyCustomCalculator]"
|
|
280
|
+
/>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
3. **Consume it anywhere**:
|
|
284
|
+
```typescript
|
|
285
|
+
@Component({ ... })
|
|
286
|
+
export class MyToolbarComponent {
|
|
287
|
+
private editorCommands = inject(EditorCommandsService);
|
|
288
|
+
|
|
289
|
+
// Access your custom data reactively!
|
|
290
|
+
isHighPriority = computed(() => this.editorCommands.editorState().custom?.hasHighPriority);
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
235
294
|
## ✨ Key Features
|
|
236
295
|
|
|
237
296
|
### 📊 Table Management
|
|
@@ -254,6 +313,30 @@ Quick content insertion with slash commands:
|
|
|
254
313
|
- **Media**: `/image`, `/table`
|
|
255
314
|
- **Fully Internationalized**: All commands translated
|
|
256
315
|
|
|
316
|
+
#### Custom Slash Commands
|
|
317
|
+
|
|
318
|
+
The `slashCommands` object also allows you to add completely custom command items:
|
|
319
|
+
|
|
320
|
+
```typescript
|
|
321
|
+
import { SlashCommandsConfig } from "@flogeez/angular-tiptap-editor";
|
|
322
|
+
|
|
323
|
+
slashCommands: SlashCommandsConfig = {
|
|
324
|
+
// Toggle native commands
|
|
325
|
+
heading1: true,
|
|
326
|
+
image: false,
|
|
327
|
+
// Add custom ones
|
|
328
|
+
custom: [
|
|
329
|
+
{
|
|
330
|
+
title: 'Magic Action',
|
|
331
|
+
description: 'Insert some AI magic',
|
|
332
|
+
icon: 'auto_fix',
|
|
333
|
+
keywords: ['magic', 'ai'],
|
|
334
|
+
command: (editor) => editor.commands.insertContent('✨ Magic happened!')
|
|
335
|
+
}
|
|
336
|
+
]
|
|
337
|
+
};
|
|
338
|
+
```
|
|
339
|
+
|
|
257
340
|
### 🖼️ Advanced Image Handling
|
|
258
341
|
|
|
259
342
|
Professional image management:
|
|
@@ -403,45 +486,6 @@ Open [http://localhost:4200](http://localhost:4200) to view the demo.
|
|
|
403
486
|
| `editorFocus` | `{editor, event}` | Emitted when editor gains focus |
|
|
404
487
|
| `editorBlur` | `{editor, event}` | Emitted when editor loses focus |
|
|
405
488
|
|
|
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
489
|
|
|
446
490
|
## 🌍 Internationalization
|
|
447
491
|
|
|
@@ -469,37 +513,6 @@ The editor supports English and French with automatic browser language detection
|
|
|
469
513
|
- Error messages
|
|
470
514
|
- Word/character count (with proper pluralization)
|
|
471
515
|
|
|
472
|
-
### Custom Slash Commands
|
|
473
|
-
|
|
474
|
-
For advanced usage, you can provide entirely custom command items (titles, icons, logic):
|
|
475
|
-
|
|
476
|
-
```typescript
|
|
477
|
-
import {
|
|
478
|
-
CustomSlashCommands,
|
|
479
|
-
SlashCommandItem
|
|
480
|
-
} from "@flogeez/angular-tiptap-editor";
|
|
481
|
-
|
|
482
|
-
// Define your custom items
|
|
483
|
-
const myCommands: SlashCommandItem[] = [
|
|
484
|
-
{
|
|
485
|
-
title: 'My Action',
|
|
486
|
-
description: 'Do something cool',
|
|
487
|
-
icon: 'star',
|
|
488
|
-
keywords: ['custom', 'cool'],
|
|
489
|
-
command: (editor) => { /* logic */ }
|
|
490
|
-
}
|
|
491
|
-
];
|
|
492
|
-
|
|
493
|
-
// Use in template
|
|
494
|
-
customSlashCommands = {
|
|
495
|
-
commands: myCommands,
|
|
496
|
-
};
|
|
497
|
-
```
|
|
498
|
-
|
|
499
|
-
And in template:
|
|
500
|
-
```html
|
|
501
|
-
<angular-tiptap-editor [customSlashCommands]="customSlashCommands" />
|
|
502
|
-
```
|
|
503
516
|
|
|
504
517
|
### 🎨 CSS Custom Properties
|
|
505
518
|
|
|
@@ -573,21 +586,30 @@ angular-tiptap-editor {
|
|
|
573
586
|
|
|
574
587
|
## 🏗️ Architecture
|
|
575
588
|
|
|
576
|
-
###
|
|
589
|
+
### Reactive State Management
|
|
590
|
+
|
|
591
|
+
The library uses a **Snapshot & Signal** pattern to bridge Tiptap and Angular.
|
|
592
|
+
|
|
593
|
+
1. **State Snapshot**: Every editor transaction triggers a set of "Calculators" that produce a single immutable state object.
|
|
594
|
+
2. **Specialized Calculators**: Logic is modularized into specialized functions (Marks, Table, Image, etc.) and a **Discovery Calculator** for automatic extension detection.
|
|
595
|
+
3. **Signals Integration**: This snapshot is stored in a single Angular Signal. Sub-components (toolbar, menus) consume this signal only where needed.
|
|
596
|
+
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.
|
|
597
|
+
|
|
598
|
+
### Core Services
|
|
599
|
+
|
|
600
|
+
- **`EditorCommandsService`**: Exposes the `editorState` signal and provides a centralized API for executing Tiptap commands.
|
|
601
|
+
- **`ImageService`**: Manages the image processing pipeline (selection, compression, and server-side upload handling).
|
|
602
|
+
- **`TiptapI18nService`**: Reactive translation service with support for browser locale auto-detection.
|
|
577
603
|
|
|
578
|
-
|
|
604
|
+
### Isolated Instances
|
|
579
605
|
|
|
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
|
|
606
|
+
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
607
|
|
|
585
|
-
### Modern Angular
|
|
608
|
+
### Modern Angular Integration
|
|
586
609
|
|
|
587
|
-
- **Signals**:
|
|
588
|
-
- **
|
|
589
|
-
- **
|
|
590
|
-
- **TypeScript**: Strict typing with comprehensive interfaces
|
|
610
|
+
- **Signals**: Native reactivity for efficient UI updates.
|
|
611
|
+
- **OnPush**: Designed for `ChangeDetectionStrategy.OnPush` throughout.
|
|
612
|
+
- **Typed State**: Fully typed interfaces for the editor state and configurations.
|
|
591
613
|
|
|
592
614
|
### Default Configurations
|
|
593
615
|
|
|
@@ -649,14 +671,11 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
649
671
|
|
|
650
672
|
### Latest Updates
|
|
651
673
|
|
|
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
|
|
674
|
+
- ✅ **Reactive State & Signals**: Optimized state management for a faster, smoother experience.
|
|
675
|
+
- ✅ **Zero-Config Extensions**: Custom Tiptap Marks and Nodes are tracked automatically.
|
|
676
|
+
- ✅ **Multi-Instance Support**: Use multiple independent editors on the same page without state leaks.
|
|
677
|
+
- ✅ **Clean Service Architecture**: Decoupled configurations and isolated services for better stability.
|
|
678
|
+
- ✅ **Refactored Link Management**: Dedicated link bubble menu with smart UI anchoring and real-time URL sync.
|
|
660
679
|
|
|
661
680
|
---
|
|
662
681
|
|