@flogeez/angular-tiptap-editor 0.3.5 → 0.3.7
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/README.md
CHANGED
|
@@ -229,6 +229,80 @@ Professional image management:
|
|
|
229
229
|
- **Auto-Compression**: Images automatically compressed (max 1920x1080)
|
|
230
230
|
- **Resizable**: Images can be resized with handles
|
|
231
231
|
- **Bubble Menu**: Context menu for image operations
|
|
232
|
+
- **Custom Upload Handler**: Upload images to your own server instead of base64
|
|
233
|
+
|
|
234
|
+
#### Custom Image Upload Handler
|
|
235
|
+
|
|
236
|
+
By default, images are converted to base64 and embedded directly in the HTML content. You can provide a custom upload handler to upload images to your own server (S3, Cloudinary, custom API, etc.) and use the returned URL instead.
|
|
237
|
+
|
|
238
|
+
The handler can return either an **Observable** or a **Promise**.
|
|
239
|
+
|
|
240
|
+
#### Using Observable (recommended for Angular)
|
|
241
|
+
|
|
242
|
+
```typescript
|
|
243
|
+
import { Component, inject } from '@angular/core';
|
|
244
|
+
import { HttpClient } from '@angular/common/http';
|
|
245
|
+
import { map } from 'rxjs/operators';
|
|
246
|
+
import {
|
|
247
|
+
AngularTiptapEditorComponent,
|
|
248
|
+
ImageUploadHandler
|
|
249
|
+
} from '@flogeez/angular-tiptap-editor';
|
|
250
|
+
|
|
251
|
+
@Component({
|
|
252
|
+
selector: 'app-custom-upload',
|
|
253
|
+
standalone: true,
|
|
254
|
+
imports: [AngularTiptapEditorComponent],
|
|
255
|
+
template: `
|
|
256
|
+
<angular-tiptap-editor
|
|
257
|
+
[content]="content"
|
|
258
|
+
[imageUploadHandler]="uploadHandler"
|
|
259
|
+
(contentChange)="onContentChange($event)"
|
|
260
|
+
/>
|
|
261
|
+
`
|
|
262
|
+
})
|
|
263
|
+
export class CustomUploadComponent {
|
|
264
|
+
private http = inject(HttpClient);
|
|
265
|
+
content = '';
|
|
266
|
+
|
|
267
|
+
uploadHandler: ImageUploadHandler = (ctx) => {
|
|
268
|
+
const formData = new FormData();
|
|
269
|
+
formData.append('image', ctx.file);
|
|
270
|
+
|
|
271
|
+
return this.http.post<{ url: string }>('/api/upload', formData).pipe(
|
|
272
|
+
map(result => ({ src: result.url }))
|
|
273
|
+
);
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
onContentChange(newContent: string) {
|
|
277
|
+
this.content = newContent;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
#### Using Promise (async/await)
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
uploadHandler: ImageUploadHandler = async (ctx) => {
|
|
286
|
+
const formData = new FormData();
|
|
287
|
+
formData.append('image', ctx.file);
|
|
288
|
+
|
|
289
|
+
const result = await firstValueFrom(
|
|
290
|
+
this.http.post<{ url: string }>('/api/upload', formData)
|
|
291
|
+
);
|
|
292
|
+
|
|
293
|
+
return { src: result.url };
|
|
294
|
+
};
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
The `ImageUploadContext` provides:
|
|
298
|
+
- `file`: The original File object
|
|
299
|
+
- `width`: Processed image width
|
|
300
|
+
- `height`: Processed image height
|
|
301
|
+
- `type`: MIME type (e.g., 'image/jpeg')
|
|
302
|
+
- `base64`: Base64 data URL of the processed image (fallback)
|
|
303
|
+
|
|
304
|
+
The handler must return an `ImageUploadHandlerResult` with at least a `src` property containing the image URL.
|
|
305
|
+
|
|
232
306
|
|
|
233
307
|
### 📝 Word & Character Counting
|
|
234
308
|
|
|
@@ -262,22 +336,27 @@ Open [http://localhost:4200](http://localhost:4200) to view the demo.
|
|
|
262
336
|
|
|
263
337
|
#### Inputs
|
|
264
338
|
|
|
265
|
-
| Input | Type | Default | Description
|
|
266
|
-
| -------------------- | --------------------- | ------------------- |
|
|
267
|
-
| `content` | `string` | `""` | Initial HTML content
|
|
268
|
-
| `placeholder` | `string` | `"Start typing..."` | Placeholder text
|
|
269
|
-
| `locale` | `'en' \| 'fr'` | Auto-detect | Editor language
|
|
270
|
-
| `editable` | `boolean` | `true` | Whether editor is editable
|
|
271
|
-
| `height` | `number` | `undefined` | Fixed height in pixels
|
|
272
|
-
| `maxHeight` | `number` | `undefined` | Maximum height in pixels
|
|
273
|
-
| `minHeight` | `number` | `200` | Minimum height in pixels
|
|
274
|
-
| `
|
|
275
|
-
| `
|
|
276
|
-
| `
|
|
277
|
-
| `
|
|
278
|
-
| `
|
|
279
|
-
| `
|
|
280
|
-
| `
|
|
339
|
+
| Input | Type | Default | Description |
|
|
340
|
+
| -------------------- | --------------------- | ------------------- | ----------------------------- |
|
|
341
|
+
| `content` | `string` | `""` | Initial HTML content |
|
|
342
|
+
| `placeholder` | `string` | `"Start typing..."` | Placeholder text |
|
|
343
|
+
| `locale` | `'en' \| 'fr'` | Auto-detect | Editor language |
|
|
344
|
+
| `editable` | `boolean` | `true` | Whether editor is editable |
|
|
345
|
+
| `height` | `number` | `undefined` | Fixed height in pixels |
|
|
346
|
+
| `maxHeight` | `number` | `undefined` | Maximum height in pixels |
|
|
347
|
+
| `minHeight` | `number` | `200` | Minimum height in pixels |
|
|
348
|
+
| `fillContainer` | `boolean` | `false` | Fill parent container height |
|
|
349
|
+
| `autofocus` | `boolean \| 'start' \| 'end' \| 'all'` | `false` | Auto-focus behavior |
|
|
350
|
+
| `showToolbar` | `boolean` | `true` | Show toolbar |
|
|
351
|
+
| `showBubbleMenu` | `boolean` | `true` | Show bubble menu |
|
|
352
|
+
| `showCharacterCount` | `boolean` | `true` | Show character counter |
|
|
353
|
+
| `showWordCount` | `boolean` | `true` | Show word counter |
|
|
354
|
+
| `toolbar` | `ToolbarConfig` | All enabled | Toolbar configuration |
|
|
355
|
+
| `bubbleMenu` | `BubbleMenuConfig` | All enabled | Bubble menu configuration |
|
|
356
|
+
| `slashCommands` | `SlashCommandsConfig` | All enabled | Slash commands configuration |
|
|
357
|
+
| `imageUploadHandler` | `ImageUploadHandler` | `undefined` | Custom image upload function |
|
|
358
|
+
|
|
359
|
+
|
|
281
360
|
|
|
282
361
|
#### Outputs
|
|
283
362
|
|
|
@@ -446,6 +525,7 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
446
525
|
|
|
447
526
|
### Latest Updates
|
|
448
527
|
|
|
528
|
+
- ✅ **Custom Image Upload Handler**: Upload images to your own server (S3, Cloudinary, etc.)
|
|
449
529
|
- ✅ **Table Support**: Full table management with bubble menus
|
|
450
530
|
- ✅ **Slash Commands**: Intuitive content insertion commands
|
|
451
531
|
- ✅ **Word/Character Count**: Real-time counting with proper pluralization
|
|
@@ -454,6 +534,7 @@ Contributions are welcome! Please feel free to submit a Pull Request.
|
|
|
454
534
|
- ✅ **Office Paste**: Clean pasting from Microsoft Office applications
|
|
455
535
|
- ✅ **Enhanced i18n**: Improved internationalization with better architecture
|
|
456
536
|
|
|
537
|
+
|
|
457
538
|
---
|
|
458
539
|
|
|
459
540
|
Made with ❤️ by [FloGeez](https://github.com/FloGeez)
|
|
@@ -20,10 +20,10 @@ import TableCell from '@tiptap/extension-table-cell';
|
|
|
20
20
|
import TableHeader from '@tiptap/extension-table-header';
|
|
21
21
|
import tippy from 'tippy.js';
|
|
22
22
|
import { CellSelection } from '@tiptap/pm/tables';
|
|
23
|
+
import { isObservable, firstValueFrom, concat, defer, of, tap } from 'rxjs';
|
|
23
24
|
import { CommonModule } from '@angular/common';
|
|
24
25
|
import { Plugin as Plugin$1, PluginKey as PluginKey$1 } from 'prosemirror-state';
|
|
25
26
|
import { NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
|
|
26
|
-
import { concat, defer, of, tap } from 'rxjs';
|
|
27
27
|
|
|
28
28
|
const ResizableImage = Node.create({
|
|
29
29
|
name: "resizableImage",
|
|
@@ -1010,6 +1010,23 @@ class ImageService {
|
|
|
1010
1010
|
this.isUploading = signal(false);
|
|
1011
1011
|
this.uploadProgress = signal(0);
|
|
1012
1012
|
this.uploadMessage = signal("");
|
|
1013
|
+
/**
|
|
1014
|
+
* Custom upload handler for images.
|
|
1015
|
+
* When set, this handler will be called instead of the default base64 conversion.
|
|
1016
|
+
* This allows users to implement their own image storage logic.
|
|
1017
|
+
*
|
|
1018
|
+
* @example
|
|
1019
|
+
* ```typescript
|
|
1020
|
+
* imageService.uploadHandler = async (context) => {
|
|
1021
|
+
* const formData = new FormData();
|
|
1022
|
+
* formData.append('image', context.file);
|
|
1023
|
+
* const response = await fetch('/api/upload', { method: 'POST', body: formData });
|
|
1024
|
+
* const data = await response.json();
|
|
1025
|
+
* return { src: data.url };
|
|
1026
|
+
* };
|
|
1027
|
+
* ```
|
|
1028
|
+
*/
|
|
1029
|
+
this.uploadHandler = null;
|
|
1013
1030
|
// Référence à l'éditeur pour les mises à jour
|
|
1014
1031
|
this.currentEditor = null;
|
|
1015
1032
|
}
|
|
@@ -1261,6 +1278,34 @@ class ImageService {
|
|
|
1261
1278
|
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
1262
1279
|
const result = await this.compressImage(file, options?.quality || 0.8, options?.maxWidth || 1920, options?.maxHeight || 1080);
|
|
1263
1280
|
this.uploadProgress.set(80);
|
|
1281
|
+
// Si un handler personnalisé est défini, l'utiliser pour l'upload
|
|
1282
|
+
if (this.uploadHandler) {
|
|
1283
|
+
this.uploadMessage.set("Upload vers le serveur...");
|
|
1284
|
+
this.forceEditorUpdate();
|
|
1285
|
+
try {
|
|
1286
|
+
const handlerResponse = this.uploadHandler({
|
|
1287
|
+
file,
|
|
1288
|
+
width: result.width || 0,
|
|
1289
|
+
height: result.height || 0,
|
|
1290
|
+
type: result.type,
|
|
1291
|
+
base64: result.src,
|
|
1292
|
+
});
|
|
1293
|
+
// Convertir Observable en Promise si nécessaire
|
|
1294
|
+
const handlerResult = isObservable(handlerResponse)
|
|
1295
|
+
? await firstValueFrom(handlerResponse)
|
|
1296
|
+
: await handlerResponse;
|
|
1297
|
+
// Remplacer le src base64 par l'URL retournée par le handler
|
|
1298
|
+
result.src = handlerResult.src;
|
|
1299
|
+
// Appliquer les overrides optionnels du handler
|
|
1300
|
+
if (handlerResult.alt) {
|
|
1301
|
+
result.name = handlerResult.alt;
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
catch (handlerError) {
|
|
1305
|
+
console.error("Erreur lors de l'upload personnalisé:", handlerError);
|
|
1306
|
+
throw handlerError;
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1264
1309
|
this.uploadMessage.set(actionMessage);
|
|
1265
1310
|
this.forceEditorUpdate();
|
|
1266
1311
|
// Petit délai pour l'action
|
|
@@ -4604,13 +4649,13 @@ const DEFAULT_SLASH_COMMANDS = {
|
|
|
4604
4649
|
};
|
|
4605
4650
|
class AngularTiptapEditorComponent {
|
|
4606
4651
|
constructor() {
|
|
4607
|
-
// Nouveaux inputs avec signal
|
|
4608
4652
|
this.content = input("");
|
|
4609
4653
|
this.placeholder = input("");
|
|
4610
4654
|
this.editable = input(true);
|
|
4611
4655
|
this.minHeight = input(200);
|
|
4612
4656
|
this.height = input(undefined);
|
|
4613
4657
|
this.maxHeight = input(undefined);
|
|
4658
|
+
this.fillContainer = input(false);
|
|
4614
4659
|
this.showToolbar = input(true);
|
|
4615
4660
|
this.showCharacterCount = input(true);
|
|
4616
4661
|
this.maxCharacters = input(undefined);
|
|
@@ -4628,6 +4673,26 @@ class AngularTiptapEditorComponent {
|
|
|
4628
4673
|
this.toolbar = input({});
|
|
4629
4674
|
// Nouveau input pour la configuration de l'upload d'images
|
|
4630
4675
|
this.imageUpload = input({});
|
|
4676
|
+
/**
|
|
4677
|
+
* Custom handler for image uploads.
|
|
4678
|
+
* When provided, images will be processed through this handler instead of being converted to base64.
|
|
4679
|
+
* This allows you to upload images to your own server/storage and use the returned URL.
|
|
4680
|
+
*
|
|
4681
|
+
* @example
|
|
4682
|
+
* ```typescript
|
|
4683
|
+
* myUploadHandler: ImageUploadHandler = async (context) => {
|
|
4684
|
+
* const formData = new FormData();
|
|
4685
|
+
* formData.append('image', context.file);
|
|
4686
|
+
* const response = await fetch('/api/upload', { method: 'POST', body: formData });
|
|
4687
|
+
* const data = await response.json();
|
|
4688
|
+
* return { src: data.imageUrl };
|
|
4689
|
+
* };
|
|
4690
|
+
*
|
|
4691
|
+
* // In template:
|
|
4692
|
+
* // <angular-tiptap-editor [imageUploadHandler]="myUploadHandler" />
|
|
4693
|
+
* ```
|
|
4694
|
+
*/
|
|
4695
|
+
this.imageUploadHandler = input(undefined);
|
|
4631
4696
|
// Nouveaux outputs
|
|
4632
4697
|
this.contentChange = output();
|
|
4633
4698
|
this.editorCreated = output();
|
|
@@ -4751,6 +4816,11 @@ class AngularTiptapEditorComponent {
|
|
|
4751
4816
|
this.editorCommandsService.setEditable(currentEditor, isEditable);
|
|
4752
4817
|
}
|
|
4753
4818
|
});
|
|
4819
|
+
// Effect pour synchroniser le handler d'upload d'images avec le service
|
|
4820
|
+
effect(() => {
|
|
4821
|
+
const handler = this.imageUploadHandler();
|
|
4822
|
+
this.imageService.uploadHandler = handler || null;
|
|
4823
|
+
});
|
|
4754
4824
|
// Effect pour la détection du survol des tables
|
|
4755
4825
|
effect(() => {
|
|
4756
4826
|
const currentEditor = this.editor();
|
|
@@ -5007,8 +5077,8 @@ class AngularTiptapEditorComponent {
|
|
|
5007
5077
|
}
|
|
5008
5078
|
}
|
|
5009
5079
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AngularTiptapEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5010
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: AngularTiptapEditorComponent, isStandalone: true, selector: "angular-tiptap-editor", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showCharacterCount: { classPropertyName: "showCharacterCount", publicName: "showCharacterCount", isSignal: true, isRequired: false, transformFunction: null }, maxCharacters: { classPropertyName: "maxCharacters", publicName: "maxCharacters", isSignal: true, isRequired: false, transformFunction: null }, enableOfficePaste: { classPropertyName: "enableOfficePaste", publicName: "enableOfficePaste", isSignal: true, isRequired: false, transformFunction: null }, enableSlashCommands: { classPropertyName: "enableSlashCommands", publicName: "enableSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, slashCommandsConfig: { classPropertyName: "slashCommandsConfig", publicName: "slashCommandsConfig", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, showBubbleMenu: { classPropertyName: "showBubbleMenu", publicName: "showBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, bubbleMenu: { classPropertyName: "bubbleMenu", publicName: "bubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showImageBubbleMenu: { classPropertyName: "showImageBubbleMenu", publicName: "showImageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, imageBubbleMenu: { classPropertyName: "imageBubbleMenu", publicName: "imageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentChange: "contentChange", editorCreated: "editorCreated", editorUpdate: "editorUpdate", editorFocus: "editorFocus", editorBlur: "editorBlur" }, viewQueries: [{ propertyName: "editorElement", first: true, predicate: ["editorElement"], descendants: true, isSignal: true }], hostDirectives: [{ directive: NoopValueAccessorDirective }], ngImport: i0, template: `
|
|
5011
|
-
<div class="tiptap-editor">
|
|
5080
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: AngularTiptapEditorComponent, isStandalone: true, selector: "angular-tiptap-editor", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, fillContainer: { classPropertyName: "fillContainer", publicName: "fillContainer", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showCharacterCount: { classPropertyName: "showCharacterCount", publicName: "showCharacterCount", isSignal: true, isRequired: false, transformFunction: null }, maxCharacters: { classPropertyName: "maxCharacters", publicName: "maxCharacters", isSignal: true, isRequired: false, transformFunction: null }, enableOfficePaste: { classPropertyName: "enableOfficePaste", publicName: "enableOfficePaste", isSignal: true, isRequired: false, transformFunction: null }, enableSlashCommands: { classPropertyName: "enableSlashCommands", publicName: "enableSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, slashCommandsConfig: { classPropertyName: "slashCommandsConfig", publicName: "slashCommandsConfig", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, showBubbleMenu: { classPropertyName: "showBubbleMenu", publicName: "showBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, bubbleMenu: { classPropertyName: "bubbleMenu", publicName: "bubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showImageBubbleMenu: { classPropertyName: "showImageBubbleMenu", publicName: "showImageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, imageBubbleMenu: { classPropertyName: "imageBubbleMenu", publicName: "imageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null }, imageUploadHandler: { classPropertyName: "imageUploadHandler", publicName: "imageUploadHandler", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentChange: "contentChange", editorCreated: "editorCreated", editorUpdate: "editorUpdate", editorFocus: "editorFocus", editorBlur: "editorBlur" }, host: { properties: { "class.fill-container": "fillContainer()" } }, viewQueries: [{ propertyName: "editorElement", first: true, predicate: ["editorElement"], descendants: true, isSignal: true }], hostDirectives: [{ directive: NoopValueAccessorDirective }], ngImport: i0, template: `
|
|
5081
|
+
<div class="tiptap-editor" [class.fill-container]="fillContainer()">
|
|
5012
5082
|
<!-- Toolbar -->
|
|
5013
5083
|
@if (showToolbar() && editor()) {
|
|
5014
5084
|
<tiptap-toolbar [editor]="editor()!" [config]="toolbarConfig()">
|
|
@@ -5093,11 +5163,13 @@ class AngularTiptapEditorComponent {
|
|
|
5093
5163
|
</div>
|
|
5094
5164
|
}
|
|
5095
5165
|
</div>
|
|
5096
|
-
`, isInline: true, styles: [".tiptap-editor{border:2px solid #e2e8f0;border-radius:8px;background:#fff;overflow:hidden;transition:border-color .2s ease}.tiptap-editor:focus-within{border-color:#3182ce}.tiptap-content{padding:16px;min-height:var(--editor-min-height, 200px);height:var(--editor-height, auto);max-height:var(--editor-max-height, none);overflow-y:var(--editor-overflow, visible);outline:none;position:relative}.tiptap-content.drag-over{background:#f0f8ff;border:2px dashed #3182ce}.character-count{padding:8px 16px;font-size:12px;color:#718096;text-align:right;border-top:1px solid #e2e8f0;background:#f8f9fa}.image-upload-container{position:relative;display:inline-block}:host ::ng-deep .ProseMirror{outline:none;line-height:1.6;color:#2d3748;min-height:100%;height:100%;word-wrap:break-word;overflow-wrap:break-word}:host ::ng-deep .ProseMirror h1{font-size:2em;font-weight:700;margin-top:0;margin-bottom:.5em}:host ::ng-deep .ProseMirror h2{font-size:1.5em;font-weight:700;margin-top:1em;margin-bottom:.5em}:host ::ng-deep .ProseMirror h3{font-size:1.25em;font-weight:700;margin-top:1em;margin-bottom:.5em}:host ::ng-deep .ProseMirror p{margin:.5em 0}:host ::ng-deep .ProseMirror ul,:host ::ng-deep .ProseMirror ol{padding-left:2em;margin:.5em 0}:host ::ng-deep .ProseMirror blockquote{border-left:4px solid #e2e8f0;margin:1em 0;font-style:italic;background:#f8f9fa;padding:.5em 1em;border-radius:0 4px 4px 0}:host ::ng-deep .ProseMirror code{background:#f1f5f9;padding:.2em .4em;border-radius:3px;font-family:Monaco,Consolas,monospace;font-size:.9em}:host ::ng-deep .ProseMirror pre{background:#1a202c;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;margin:1em 0}:host ::ng-deep .ProseMirror pre code{background:none;color:inherit;padding:0}:host ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:#a0aec0;pointer-events:none;float:left;height:0}:host ::ng-deep .ProseMirror[contenteditable=false]{pointer-events:none}:host ::ng-deep .ProseMirror[contenteditable=false] img{cursor:default;pointer-events:none}:host ::ng-deep .ProseMirror[contenteditable=false] img:hover{transform:none;box-shadow:0 2px 8px #0000001a}:host ::ng-deep .ProseMirror[contenteditable=false] img.ProseMirror-selectednode{outline:none}:host ::ng-deep .ProseMirror img{position:relative;display:inline-block;max-width:100%;height:auto;cursor:pointer;transition:all .2s ease;border:2px solid transparent;border-radius:8px}:host ::ng-deep .ProseMirror img:hover{border-color:#e2e8f0;box-shadow:0 2px 4px #0000001a}:host ::ng-deep .ProseMirror img.ProseMirror-selectednode{border-color:#3182ce;box-shadow:0 0 0 3px #3182ce1a;transition:all .2s ease}:host ::ng-deep .ProseMirror .tiptap-image{max-width:100%;height:auto;border-radius:16px;box-shadow:0 4px 20px #00000014;margin:.5em 0;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);display:block;filter:brightness(1) contrast(1)}:host ::ng-deep .ProseMirror .tiptap-image:hover{box-shadow:0 8px 30px #0000001f;filter:brightness(1.02) contrast(1.02)}:host ::ng-deep .ProseMirror .tiptap-image.ProseMirror-selectednode{outline:2px solid #6366f1;outline-offset:2px;border-radius:16px;box-shadow:0 0 0 4px #6366f11a}:host ::ng-deep .image-container{margin:.5em 0;text-align:center;border-radius:16px;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1)}:host ::ng-deep .image-container.image-align-left{text-align:left}:host ::ng-deep .image-container.image-align-center{text-align:center}:host ::ng-deep .image-container.image-align-right{text-align:right}:host ::ng-deep .image-container img{display:inline-block;max-width:100%;height:auto;border-radius:16px}:host ::ng-deep .resizable-image-container{position:relative;display:inline-block;margin:.5em 0}:host ::ng-deep .resize-controls{position:absolute;inset:0;pointer-events:none;z-index:1000}:host ::ng-deep .resize-handle{position:absolute;width:12px;height:12px;background:#3b82f6;border:2px solid white;border-radius:50%;pointer-events:all;cursor:pointer;z-index:1001;transition:all .15s ease;box-shadow:0 2px 6px #0003}:host ::ng-deep .resize-handle:hover{background:#2563eb;box-shadow:0 3px 8px #0000004d}:host ::ng-deep .resize-handle:active{background:#1d4ed8}:host ::ng-deep .resize-handle-n:hover,:host ::ng-deep .resize-handle-s:hover{transform:translate(-50%) scale(1.2)}:host ::ng-deep .resize-handle-w:hover,:host ::ng-deep .resize-handle-e:hover{transform:translateY(-50%) scale(1.2)}:host ::ng-deep .resize-handle-n:active,:host ::ng-deep .resize-handle-s:active{transform:translate(-50%) scale(.9)}:host ::ng-deep .resize-handle-w:active,:host ::ng-deep .resize-handle-e:active{transform:translateY(-50%) scale(.9)}:host ::ng-deep .resize-handle-nw:hover,:host ::ng-deep .resize-handle-ne:hover,:host ::ng-deep .resize-handle-sw:hover,:host ::ng-deep .resize-handle-se:hover{transform:scale(1.2)}:host ::ng-deep .resize-handle-nw:active,:host ::ng-deep .resize-handle-ne:active,:host ::ng-deep .resize-handle-sw:active,:host ::ng-deep .resize-handle-se:active{transform:scale(.9)}:host ::ng-deep .resize-handle-nw{top:0;left:-6px;cursor:nw-resize}:host ::ng-deep .resize-handle-n{top:0;left:50%;transform:translate(-50%);cursor:n-resize}:host ::ng-deep .resize-handle-ne{top:0;right:-6px;cursor:ne-resize}:host ::ng-deep .resize-handle-w{top:50%;left:-6px;transform:translateY(-50%);cursor:w-resize}:host ::ng-deep .resize-handle-e{top:50%;right:-6px;transform:translateY(-50%);cursor:e-resize}:host ::ng-deep .resize-handle-sw{bottom:0;left:-6px;cursor:sw-resize}:host ::ng-deep .resize-handle-s{bottom:0;left:50%;transform:translate(-50%);cursor:s-resize}:host ::ng-deep .resize-handle-se{bottom:0;right:-6px;cursor:se-resize}:host ::ng-deep body.resizing{-webkit-user-select:none;user-select:none;cursor:crosshair}:host ::ng-deep body.resizing .ProseMirror{pointer-events:none}:host ::ng-deep body.resizing .ProseMirror .tiptap-image{pointer-events:none}:host ::ng-deep .image-size-info{position:absolute;bottom:-20px;left:50%;transform:translate(-50%);background:#000c;color:#fff;padding:2px 6px;border-radius:3px;font-size:11px;white-space:nowrap;opacity:0;transition:opacity .2s ease}:host ::ng-deep .image-container:hover .image-size-info{opacity:1}:host ::ng-deep .ProseMirror table{border-collapse:separate;border-spacing:0;margin:0;table-layout:fixed;width:100%;border-radius:8px;overflow:hidden}:host ::ng-deep .ProseMirror table td,:host ::ng-deep .ProseMirror table th{border:none;border-right:1px solid #e2e8f0;border-bottom:1px solid #e2e8f0;box-sizing:border-box;min-width:1em;padding:8px 12px;position:relative;vertical-align:top;background:#fff}:host ::ng-deep .ProseMirror table td:first-child,:host ::ng-deep .ProseMirror table th:first-child{border-left:1px solid #e2e8f0}:host ::ng-deep .ProseMirror table tr:first-child td,:host ::ng-deep .ProseMirror table tr:first-child th{border-top:1px solid #e2e8f0}:host ::ng-deep .ProseMirror table tr:first-child th:first-child{border-top-left-radius:8px}:host ::ng-deep .ProseMirror table tr:first-child th:last-child{border-top-right-radius:8px}:host ::ng-deep .ProseMirror table tr:last-child td:first-child{border-bottom-left-radius:8px}:host ::ng-deep .ProseMirror table tr:last-child td:last-child{border-bottom-right-radius:8px}:host ::ng-deep .ProseMirror table th{background:#f8f9fa;font-weight:600;color:#374151}:host ::ng-deep .ProseMirror table .selectedCell:after{background:#c8c8ff66;content:\"\";inset:0;pointer-events:none;position:absolute;z-index:2}:host ::ng-deep .ProseMirror table .column-resize-handle{position:absolute;right:-2px;top:0;bottom:0;width:4px;background-color:#6366f1;opacity:0;transition:opacity .2s ease}:host ::ng-deep .ProseMirror table:hover .column-resize-handle{opacity:1}:host ::ng-deep .ProseMirror table .column-resize-handle:hover{background-color:#4f46e5}:host ::ng-deep .ProseMirror .tableWrapper{overflow-x:auto;margin:1em 0;border-radius:8px}:host ::ng-deep .ProseMirror .tableWrapper table{margin:0;border-radius:8px;min-width:600px;overflow:hidden}:host ::ng-deep .ProseMirror table p{margin:0}:host ::ng-deep .ProseMirror table .selectedCell{background-color:#6366f11a}:host ::ng-deep .ProseMirror table th{background-color:#f8f9fa;font-weight:600;color:#374151;text-align:left}:host ::ng-deep .ProseMirror table tbody tr:nth-child(2n){background-color:#fafbfc}:host ::ng-deep .ProseMirror table tbody tr:hover{background-color:#f1f5f9}\n"], dependencies: [{ kind: "component", type: TiptapToolbarComponent, selector: "tiptap-toolbar", inputs: ["editor", "config"], outputs: ["imageUploaded", "imageError"] }, { kind: "component", type: TiptapImageUploadComponent, selector: "tiptap-image-upload", inputs: ["config"], outputs: ["imageSelected", "error"] }, { kind: "component", type: TiptapBubbleMenuComponent, selector: "tiptap-bubble-menu", inputs: ["editor", "config"] }, { kind: "component", type: TiptapImageBubbleMenuComponent, selector: "tiptap-image-bubble-menu", inputs: ["editor", "config"] }, { kind: "component", type: TiptapTableBubbleMenuComponent, selector: "tiptap-table-bubble-menu", inputs: ["editor", "config"] }, { kind: "component", type: TiptapCellBubbleMenuComponent, selector: "tiptap-cell-bubble-menu", inputs: ["editor", "config"] }, { kind: "component", type: TiptapSlashCommandsComponent, selector: "tiptap-slash-commands", inputs: ["editor", "config"], outputs: ["imageUploadRequested"] }] }); }
|
|
5166
|
+
`, isInline: true, styles: [":host(.fill-container){display:block;height:100%}.tiptap-editor{border:2px solid #e2e8f0;border-radius:8px;background:#fff;overflow:hidden;transition:border-color .2s ease}.tiptap-editor.fill-container{display:flex;flex-direction:column;height:100%}.tiptap-editor.fill-container .tiptap-content{flex:1;min-height:0;overflow-y:auto}.tiptap-editor:focus-within{border-color:#3182ce}.tiptap-content{padding:16px;min-height:var(--editor-min-height, 200px);height:var(--editor-height, auto);max-height:var(--editor-max-height, none);overflow-y:var(--editor-overflow, visible);outline:none;position:relative}.tiptap-content.drag-over{background:#f0f8ff;border:2px dashed #3182ce}.character-count{padding:8px 16px;font-size:12px;color:#718096;text-align:right;border-top:1px solid #e2e8f0;background:#f8f9fa}.image-upload-container{position:relative;display:inline-block}:host ::ng-deep .ProseMirror{outline:none;line-height:1.6;color:#2d3748;min-height:100%;height:100%;word-wrap:break-word;overflow-wrap:break-word}:host ::ng-deep .ProseMirror h1{font-size:2em;font-weight:700;margin-top:0;margin-bottom:.5em}:host ::ng-deep .ProseMirror h2{font-size:1.5em;font-weight:700;margin-top:1em;margin-bottom:.5em}:host ::ng-deep .ProseMirror h3{font-size:1.25em;font-weight:700;margin-top:1em;margin-bottom:.5em}:host ::ng-deep .ProseMirror p{margin:.5em 0}:host ::ng-deep .ProseMirror ul,:host ::ng-deep .ProseMirror ol{padding-left:2em;margin:.5em 0}:host ::ng-deep .ProseMirror blockquote{border-left:4px solid #e2e8f0;margin:1em 0;font-style:italic;background:#f8f9fa;padding:.5em 1em;border-radius:0 4px 4px 0}:host ::ng-deep .ProseMirror code{background:#f1f5f9;padding:.2em .4em;border-radius:3px;font-family:Monaco,Consolas,monospace;font-size:.9em}:host ::ng-deep .ProseMirror pre{background:#1a202c;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;margin:1em 0}:host ::ng-deep .ProseMirror pre code{background:none;color:inherit;padding:0}:host ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:#a0aec0;pointer-events:none;float:left;height:0}:host ::ng-deep .ProseMirror[contenteditable=false]{pointer-events:none}:host ::ng-deep .ProseMirror[contenteditable=false] img{cursor:default;pointer-events:none}:host ::ng-deep .ProseMirror[contenteditable=false] img:hover{transform:none;box-shadow:0 2px 8px #0000001a}:host ::ng-deep .ProseMirror[contenteditable=false] img.ProseMirror-selectednode{outline:none}:host ::ng-deep .ProseMirror img{position:relative;display:inline-block;max-width:100%;height:auto;cursor:pointer;transition:all .2s ease;border:2px solid transparent;border-radius:8px}:host ::ng-deep .ProseMirror img:hover{border-color:#e2e8f0;box-shadow:0 2px 4px #0000001a}:host ::ng-deep .ProseMirror img.ProseMirror-selectednode{border-color:#3182ce;box-shadow:0 0 0 3px #3182ce1a;transition:all .2s ease}:host ::ng-deep .ProseMirror .tiptap-image{max-width:100%;height:auto;border-radius:16px;box-shadow:0 4px 20px #00000014;margin:.5em 0;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);display:block;filter:brightness(1) contrast(1)}:host ::ng-deep .ProseMirror .tiptap-image:hover{box-shadow:0 8px 30px #0000001f;filter:brightness(1.02) contrast(1.02)}:host ::ng-deep .ProseMirror .tiptap-image.ProseMirror-selectednode{outline:2px solid #6366f1;outline-offset:2px;border-radius:16px;box-shadow:0 0 0 4px #6366f11a}:host ::ng-deep .image-container{margin:.5em 0;text-align:center;border-radius:16px;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1)}:host ::ng-deep .image-container.image-align-left{text-align:left}:host ::ng-deep .image-container.image-align-center{text-align:center}:host ::ng-deep .image-container.image-align-right{text-align:right}:host ::ng-deep .image-container img{display:inline-block;max-width:100%;height:auto;border-radius:16px}:host ::ng-deep .resizable-image-container{position:relative;display:inline-block;margin:.5em 0}:host ::ng-deep .resize-controls{position:absolute;inset:0;pointer-events:none;z-index:1000}:host ::ng-deep .resize-handle{position:absolute;width:12px;height:12px;background:#3b82f6;border:2px solid white;border-radius:50%;pointer-events:all;cursor:pointer;z-index:1001;transition:all .15s ease;box-shadow:0 2px 6px #0003}:host ::ng-deep .resize-handle:hover{background:#2563eb;box-shadow:0 3px 8px #0000004d}:host ::ng-deep .resize-handle:active{background:#1d4ed8}:host ::ng-deep .resize-handle-n:hover,:host ::ng-deep .resize-handle-s:hover{transform:translate(-50%) scale(1.2)}:host ::ng-deep .resize-handle-w:hover,:host ::ng-deep .resize-handle-e:hover{transform:translateY(-50%) scale(1.2)}:host ::ng-deep .resize-handle-n:active,:host ::ng-deep .resize-handle-s:active{transform:translate(-50%) scale(.9)}:host ::ng-deep .resize-handle-w:active,:host ::ng-deep .resize-handle-e:active{transform:translateY(-50%) scale(.9)}:host ::ng-deep .resize-handle-nw:hover,:host ::ng-deep .resize-handle-ne:hover,:host ::ng-deep .resize-handle-sw:hover,:host ::ng-deep .resize-handle-se:hover{transform:scale(1.2)}:host ::ng-deep .resize-handle-nw:active,:host ::ng-deep .resize-handle-ne:active,:host ::ng-deep .resize-handle-sw:active,:host ::ng-deep .resize-handle-se:active{transform:scale(.9)}:host ::ng-deep .resize-handle-nw{top:0;left:-6px;cursor:nw-resize}:host ::ng-deep .resize-handle-n{top:0;left:50%;transform:translate(-50%);cursor:n-resize}:host ::ng-deep .resize-handle-ne{top:0;right:-6px;cursor:ne-resize}:host ::ng-deep .resize-handle-w{top:50%;left:-6px;transform:translateY(-50%);cursor:w-resize}:host ::ng-deep .resize-handle-e{top:50%;right:-6px;transform:translateY(-50%);cursor:e-resize}:host ::ng-deep .resize-handle-sw{bottom:0;left:-6px;cursor:sw-resize}:host ::ng-deep .resize-handle-s{bottom:0;left:50%;transform:translate(-50%);cursor:s-resize}:host ::ng-deep .resize-handle-se{bottom:0;right:-6px;cursor:se-resize}:host ::ng-deep body.resizing{-webkit-user-select:none;user-select:none;cursor:crosshair}:host ::ng-deep body.resizing .ProseMirror{pointer-events:none}:host ::ng-deep body.resizing .ProseMirror .tiptap-image{pointer-events:none}:host ::ng-deep .image-size-info{position:absolute;bottom:-20px;left:50%;transform:translate(-50%);background:#000c;color:#fff;padding:2px 6px;border-radius:3px;font-size:11px;white-space:nowrap;opacity:0;transition:opacity .2s ease}:host ::ng-deep .image-container:hover .image-size-info{opacity:1}:host ::ng-deep .ProseMirror table{border-collapse:separate;border-spacing:0;margin:0;table-layout:fixed;width:100%;border-radius:8px;overflow:hidden}:host ::ng-deep .ProseMirror table td,:host ::ng-deep .ProseMirror table th{border:none;border-right:1px solid #e2e8f0;border-bottom:1px solid #e2e8f0;box-sizing:border-box;min-width:1em;padding:8px 12px;position:relative;vertical-align:top;background:#fff}:host ::ng-deep .ProseMirror table td:first-child,:host ::ng-deep .ProseMirror table th:first-child{border-left:1px solid #e2e8f0}:host ::ng-deep .ProseMirror table tr:first-child td,:host ::ng-deep .ProseMirror table tr:first-child th{border-top:1px solid #e2e8f0}:host ::ng-deep .ProseMirror table tr:first-child th:first-child{border-top-left-radius:8px}:host ::ng-deep .ProseMirror table tr:first-child th:last-child{border-top-right-radius:8px}:host ::ng-deep .ProseMirror table tr:last-child td:first-child{border-bottom-left-radius:8px}:host ::ng-deep .ProseMirror table tr:last-child td:last-child{border-bottom-right-radius:8px}:host ::ng-deep .ProseMirror table th{background:#f8f9fa;font-weight:600;color:#374151}:host ::ng-deep .ProseMirror table .selectedCell:after{background:#c8c8ff66;content:\"\";inset:0;pointer-events:none;position:absolute;z-index:2}:host ::ng-deep .ProseMirror table .column-resize-handle{position:absolute;right:-2px;top:0;bottom:0;width:4px;background-color:#6366f1;opacity:0;transition:opacity .2s ease}:host ::ng-deep .ProseMirror table:hover .column-resize-handle{opacity:1}:host ::ng-deep .ProseMirror table .column-resize-handle:hover{background-color:#4f46e5}:host ::ng-deep .ProseMirror .tableWrapper{overflow-x:auto;margin:1em 0;border-radius:8px}:host ::ng-deep .ProseMirror .tableWrapper table{margin:0;border-radius:8px;min-width:600px;overflow:hidden}:host ::ng-deep .ProseMirror table p{margin:0}:host ::ng-deep .ProseMirror table .selectedCell{background-color:#6366f11a}:host ::ng-deep .ProseMirror table th{background-color:#f8f9fa;font-weight:600;color:#374151;text-align:left}:host ::ng-deep .ProseMirror table tbody tr:nth-child(2n){background-color:#fafbfc}:host ::ng-deep .ProseMirror table tbody tr:hover{background-color:#f1f5f9}\n"], dependencies: [{ kind: "component", type: TiptapToolbarComponent, selector: "tiptap-toolbar", inputs: ["editor", "config"], outputs: ["imageUploaded", "imageError"] }, { kind: "component", type: TiptapImageUploadComponent, selector: "tiptap-image-upload", inputs: ["config"], outputs: ["imageSelected", "error"] }, { kind: "component", type: TiptapBubbleMenuComponent, selector: "tiptap-bubble-menu", inputs: ["editor", "config"] }, { kind: "component", type: TiptapImageBubbleMenuComponent, selector: "tiptap-image-bubble-menu", inputs: ["editor", "config"] }, { kind: "component", type: TiptapTableBubbleMenuComponent, selector: "tiptap-table-bubble-menu", inputs: ["editor", "config"] }, { kind: "component", type: TiptapCellBubbleMenuComponent, selector: "tiptap-cell-bubble-menu", inputs: ["editor", "config"] }, { kind: "component", type: TiptapSlashCommandsComponent, selector: "tiptap-slash-commands", inputs: ["editor", "config"], outputs: ["imageUploadRequested"] }] }); }
|
|
5097
5167
|
}
|
|
5098
5168
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AngularTiptapEditorComponent, decorators: [{
|
|
5099
5169
|
type: Component,
|
|
5100
|
-
args: [{ selector: "angular-tiptap-editor", standalone: true, hostDirectives: [NoopValueAccessorDirective],
|
|
5170
|
+
args: [{ selector: "angular-tiptap-editor", standalone: true, hostDirectives: [NoopValueAccessorDirective], host: {
|
|
5171
|
+
'[class.fill-container]': 'fillContainer()',
|
|
5172
|
+
}, imports: [
|
|
5101
5173
|
TiptapToolbarComponent,
|
|
5102
5174
|
TiptapImageUploadComponent,
|
|
5103
5175
|
TiptapBubbleMenuComponent,
|
|
@@ -5106,7 +5178,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
5106
5178
|
TiptapCellBubbleMenuComponent,
|
|
5107
5179
|
TiptapSlashCommandsComponent,
|
|
5108
5180
|
], template: `
|
|
5109
|
-
<div class="tiptap-editor">
|
|
5181
|
+
<div class="tiptap-editor" [class.fill-container]="fillContainer()">
|
|
5110
5182
|
<!-- Toolbar -->
|
|
5111
5183
|
@if (showToolbar() && editor()) {
|
|
5112
5184
|
<tiptap-toolbar [editor]="editor()!" [config]="toolbarConfig()">
|
|
@@ -5191,7 +5263,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
5191
5263
|
</div>
|
|
5192
5264
|
}
|
|
5193
5265
|
</div>
|
|
5194
|
-
`, styles: [".tiptap-editor{border:2px solid #e2e8f0;border-radius:8px;background:#fff;overflow:hidden;transition:border-color .2s ease}.tiptap-editor:focus-within{border-color:#3182ce}.tiptap-content{padding:16px;min-height:var(--editor-min-height, 200px);height:var(--editor-height, auto);max-height:var(--editor-max-height, none);overflow-y:var(--editor-overflow, visible);outline:none;position:relative}.tiptap-content.drag-over{background:#f0f8ff;border:2px dashed #3182ce}.character-count{padding:8px 16px;font-size:12px;color:#718096;text-align:right;border-top:1px solid #e2e8f0;background:#f8f9fa}.image-upload-container{position:relative;display:inline-block}:host ::ng-deep .ProseMirror{outline:none;line-height:1.6;color:#2d3748;min-height:100%;height:100%;word-wrap:break-word;overflow-wrap:break-word}:host ::ng-deep .ProseMirror h1{font-size:2em;font-weight:700;margin-top:0;margin-bottom:.5em}:host ::ng-deep .ProseMirror h2{font-size:1.5em;font-weight:700;margin-top:1em;margin-bottom:.5em}:host ::ng-deep .ProseMirror h3{font-size:1.25em;font-weight:700;margin-top:1em;margin-bottom:.5em}:host ::ng-deep .ProseMirror p{margin:.5em 0}:host ::ng-deep .ProseMirror ul,:host ::ng-deep .ProseMirror ol{padding-left:2em;margin:.5em 0}:host ::ng-deep .ProseMirror blockquote{border-left:4px solid #e2e8f0;margin:1em 0;font-style:italic;background:#f8f9fa;padding:.5em 1em;border-radius:0 4px 4px 0}:host ::ng-deep .ProseMirror code{background:#f1f5f9;padding:.2em .4em;border-radius:3px;font-family:Monaco,Consolas,monospace;font-size:.9em}:host ::ng-deep .ProseMirror pre{background:#1a202c;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;margin:1em 0}:host ::ng-deep .ProseMirror pre code{background:none;color:inherit;padding:0}:host ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:#a0aec0;pointer-events:none;float:left;height:0}:host ::ng-deep .ProseMirror[contenteditable=false]{pointer-events:none}:host ::ng-deep .ProseMirror[contenteditable=false] img{cursor:default;pointer-events:none}:host ::ng-deep .ProseMirror[contenteditable=false] img:hover{transform:none;box-shadow:0 2px 8px #0000001a}:host ::ng-deep .ProseMirror[contenteditable=false] img.ProseMirror-selectednode{outline:none}:host ::ng-deep .ProseMirror img{position:relative;display:inline-block;max-width:100%;height:auto;cursor:pointer;transition:all .2s ease;border:2px solid transparent;border-radius:8px}:host ::ng-deep .ProseMirror img:hover{border-color:#e2e8f0;box-shadow:0 2px 4px #0000001a}:host ::ng-deep .ProseMirror img.ProseMirror-selectednode{border-color:#3182ce;box-shadow:0 0 0 3px #3182ce1a;transition:all .2s ease}:host ::ng-deep .ProseMirror .tiptap-image{max-width:100%;height:auto;border-radius:16px;box-shadow:0 4px 20px #00000014;margin:.5em 0;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);display:block;filter:brightness(1) contrast(1)}:host ::ng-deep .ProseMirror .tiptap-image:hover{box-shadow:0 8px 30px #0000001f;filter:brightness(1.02) contrast(1.02)}:host ::ng-deep .ProseMirror .tiptap-image.ProseMirror-selectednode{outline:2px solid #6366f1;outline-offset:2px;border-radius:16px;box-shadow:0 0 0 4px #6366f11a}:host ::ng-deep .image-container{margin:.5em 0;text-align:center;border-radius:16px;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1)}:host ::ng-deep .image-container.image-align-left{text-align:left}:host ::ng-deep .image-container.image-align-center{text-align:center}:host ::ng-deep .image-container.image-align-right{text-align:right}:host ::ng-deep .image-container img{display:inline-block;max-width:100%;height:auto;border-radius:16px}:host ::ng-deep .resizable-image-container{position:relative;display:inline-block;margin:.5em 0}:host ::ng-deep .resize-controls{position:absolute;inset:0;pointer-events:none;z-index:1000}:host ::ng-deep .resize-handle{position:absolute;width:12px;height:12px;background:#3b82f6;border:2px solid white;border-radius:50%;pointer-events:all;cursor:pointer;z-index:1001;transition:all .15s ease;box-shadow:0 2px 6px #0003}:host ::ng-deep .resize-handle:hover{background:#2563eb;box-shadow:0 3px 8px #0000004d}:host ::ng-deep .resize-handle:active{background:#1d4ed8}:host ::ng-deep .resize-handle-n:hover,:host ::ng-deep .resize-handle-s:hover{transform:translate(-50%) scale(1.2)}:host ::ng-deep .resize-handle-w:hover,:host ::ng-deep .resize-handle-e:hover{transform:translateY(-50%) scale(1.2)}:host ::ng-deep .resize-handle-n:active,:host ::ng-deep .resize-handle-s:active{transform:translate(-50%) scale(.9)}:host ::ng-deep .resize-handle-w:active,:host ::ng-deep .resize-handle-e:active{transform:translateY(-50%) scale(.9)}:host ::ng-deep .resize-handle-nw:hover,:host ::ng-deep .resize-handle-ne:hover,:host ::ng-deep .resize-handle-sw:hover,:host ::ng-deep .resize-handle-se:hover{transform:scale(1.2)}:host ::ng-deep .resize-handle-nw:active,:host ::ng-deep .resize-handle-ne:active,:host ::ng-deep .resize-handle-sw:active,:host ::ng-deep .resize-handle-se:active{transform:scale(.9)}:host ::ng-deep .resize-handle-nw{top:0;left:-6px;cursor:nw-resize}:host ::ng-deep .resize-handle-n{top:0;left:50%;transform:translate(-50%);cursor:n-resize}:host ::ng-deep .resize-handle-ne{top:0;right:-6px;cursor:ne-resize}:host ::ng-deep .resize-handle-w{top:50%;left:-6px;transform:translateY(-50%);cursor:w-resize}:host ::ng-deep .resize-handle-e{top:50%;right:-6px;transform:translateY(-50%);cursor:e-resize}:host ::ng-deep .resize-handle-sw{bottom:0;left:-6px;cursor:sw-resize}:host ::ng-deep .resize-handle-s{bottom:0;left:50%;transform:translate(-50%);cursor:s-resize}:host ::ng-deep .resize-handle-se{bottom:0;right:-6px;cursor:se-resize}:host ::ng-deep body.resizing{-webkit-user-select:none;user-select:none;cursor:crosshair}:host ::ng-deep body.resizing .ProseMirror{pointer-events:none}:host ::ng-deep body.resizing .ProseMirror .tiptap-image{pointer-events:none}:host ::ng-deep .image-size-info{position:absolute;bottom:-20px;left:50%;transform:translate(-50%);background:#000c;color:#fff;padding:2px 6px;border-radius:3px;font-size:11px;white-space:nowrap;opacity:0;transition:opacity .2s ease}:host ::ng-deep .image-container:hover .image-size-info{opacity:1}:host ::ng-deep .ProseMirror table{border-collapse:separate;border-spacing:0;margin:0;table-layout:fixed;width:100%;border-radius:8px;overflow:hidden}:host ::ng-deep .ProseMirror table td,:host ::ng-deep .ProseMirror table th{border:none;border-right:1px solid #e2e8f0;border-bottom:1px solid #e2e8f0;box-sizing:border-box;min-width:1em;padding:8px 12px;position:relative;vertical-align:top;background:#fff}:host ::ng-deep .ProseMirror table td:first-child,:host ::ng-deep .ProseMirror table th:first-child{border-left:1px solid #e2e8f0}:host ::ng-deep .ProseMirror table tr:first-child td,:host ::ng-deep .ProseMirror table tr:first-child th{border-top:1px solid #e2e8f0}:host ::ng-deep .ProseMirror table tr:first-child th:first-child{border-top-left-radius:8px}:host ::ng-deep .ProseMirror table tr:first-child th:last-child{border-top-right-radius:8px}:host ::ng-deep .ProseMirror table tr:last-child td:first-child{border-bottom-left-radius:8px}:host ::ng-deep .ProseMirror table tr:last-child td:last-child{border-bottom-right-radius:8px}:host ::ng-deep .ProseMirror table th{background:#f8f9fa;font-weight:600;color:#374151}:host ::ng-deep .ProseMirror table .selectedCell:after{background:#c8c8ff66;content:\"\";inset:0;pointer-events:none;position:absolute;z-index:2}:host ::ng-deep .ProseMirror table .column-resize-handle{position:absolute;right:-2px;top:0;bottom:0;width:4px;background-color:#6366f1;opacity:0;transition:opacity .2s ease}:host ::ng-deep .ProseMirror table:hover .column-resize-handle{opacity:1}:host ::ng-deep .ProseMirror table .column-resize-handle:hover{background-color:#4f46e5}:host ::ng-deep .ProseMirror .tableWrapper{overflow-x:auto;margin:1em 0;border-radius:8px}:host ::ng-deep .ProseMirror .tableWrapper table{margin:0;border-radius:8px;min-width:600px;overflow:hidden}:host ::ng-deep .ProseMirror table p{margin:0}:host ::ng-deep .ProseMirror table .selectedCell{background-color:#6366f11a}:host ::ng-deep .ProseMirror table th{background-color:#f8f9fa;font-weight:600;color:#374151;text-align:left}:host ::ng-deep .ProseMirror table tbody tr:nth-child(2n){background-color:#fafbfc}:host ::ng-deep .ProseMirror table tbody tr:hover{background-color:#f1f5f9}\n"] }]
|
|
5266
|
+
`, styles: [":host(.fill-container){display:block;height:100%}.tiptap-editor{border:2px solid #e2e8f0;border-radius:8px;background:#fff;overflow:hidden;transition:border-color .2s ease}.tiptap-editor.fill-container{display:flex;flex-direction:column;height:100%}.tiptap-editor.fill-container .tiptap-content{flex:1;min-height:0;overflow-y:auto}.tiptap-editor:focus-within{border-color:#3182ce}.tiptap-content{padding:16px;min-height:var(--editor-min-height, 200px);height:var(--editor-height, auto);max-height:var(--editor-max-height, none);overflow-y:var(--editor-overflow, visible);outline:none;position:relative}.tiptap-content.drag-over{background:#f0f8ff;border:2px dashed #3182ce}.character-count{padding:8px 16px;font-size:12px;color:#718096;text-align:right;border-top:1px solid #e2e8f0;background:#f8f9fa}.image-upload-container{position:relative;display:inline-block}:host ::ng-deep .ProseMirror{outline:none;line-height:1.6;color:#2d3748;min-height:100%;height:100%;word-wrap:break-word;overflow-wrap:break-word}:host ::ng-deep .ProseMirror h1{font-size:2em;font-weight:700;margin-top:0;margin-bottom:.5em}:host ::ng-deep .ProseMirror h2{font-size:1.5em;font-weight:700;margin-top:1em;margin-bottom:.5em}:host ::ng-deep .ProseMirror h3{font-size:1.25em;font-weight:700;margin-top:1em;margin-bottom:.5em}:host ::ng-deep .ProseMirror p{margin:.5em 0}:host ::ng-deep .ProseMirror ul,:host ::ng-deep .ProseMirror ol{padding-left:2em;margin:.5em 0}:host ::ng-deep .ProseMirror blockquote{border-left:4px solid #e2e8f0;margin:1em 0;font-style:italic;background:#f8f9fa;padding:.5em 1em;border-radius:0 4px 4px 0}:host ::ng-deep .ProseMirror code{background:#f1f5f9;padding:.2em .4em;border-radius:3px;font-family:Monaco,Consolas,monospace;font-size:.9em}:host ::ng-deep .ProseMirror pre{background:#1a202c;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;margin:1em 0}:host ::ng-deep .ProseMirror pre code{background:none;color:inherit;padding:0}:host ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:#a0aec0;pointer-events:none;float:left;height:0}:host ::ng-deep .ProseMirror[contenteditable=false]{pointer-events:none}:host ::ng-deep .ProseMirror[contenteditable=false] img{cursor:default;pointer-events:none}:host ::ng-deep .ProseMirror[contenteditable=false] img:hover{transform:none;box-shadow:0 2px 8px #0000001a}:host ::ng-deep .ProseMirror[contenteditable=false] img.ProseMirror-selectednode{outline:none}:host ::ng-deep .ProseMirror img{position:relative;display:inline-block;max-width:100%;height:auto;cursor:pointer;transition:all .2s ease;border:2px solid transparent;border-radius:8px}:host ::ng-deep .ProseMirror img:hover{border-color:#e2e8f0;box-shadow:0 2px 4px #0000001a}:host ::ng-deep .ProseMirror img.ProseMirror-selectednode{border-color:#3182ce;box-shadow:0 0 0 3px #3182ce1a;transition:all .2s ease}:host ::ng-deep .ProseMirror .tiptap-image{max-width:100%;height:auto;border-radius:16px;box-shadow:0 4px 20px #00000014;margin:.5em 0;cursor:pointer;transition:all .3s cubic-bezier(.4,0,.2,1);display:block;filter:brightness(1) contrast(1)}:host ::ng-deep .ProseMirror .tiptap-image:hover{box-shadow:0 8px 30px #0000001f;filter:brightness(1.02) contrast(1.02)}:host ::ng-deep .ProseMirror .tiptap-image.ProseMirror-selectednode{outline:2px solid #6366f1;outline-offset:2px;border-radius:16px;box-shadow:0 0 0 4px #6366f11a}:host ::ng-deep .image-container{margin:.5em 0;text-align:center;border-radius:16px;overflow:hidden;transition:all .3s cubic-bezier(.4,0,.2,1)}:host ::ng-deep .image-container.image-align-left{text-align:left}:host ::ng-deep .image-container.image-align-center{text-align:center}:host ::ng-deep .image-container.image-align-right{text-align:right}:host ::ng-deep .image-container img{display:inline-block;max-width:100%;height:auto;border-radius:16px}:host ::ng-deep .resizable-image-container{position:relative;display:inline-block;margin:.5em 0}:host ::ng-deep .resize-controls{position:absolute;inset:0;pointer-events:none;z-index:1000}:host ::ng-deep .resize-handle{position:absolute;width:12px;height:12px;background:#3b82f6;border:2px solid white;border-radius:50%;pointer-events:all;cursor:pointer;z-index:1001;transition:all .15s ease;box-shadow:0 2px 6px #0003}:host ::ng-deep .resize-handle:hover{background:#2563eb;box-shadow:0 3px 8px #0000004d}:host ::ng-deep .resize-handle:active{background:#1d4ed8}:host ::ng-deep .resize-handle-n:hover,:host ::ng-deep .resize-handle-s:hover{transform:translate(-50%) scale(1.2)}:host ::ng-deep .resize-handle-w:hover,:host ::ng-deep .resize-handle-e:hover{transform:translateY(-50%) scale(1.2)}:host ::ng-deep .resize-handle-n:active,:host ::ng-deep .resize-handle-s:active{transform:translate(-50%) scale(.9)}:host ::ng-deep .resize-handle-w:active,:host ::ng-deep .resize-handle-e:active{transform:translateY(-50%) scale(.9)}:host ::ng-deep .resize-handle-nw:hover,:host ::ng-deep .resize-handle-ne:hover,:host ::ng-deep .resize-handle-sw:hover,:host ::ng-deep .resize-handle-se:hover{transform:scale(1.2)}:host ::ng-deep .resize-handle-nw:active,:host ::ng-deep .resize-handle-ne:active,:host ::ng-deep .resize-handle-sw:active,:host ::ng-deep .resize-handle-se:active{transform:scale(.9)}:host ::ng-deep .resize-handle-nw{top:0;left:-6px;cursor:nw-resize}:host ::ng-deep .resize-handle-n{top:0;left:50%;transform:translate(-50%);cursor:n-resize}:host ::ng-deep .resize-handle-ne{top:0;right:-6px;cursor:ne-resize}:host ::ng-deep .resize-handle-w{top:50%;left:-6px;transform:translateY(-50%);cursor:w-resize}:host ::ng-deep .resize-handle-e{top:50%;right:-6px;transform:translateY(-50%);cursor:e-resize}:host ::ng-deep .resize-handle-sw{bottom:0;left:-6px;cursor:sw-resize}:host ::ng-deep .resize-handle-s{bottom:0;left:50%;transform:translate(-50%);cursor:s-resize}:host ::ng-deep .resize-handle-se{bottom:0;right:-6px;cursor:se-resize}:host ::ng-deep body.resizing{-webkit-user-select:none;user-select:none;cursor:crosshair}:host ::ng-deep body.resizing .ProseMirror{pointer-events:none}:host ::ng-deep body.resizing .ProseMirror .tiptap-image{pointer-events:none}:host ::ng-deep .image-size-info{position:absolute;bottom:-20px;left:50%;transform:translate(-50%);background:#000c;color:#fff;padding:2px 6px;border-radius:3px;font-size:11px;white-space:nowrap;opacity:0;transition:opacity .2s ease}:host ::ng-deep .image-container:hover .image-size-info{opacity:1}:host ::ng-deep .ProseMirror table{border-collapse:separate;border-spacing:0;margin:0;table-layout:fixed;width:100%;border-radius:8px;overflow:hidden}:host ::ng-deep .ProseMirror table td,:host ::ng-deep .ProseMirror table th{border:none;border-right:1px solid #e2e8f0;border-bottom:1px solid #e2e8f0;box-sizing:border-box;min-width:1em;padding:8px 12px;position:relative;vertical-align:top;background:#fff}:host ::ng-deep .ProseMirror table td:first-child,:host ::ng-deep .ProseMirror table th:first-child{border-left:1px solid #e2e8f0}:host ::ng-deep .ProseMirror table tr:first-child td,:host ::ng-deep .ProseMirror table tr:first-child th{border-top:1px solid #e2e8f0}:host ::ng-deep .ProseMirror table tr:first-child th:first-child{border-top-left-radius:8px}:host ::ng-deep .ProseMirror table tr:first-child th:last-child{border-top-right-radius:8px}:host ::ng-deep .ProseMirror table tr:last-child td:first-child{border-bottom-left-radius:8px}:host ::ng-deep .ProseMirror table tr:last-child td:last-child{border-bottom-right-radius:8px}:host ::ng-deep .ProseMirror table th{background:#f8f9fa;font-weight:600;color:#374151}:host ::ng-deep .ProseMirror table .selectedCell:after{background:#c8c8ff66;content:\"\";inset:0;pointer-events:none;position:absolute;z-index:2}:host ::ng-deep .ProseMirror table .column-resize-handle{position:absolute;right:-2px;top:0;bottom:0;width:4px;background-color:#6366f1;opacity:0;transition:opacity .2s ease}:host ::ng-deep .ProseMirror table:hover .column-resize-handle{opacity:1}:host ::ng-deep .ProseMirror table .column-resize-handle:hover{background-color:#4f46e5}:host ::ng-deep .ProseMirror .tableWrapper{overflow-x:auto;margin:1em 0;border-radius:8px}:host ::ng-deep .ProseMirror .tableWrapper table{margin:0;border-radius:8px;min-width:600px;overflow:hidden}:host ::ng-deep .ProseMirror table p{margin:0}:host ::ng-deep .ProseMirror table .selectedCell{background-color:#6366f11a}:host ::ng-deep .ProseMirror table th{background-color:#f8f9fa;font-weight:600;color:#374151;text-align:left}:host ::ng-deep .ProseMirror table tbody tr:nth-child(2n){background-color:#fafbfc}:host ::ng-deep .ProseMirror table tbody tr:hover{background-color:#f1f5f9}\n"] }]
|
|
5195
5267
|
}], ctorParameters: () => [] });
|
|
5196
5268
|
|
|
5197
5269
|
/*
|