@flogeez/angular-tiptap-editor 0.5.4 → 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 CHANGED
@@ -5,6 +5,45 @@ 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
+
8
47
  ## [0.5.4] - 2026-01-08
9
48
 
10
49
  ### Added
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 FloGeez
3
+ Copyright (c) 2026 FloGeez
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
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
- slashCommands = {
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
- You can also pass additional TipTap extensions (including custom marks)
130
- via the `tiptapExtensions` input.
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
- ### 3. With Form Integration
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
- <button (click)="clearContent()">Clear Content</button>
199
- <button (click)="focusEditor()">Focus Editor</button>
200
- <button (click)="setContent()">Set Content</button>
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
- ### Service-Based Design
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
- The library follows a clean service-based architecture:
604
+ ### Isolated Instances
579
605
 
580
- - **`EditorCommandsService`**: Centralized service for all editor commands
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 Patterns
608
+ ### Modern Angular Integration
586
609
 
587
- - **Signals**: Used throughout for reactive state management
588
- - **Dependency Injection**: Clean service injection with `inject()`
589
- - **Standalone Components**: All components are standalone for better tree-shaking
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
- - ✅ **Custom Image Upload Handler**: Upload images to your own server (S3, Cloudinary, etc.)
653
- - ✅ **Table Support**: Full table management with bubble menus
654
- - ✅ **Slash Commands**: Intuitive content insertion commands
655
- - ✅ **Word/Character Count**: Real-time counting with proper pluralization
656
- - ✅ **Service Architecture**: Clean `EditorCommandsService` for better maintainability
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