@flogeez/angular-tiptap-editor 2.0.3 → 2.1.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 +12 -0
- package/README.md +168 -107
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +203 -129
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/index.d.ts +284 -167
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ 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
|
+
## [2.1.0] - 2026-01-20
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Unified Configuration**: Introduced `AteEditorConfig`, a single flatter interface to manage all editor settings (fundamentals, display options, and modules) via a new `[config]` input.
|
|
12
|
+
- **Enhanced Image Upload Config**: Restructured image upload settings with dedicated `AteImageUploadConfig`, supporting quality, dimensions, max size (in MB), and allowed types.
|
|
13
|
+
- **Menu Visibility Controls**: Added root-level boolean flags to toggle specific bubble menus (`showBubbleMenu`, `showTableMenu`, `showCellMenu`, `showImageBubbleMenu`) and slash commands (`enableSlashCommands`).
|
|
14
|
+
- **Improved Developer Experience**: Updated the demo's code generator to produce consolidated `AteEditorConfig` boilerplate, making it easier for developers to copy-paste configurations.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- **Configuration Precedence**: Standardized the merging logic across all components, ensuring individual inputs correctly override global configuration values while maintaining sensible defaults.
|
|
18
|
+
- **Public API**: Exported `AteEditorConfig` in the public API for better type safety in host applications.
|
|
19
|
+
|
|
8
20
|
## [2.0.3] - 2026-01-19
|
|
9
21
|
|
|
10
22
|
### Added
|
package/README.md
CHANGED
|
@@ -88,12 +88,14 @@ export class ExampleComponent {
|
|
|
88
88
|
|
|
89
89
|
### 2. With Custom Configuration
|
|
90
90
|
|
|
91
|
+
The editor can be fully configured using a single `[config]` object, which provides a clean and type-safe way to manage all settings.
|
|
92
|
+
|
|
91
93
|
```typescript
|
|
92
94
|
import { Component } from "@angular/core";
|
|
93
95
|
import {
|
|
94
96
|
AngularTiptapEditorComponent,
|
|
97
|
+
AteEditorConfig,
|
|
95
98
|
DEFAULT_TOOLBAR_CONFIG,
|
|
96
|
-
DEFAULT_BUBBLE_MENU_CONFIG,
|
|
97
99
|
} from "@flogeez/angular-tiptap-editor";
|
|
98
100
|
|
|
99
101
|
@Component({
|
|
@@ -103,14 +105,7 @@ import {
|
|
|
103
105
|
template: `
|
|
104
106
|
<angular-tiptap-editor
|
|
105
107
|
[content]="content"
|
|
106
|
-
[
|
|
107
|
-
[bubbleMenu]="bubbleMenuConfig"
|
|
108
|
-
[slashCommands]="slashCommandsConfig"
|
|
109
|
-
[locale]="'en'"
|
|
110
|
-
[height]="400"
|
|
111
|
-
[showCharacterCount]="true"
|
|
112
|
-
[showWordCount]="true"
|
|
113
|
-
[maxCharacters]="500"
|
|
108
|
+
[config]="editorConfig"
|
|
114
109
|
(contentChange)="onContentChange($event)"
|
|
115
110
|
/>
|
|
116
111
|
`,
|
|
@@ -118,27 +113,29 @@ import {
|
|
|
118
113
|
export class AdvancedComponent {
|
|
119
114
|
content = "<h1>Welcome!</h1><p>Start editing...</p>";
|
|
120
115
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
116
|
+
editorConfig: AteEditorConfig = {
|
|
117
|
+
locale: "fr", // Force French (default is auto-detect)
|
|
118
|
+
height: "400px", // Set a fixed height
|
|
119
|
+
placeholder: "Commencez à rédiger...",
|
|
120
|
+
showWordCount: false, // Hide the word counter (default is true)
|
|
121
|
+
showEditToggle: true, // Show the button to toggle read-only mode (default is false)
|
|
122
|
+
|
|
123
|
+
// Customize the toolbar by enabling specific features
|
|
124
|
+
toolbar: {
|
|
125
|
+
...DEFAULT_TOOLBAR_CONFIG,
|
|
126
|
+
clear: true, // Enable the 'Clear' button
|
|
127
|
+
highlight: false, // Disable the highlight button
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
// Only enable specific slash commands
|
|
131
|
+
slashCommands: {
|
|
132
|
+
heading1: true,
|
|
133
|
+
heading2: true,
|
|
134
|
+
image: true,
|
|
135
|
+
table: true,
|
|
136
|
+
},
|
|
137
137
|
};
|
|
138
138
|
|
|
139
|
-
// Available keys: "heading1", "heading2", "heading3", "bulletList",
|
|
140
|
-
// "orderedList", "blockquote", "code", "image", "horizontalRule", "table"
|
|
141
|
-
|
|
142
139
|
onContentChange(newContent: string) {
|
|
143
140
|
this.content = newContent;
|
|
144
141
|
}
|
|
@@ -221,9 +218,7 @@ import { EditorCommandsService } from "@flogeez/angular-tiptap-editor";
|
|
|
221
218
|
<button (click)="setContent()">Set Content</button>
|
|
222
219
|
</div>
|
|
223
220
|
|
|
224
|
-
<angular-tiptap-editor
|
|
225
|
-
(editorCreated)="onEditorCreated($event)"
|
|
226
|
-
/>
|
|
221
|
+
<angular-tiptap-editor (editorCreated)="onEditorCreated($event)" />
|
|
227
222
|
</div>
|
|
228
223
|
`,
|
|
229
224
|
})
|
|
@@ -251,7 +246,7 @@ export class CommandsComponent {
|
|
|
251
246
|
if (this.editor) {
|
|
252
247
|
this.editorCommandsService.setContent(
|
|
253
248
|
this.editor,
|
|
254
|
-
"<h1>New Content</h1>"
|
|
249
|
+
"<h1>New Content</h1>",
|
|
255
250
|
);
|
|
256
251
|
}
|
|
257
252
|
}
|
|
@@ -266,14 +261,15 @@ The editor features a dual-layer state architecture: **Automatic Tracking** for
|
|
|
266
261
|
|
|
267
262
|
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
263
|
|
|
269
|
-
|
|
270
|
-
|
|
264
|
+
- **For Marks**: `state().marks.yourExtensionName` (boolean) and `state().can.toggleYourExtensionName` (boolean).
|
|
265
|
+
- **For Nodes**: `state().nodes.yourExtensionName` (boolean).
|
|
271
266
|
|
|
272
267
|
#### B. Custom State Calculators (Advanced)
|
|
273
268
|
|
|
274
269
|
If you need to extract complex data (like attributes, depth, or custom logic), you can provide a custom `StateCalculator`.
|
|
275
270
|
|
|
276
271
|
1. **Define a Calculator**:
|
|
272
|
+
|
|
277
273
|
```typescript
|
|
278
274
|
import { StateCalculator } from "@flogeez/angular-tiptap-editor";
|
|
279
275
|
|
|
@@ -281,27 +277,27 @@ import { StateCalculator } from "@flogeez/angular-tiptap-editor";
|
|
|
281
277
|
export const MyCustomCalculator: StateCalculator = (editor) => {
|
|
282
278
|
return {
|
|
283
279
|
custom: {
|
|
284
|
-
hasHighPriority: editor.isActive(
|
|
280
|
+
hasHighPriority: editor.isActive("priority"),
|
|
285
281
|
selectionDepth: editor.state.selection.$from.depth,
|
|
286
282
|
// Any data you need...
|
|
287
|
-
}
|
|
283
|
+
},
|
|
288
284
|
};
|
|
289
285
|
};
|
|
290
286
|
```
|
|
291
287
|
|
|
292
288
|
2. **Register it in the Template**:
|
|
289
|
+
|
|
293
290
|
```html
|
|
294
|
-
<angular-tiptap-editor
|
|
295
|
-
[stateCalculators]="[MyCustomCalculator]"
|
|
296
|
-
/>
|
|
291
|
+
<angular-tiptap-editor [stateCalculators]="[MyCustomCalculator]" />
|
|
297
292
|
```
|
|
298
293
|
|
|
299
294
|
3. **Consume it anywhere**:
|
|
295
|
+
|
|
300
296
|
```typescript
|
|
301
297
|
@Component({ ... })
|
|
302
298
|
export class MyToolbarComponent {
|
|
303
299
|
private editorCommands = inject(EditorCommandsService);
|
|
304
|
-
|
|
300
|
+
|
|
305
301
|
// Access your custom data reactively!
|
|
306
302
|
isHighPriority = computed(() => this.editorCommands.editorState().custom?.hasHighPriority);
|
|
307
303
|
}
|
|
@@ -343,13 +339,13 @@ slashCommands: SlashCommandsConfig = {
|
|
|
343
339
|
// Add custom ones
|
|
344
340
|
custom: [
|
|
345
341
|
{
|
|
346
|
-
title:
|
|
347
|
-
description:
|
|
348
|
-
icon:
|
|
349
|
-
keywords: [
|
|
350
|
-
command: (editor) => editor.commands.insertContent(
|
|
351
|
-
}
|
|
352
|
-
]
|
|
342
|
+
title: "Magic Action",
|
|
343
|
+
description: "Insert some AI magic",
|
|
344
|
+
icon: "auto_fix",
|
|
345
|
+
keywords: ["magic", "ai"],
|
|
346
|
+
command: (editor) => editor.commands.insertContent("✨ Magic happened!"),
|
|
347
|
+
},
|
|
348
|
+
],
|
|
353
349
|
};
|
|
354
350
|
```
|
|
355
351
|
|
|
@@ -373,16 +369,16 @@ The handler can return either an **Observable** or a **Promise**.
|
|
|
373
369
|
#### Using Observable (recommended for Angular)
|
|
374
370
|
|
|
375
371
|
```typescript
|
|
376
|
-
import { Component, inject } from
|
|
377
|
-
import { HttpClient } from
|
|
378
|
-
import { map } from
|
|
372
|
+
import { Component, inject } from "@angular/core";
|
|
373
|
+
import { HttpClient } from "@angular/common/http";
|
|
374
|
+
import { map } from "rxjs/operators";
|
|
379
375
|
import {
|
|
380
376
|
AngularTiptapEditorComponent,
|
|
381
|
-
ImageUploadHandler
|
|
382
|
-
} from
|
|
377
|
+
ImageUploadHandler,
|
|
378
|
+
} from "@flogeez/angular-tiptap-editor";
|
|
383
379
|
|
|
384
380
|
@Component({
|
|
385
|
-
selector:
|
|
381
|
+
selector: "app-custom-upload",
|
|
386
382
|
standalone: true,
|
|
387
383
|
imports: [AngularTiptapEditorComponent],
|
|
388
384
|
template: `
|
|
@@ -391,19 +387,19 @@ import {
|
|
|
391
387
|
[imageUploadHandler]="uploadHandler"
|
|
392
388
|
(contentChange)="onContentChange($event)"
|
|
393
389
|
/>
|
|
394
|
-
|
|
390
|
+
`,
|
|
395
391
|
})
|
|
396
392
|
export class CustomUploadComponent {
|
|
397
393
|
private http = inject(HttpClient);
|
|
398
|
-
content =
|
|
394
|
+
content = "";
|
|
399
395
|
|
|
400
396
|
uploadHandler: ImageUploadHandler = (ctx) => {
|
|
401
397
|
const formData = new FormData();
|
|
402
|
-
formData.append(
|
|
398
|
+
formData.append("image", ctx.file);
|
|
403
399
|
|
|
404
|
-
return this.http
|
|
405
|
-
|
|
406
|
-
|
|
400
|
+
return this.http
|
|
401
|
+
.post<{ url: string }>("/api/upload", formData)
|
|
402
|
+
.pipe(map((result) => ({ src: result.url })));
|
|
407
403
|
};
|
|
408
404
|
|
|
409
405
|
onContentChange(newContent: string) {
|
|
@@ -417,10 +413,10 @@ export class CustomUploadComponent {
|
|
|
417
413
|
```typescript
|
|
418
414
|
uploadHandler: ImageUploadHandler = async (ctx) => {
|
|
419
415
|
const formData = new FormData();
|
|
420
|
-
formData.append(
|
|
416
|
+
formData.append("image", ctx.file);
|
|
421
417
|
|
|
422
418
|
const result = await firstValueFrom(
|
|
423
|
-
this.http.post<{ url: string }>(
|
|
419
|
+
this.http.post<{ url: string }>("/api/upload", formData),
|
|
424
420
|
);
|
|
425
421
|
|
|
426
422
|
return { src: result.url };
|
|
@@ -428,6 +424,7 @@ uploadHandler: ImageUploadHandler = async (ctx) => {
|
|
|
428
424
|
```
|
|
429
425
|
|
|
430
426
|
The `ImageUploadContext` provides:
|
|
427
|
+
|
|
431
428
|
- `file`: The original File object
|
|
432
429
|
- `width`: Processed image width
|
|
433
430
|
- `height`: Processed image height
|
|
@@ -438,7 +435,6 @@ The handler must return an `ImageUploadHandlerResult` with at least a `src` prop
|
|
|
438
435
|
|
|
439
436
|
---
|
|
440
437
|
|
|
441
|
-
|
|
442
438
|
### 📝 Word & Character Counting
|
|
443
439
|
|
|
444
440
|
Real-time content statistics:
|
|
@@ -471,38 +467,101 @@ Open [http://localhost:4200](http://localhost:4200) to view the demo.
|
|
|
471
467
|
|
|
472
468
|
#### Inputs
|
|
473
469
|
|
|
474
|
-
| Input
|
|
475
|
-
|
|
|
476
|
-
| `
|
|
477
|
-
| `
|
|
478
|
-
| `
|
|
479
|
-
| `
|
|
480
|
-
| `
|
|
481
|
-
| `
|
|
482
|
-
| `
|
|
483
|
-
| `
|
|
484
|
-
| `
|
|
485
|
-
| `
|
|
486
|
-
| `
|
|
487
|
-
| `
|
|
488
|
-
| `
|
|
489
|
-
| `
|
|
490
|
-
| `
|
|
491
|
-
| `
|
|
492
|
-
| `
|
|
493
|
-
| `
|
|
494
|
-
| `
|
|
495
|
-
| `
|
|
496
|
-
| `
|
|
497
|
-
| `
|
|
498
|
-
| `
|
|
499
|
-
| `
|
|
500
|
-
| `
|
|
501
|
-
| `
|
|
502
|
-
| `
|
|
503
|
-
| `
|
|
504
|
-
| `
|
|
470
|
+
| Input | Type | Default | Description |
|
|
471
|
+
| --------------------- | ------------------------------------------------ | ------------------- | --------------------------------------------- |
|
|
472
|
+
| `config` | `AteEditorConfig` | `{}` | **Global configuration object** (Recommended) |
|
|
473
|
+
| `content` | `string` | `""` | Initial HTML content |
|
|
474
|
+
| `placeholder` | `string` | `"Start typing..."` | Placeholder text (overrides config) |
|
|
475
|
+
| `locale` | `'en' \| 'fr'` | Auto-detect | Editor language (overrides config) |
|
|
476
|
+
| `editable` | `boolean` | `true` | Whether editor is editable |
|
|
477
|
+
| `height` | `string` | `undefined` | Editor height (e.g. '400px', 'auto') |
|
|
478
|
+
| `maxHeight` | `string` | `undefined` | Maximum height (e.g. '80vh') |
|
|
479
|
+
| `minHeight` | `string` | `undefined` | Minimum height |
|
|
480
|
+
| `maxCharacters` | `number` | `undefined` | Character limit |
|
|
481
|
+
| `fillContainer` | `boolean` | `false` | Fill parent container height |
|
|
482
|
+
| `autofocus` | `boolean \| 'start' \| 'end' \| 'all' \| number` | `false` | Auto-focus behavior |
|
|
483
|
+
| `disabled` | `boolean` | `false` | Disabled state (for forms) |
|
|
484
|
+
| `spellcheck` | `boolean` | `true` | Enable browser spellcheck |
|
|
485
|
+
| `showToolbar` | `boolean` | `true` | Show toolbar |
|
|
486
|
+
| `showFooter` | `boolean` | `true` | Show footer (counters) |
|
|
487
|
+
| `showBubbleMenu` | `boolean` | `true` | Show text bubble menu |
|
|
488
|
+
| `showImageBubbleMenu` | `boolean` | `true` | Show image bubble menu |
|
|
489
|
+
| `showTableMenu` | `boolean` | `true` | Show table bubble menu |
|
|
490
|
+
| `showCellMenu` | `boolean` | `true` | Show cell bubble menu |
|
|
491
|
+
| `enableSlashCommands` | `boolean` | `true` | Enable slash commands functionality |
|
|
492
|
+
| `enableOfficePaste` | `boolean` | `true` | Enable smart Office pasting |
|
|
493
|
+
| `showCharacterCount` | `boolean` | `true` | Show character counter |
|
|
494
|
+
| `showWordCount` | `boolean` | `true` | Show word counter |
|
|
495
|
+
| `toolbar` | `ToolbarConfig` | All enabled | Detailed toolbar configuration |
|
|
496
|
+
| `bubbleMenu` | `BubbleMenuConfig` | All enabled | Detailed bubble menu configuration |
|
|
497
|
+
| `slashCommands` | `SlashCommandsConfig` | All enabled | Detailed slash commands config |
|
|
498
|
+
| `imageUploadHandler` | `ImageUploadHandler` | `undefined` | Custom image upload function |
|
|
499
|
+
| `stateCalculators` | `StateCalculator[]` | `[]` | Custom reactive state logic |
|
|
500
|
+
| `tiptapExtensions` | `(Extension \| Node \| Mark)[]` | `[]` | Additional Tiptap extensions |
|
|
501
|
+
| `tiptapOptions` | `Partial<EditorOptions>` | `{}` | Additional Tiptap editor options |
|
|
502
|
+
|
|
503
|
+
> **Note on Precedence**: Values provided in individual inputs (e.g., `[editable]="false"`) always take precedence over values defined inside the `[config]` object.
|
|
504
|
+
|
|
505
|
+
#### AteEditorConfig Reference
|
|
506
|
+
|
|
507
|
+
The `AteEditorConfig` nested structure allows for complex configurations while remaining flat for core settings:
|
|
505
508
|
|
|
509
|
+
```typescript
|
|
510
|
+
export interface AteEditorConfig {
|
|
511
|
+
// Core Settings
|
|
512
|
+
theme?: "light" | "dark" | "auto";
|
|
513
|
+
height?: string;
|
|
514
|
+
minHeight?: string;
|
|
515
|
+
maxHeight?: string;
|
|
516
|
+
fillContainer?: boolean;
|
|
517
|
+
autofocus?: "start" | "end" | "all" | boolean | number;
|
|
518
|
+
placeholder?: string;
|
|
519
|
+
editable?: boolean;
|
|
520
|
+
disabled?: boolean;
|
|
521
|
+
locale?: string;
|
|
522
|
+
spellcheck?: boolean;
|
|
523
|
+
enableOfficePaste?: boolean;
|
|
524
|
+
|
|
525
|
+
// Visibility Options
|
|
526
|
+
showToolbar?: boolean;
|
|
527
|
+
showFooter?: boolean;
|
|
528
|
+
showCharacterCount?: boolean;
|
|
529
|
+
showWordCount?: boolean;
|
|
530
|
+
showEditToggle?: boolean;
|
|
531
|
+
showBubbleMenu?: boolean;
|
|
532
|
+
showImageBubbleMenu?: boolean;
|
|
533
|
+
showTableMenu?: boolean;
|
|
534
|
+
showCellMenu?: boolean;
|
|
535
|
+
enableSlashCommands?: boolean;
|
|
536
|
+
maxCharacters?: number;
|
|
537
|
+
|
|
538
|
+
// Complex Modules
|
|
539
|
+
toolbar?: ToolbarConfig;
|
|
540
|
+
bubbleMenu?: BubbleMenuConfig;
|
|
541
|
+
imageBubbleMenu?: ImageBubbleMenuConfig;
|
|
542
|
+
tableBubbleMenu?: TableBubbleMenuConfig;
|
|
543
|
+
cellBubbleMenu?: CellBubbleMenuConfig;
|
|
544
|
+
slashCommands?: SlashCommandsConfig;
|
|
545
|
+
imageUpload?: AteImageUploadConfig;
|
|
546
|
+
}
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
#### Image Upload Configuration
|
|
550
|
+
|
|
551
|
+
The `imageUpload` property in `AteEditorConfig` provides fine-grained control over the image processing pipeline:
|
|
552
|
+
|
|
553
|
+
```typescript
|
|
554
|
+
export interface AteImageUploadConfig {
|
|
555
|
+
/** Custom handler to upload files to a server */
|
|
556
|
+
handler?: ImageUploadHandler;
|
|
557
|
+
/** Maximum file size in bytes (default: 10MB) */
|
|
558
|
+
maxFileSize?: number;
|
|
559
|
+
/** Accepted file types (default: 'image/*') */
|
|
560
|
+
accept?: string;
|
|
561
|
+
/** Whether to automatically compress images before upload (default: true) */
|
|
562
|
+
autoCompress?: boolean;
|
|
563
|
+
}
|
|
564
|
+
```
|
|
506
565
|
|
|
507
566
|
#### Outputs
|
|
508
567
|
|
|
@@ -514,7 +573,6 @@ Open [http://localhost:4200](http://localhost:4200) to view the demo.
|
|
|
514
573
|
| `editorFocus` | `{editor, event}` | Emitted when editor gains focus |
|
|
515
574
|
| `editorBlur` | `{editor, event}` | Emitted when editor loses focus |
|
|
516
575
|
|
|
517
|
-
|
|
518
576
|
## 🌍 Internationalization
|
|
519
577
|
|
|
520
578
|
The editor comes with built-in support for **English (en)** and **French (fr)**, featuring automatic browser language detection.
|
|
@@ -544,14 +602,13 @@ export class MyComponent {
|
|
|
544
602
|
toolbar: { bold: 'Negrita', italic: 'Cursiva', ... },
|
|
545
603
|
editor: { placeholder: 'Empieza a escribir...' }
|
|
546
604
|
});
|
|
547
|
-
|
|
605
|
+
|
|
548
606
|
// Switch to Spanish
|
|
549
607
|
this.i18nService.setLocale('es');
|
|
550
608
|
}
|
|
551
609
|
}
|
|
552
610
|
```
|
|
553
611
|
|
|
554
|
-
|
|
555
612
|
### 🎨 CSS Custom Properties
|
|
556
613
|
|
|
557
614
|
Customize the editor appearance using CSS variables with the `--ate-` prefix:
|
|
@@ -562,17 +619,25 @@ angular-tiptap-editor {
|
|
|
562
619
|
--ate-primary: #2563eb;
|
|
563
620
|
--ate-primary-contrast: #ffffff;
|
|
564
621
|
--ate-primary-light: color-mix(in srgb, var(--ate-primary), transparent 90%);
|
|
565
|
-
--ate-primary-lighter: color-mix(
|
|
566
|
-
|
|
567
|
-
|
|
622
|
+
--ate-primary-lighter: color-mix(
|
|
623
|
+
in srgb,
|
|
624
|
+
var(--ate-primary),
|
|
625
|
+
transparent 95%
|
|
626
|
+
);
|
|
627
|
+
--ate-primary-light-alpha: color-mix(
|
|
628
|
+
in srgb,
|
|
629
|
+
var(--ate-primary),
|
|
630
|
+
transparent 85%
|
|
631
|
+
);
|
|
632
|
+
|
|
568
633
|
--ate-surface: #ffffff;
|
|
569
634
|
--ate-surface-secondary: #f8f9fa;
|
|
570
635
|
--ate-surface-tertiary: #f1f5f9;
|
|
571
|
-
|
|
636
|
+
|
|
572
637
|
--ate-text: #2d3748;
|
|
573
638
|
--ate-text-secondary: #64748b;
|
|
574
639
|
--ate-text-muted: #a0aec0;
|
|
575
|
-
|
|
640
|
+
|
|
576
641
|
--ate-border: #e2e8f0;
|
|
577
642
|
|
|
578
643
|
/* And More... */
|
|
@@ -621,7 +686,6 @@ angular-tiptap-editor {
|
|
|
621
686
|
}
|
|
622
687
|
```
|
|
623
688
|
|
|
624
|
-
|
|
625
689
|
### ⚡ Reactive State & OnPush
|
|
626
690
|
|
|
627
691
|
The library exposes a reactive `editorState` signal via the `EditorCommandsService`. This signal contains everything you need to build custom UIs around the editor:
|
|
@@ -711,7 +775,6 @@ This runs the library in watch mode and starts the demo application.
|
|
|
711
775
|
- `npm run watch:lib` - Watch library changes
|
|
712
776
|
- `npm run dev` - Development mode (watch + serve)
|
|
713
777
|
|
|
714
|
-
|
|
715
778
|
## 📝 License
|
|
716
779
|
|
|
717
780
|
MIT License - see [LICENSE](LICENSE) file for details.
|
|
@@ -733,10 +796,8 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
733
796
|
|
|
734
797
|
### Latest Updates
|
|
735
798
|
|
|
736
|
-
- ✅ **
|
|
737
|
-
- ✅ **
|
|
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.
|
|
799
|
+
- ✅ **Unified Configuration**: New unified `AteEditorConfig` system for cleaner, type-safe editor setup.
|
|
800
|
+
- ✅ **Enhanced Image Upload**: Advanced image handling with custom upload handlers and auto-compression.
|
|
740
801
|
- ✅ **Refactored Link Management**: Dedicated link bubble menu with smart UI anchoring and real-time URL sync.
|
|
741
802
|
|
|
742
803
|
---
|