@flogeez/angular-tiptap-editor 0.3.2 → 0.3.3
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 +229 -54
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +188 -180
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/index.d.ts +1 -2
- package/package.json +1 -1
|
@@ -3510,7 +3510,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
3510
3510
|
`, styles: [".tiptap-toolbar{display:flex;align-items:center;gap:4px;padding:4px 8px;background:#f8f9fa;border-bottom:1px solid #e2e8f0;flex-wrap:wrap;min-height:32px;position:relative}.toolbar-group{display:flex;align-items:center;gap:2px;padding:0 4px}.toolbar-separator{width:1px;height:24px;background:#e2e8f0;margin:0 4px}@media (max-width: 768px){.tiptap-toolbar{padding:6px 8px;gap:2px}.toolbar-group{gap:1px}}@keyframes toolbarSlideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.tiptap-toolbar{animation:toolbarSlideIn .3s cubic-bezier(.4,0,.2,1)}\n"] }]
|
|
3511
3511
|
}], ctorParameters: () => [{ type: EditorCommandsService }] });
|
|
3512
3512
|
|
|
3513
|
-
const DEFAULT_SLASH_COMMANDS = [
|
|
3513
|
+
const DEFAULT_SLASH_COMMANDS$1 = [
|
|
3514
3514
|
{
|
|
3515
3515
|
title: "Titre 1",
|
|
3516
3516
|
description: "Grand titre de section",
|
|
@@ -3647,7 +3647,7 @@ class TiptapSlashCommandsComponent {
|
|
|
3647
3647
|
constructor() {
|
|
3648
3648
|
this.editor = input.required();
|
|
3649
3649
|
this.config = input({
|
|
3650
|
-
commands: DEFAULT_SLASH_COMMANDS,
|
|
3650
|
+
commands: DEFAULT_SLASH_COMMANDS$1,
|
|
3651
3651
|
});
|
|
3652
3652
|
// Output pour l'upload d'image
|
|
3653
3653
|
this.imageUploadRequested = output();
|
|
@@ -3660,7 +3660,7 @@ class TiptapSlashCommandsComponent {
|
|
|
3660
3660
|
// Signal pour l'index sélectionné
|
|
3661
3661
|
this.selectedIndex = signal(0);
|
|
3662
3662
|
this.commands = computed(() => {
|
|
3663
|
-
const configCommands = this.config().commands || DEFAULT_SLASH_COMMANDS;
|
|
3663
|
+
const configCommands = this.config().commands || DEFAULT_SLASH_COMMANDS$1;
|
|
3664
3664
|
// Remplacer la commande image par une version qui utilise l'output
|
|
3665
3665
|
return configCommands.map((command) => {
|
|
3666
3666
|
if (command.icon === "image") {
|
|
@@ -4380,6 +4380,178 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
4380
4380
|
}]
|
|
4381
4381
|
}] });
|
|
4382
4382
|
|
|
4383
|
+
/**
|
|
4384
|
+
* Clés des commandes dans l'ordre de création
|
|
4385
|
+
*/
|
|
4386
|
+
const SLASH_COMMAND_KEYS = [
|
|
4387
|
+
"heading1",
|
|
4388
|
+
"heading2",
|
|
4389
|
+
"heading3",
|
|
4390
|
+
"bulletList",
|
|
4391
|
+
"orderedList",
|
|
4392
|
+
"blockquote",
|
|
4393
|
+
"code",
|
|
4394
|
+
"image",
|
|
4395
|
+
"horizontalRule",
|
|
4396
|
+
"table",
|
|
4397
|
+
];
|
|
4398
|
+
/**
|
|
4399
|
+
* Factory function pour créer les slash commands traduits
|
|
4400
|
+
*/
|
|
4401
|
+
function createI18nSlashCommands(i18nService) {
|
|
4402
|
+
const slashCommands = i18nService.slashCommands();
|
|
4403
|
+
return [
|
|
4404
|
+
{
|
|
4405
|
+
title: slashCommands.heading1.title,
|
|
4406
|
+
description: slashCommands.heading1.description,
|
|
4407
|
+
icon: "format_h1",
|
|
4408
|
+
keywords: slashCommands.heading1.keywords,
|
|
4409
|
+
command: (editor) => editor.chain().focus().toggleHeading({ level: 1 }).run(),
|
|
4410
|
+
},
|
|
4411
|
+
{
|
|
4412
|
+
title: slashCommands.heading2.title,
|
|
4413
|
+
description: slashCommands.heading2.description,
|
|
4414
|
+
icon: "format_h2",
|
|
4415
|
+
keywords: slashCommands.heading2.keywords,
|
|
4416
|
+
command: (editor) => editor.chain().focus().toggleHeading({ level: 2 }).run(),
|
|
4417
|
+
},
|
|
4418
|
+
{
|
|
4419
|
+
title: slashCommands.heading3.title,
|
|
4420
|
+
description: slashCommands.heading3.description,
|
|
4421
|
+
icon: "format_h3",
|
|
4422
|
+
keywords: slashCommands.heading3.keywords,
|
|
4423
|
+
command: (editor) => editor.chain().focus().toggleHeading({ level: 3 }).run(),
|
|
4424
|
+
},
|
|
4425
|
+
{
|
|
4426
|
+
title: slashCommands.bulletList.title,
|
|
4427
|
+
description: slashCommands.bulletList.description,
|
|
4428
|
+
icon: "format_list_bulleted",
|
|
4429
|
+
keywords: slashCommands.bulletList.keywords,
|
|
4430
|
+
command: (editor) => editor.chain().focus().toggleBulletList().run(),
|
|
4431
|
+
},
|
|
4432
|
+
{
|
|
4433
|
+
title: slashCommands.orderedList.title,
|
|
4434
|
+
description: slashCommands.orderedList.description,
|
|
4435
|
+
icon: "format_list_numbered",
|
|
4436
|
+
keywords: slashCommands.orderedList.keywords,
|
|
4437
|
+
command: (editor) => editor.chain().focus().toggleOrderedList().run(),
|
|
4438
|
+
},
|
|
4439
|
+
{
|
|
4440
|
+
title: slashCommands.blockquote.title,
|
|
4441
|
+
description: slashCommands.blockquote.description,
|
|
4442
|
+
icon: "format_quote",
|
|
4443
|
+
keywords: slashCommands.blockquote.keywords,
|
|
4444
|
+
command: (editor) => editor.chain().focus().toggleBlockquote().run(),
|
|
4445
|
+
},
|
|
4446
|
+
{
|
|
4447
|
+
title: slashCommands.code.title,
|
|
4448
|
+
description: slashCommands.code.description,
|
|
4449
|
+
icon: "code",
|
|
4450
|
+
keywords: slashCommands.code.keywords,
|
|
4451
|
+
command: (editor) => editor.chain().focus().toggleCodeBlock().run(),
|
|
4452
|
+
},
|
|
4453
|
+
{
|
|
4454
|
+
title: slashCommands.image.title,
|
|
4455
|
+
description: slashCommands.image.description,
|
|
4456
|
+
icon: "image",
|
|
4457
|
+
keywords: slashCommands.image.keywords,
|
|
4458
|
+
command: (editor) => {
|
|
4459
|
+
// Créer un input file temporaire pour sélectionner une image
|
|
4460
|
+
const input = document.createElement("input");
|
|
4461
|
+
input.type = "file";
|
|
4462
|
+
input.accept = "image/*";
|
|
4463
|
+
input.style.display = "none";
|
|
4464
|
+
input.addEventListener("change", async (e) => {
|
|
4465
|
+
const file = e.target.files?.[0];
|
|
4466
|
+
if (file && file.type.startsWith("image/")) {
|
|
4467
|
+
try {
|
|
4468
|
+
// Utiliser la méthode de compression unifiée
|
|
4469
|
+
const canvas = document.createElement("canvas");
|
|
4470
|
+
const ctx = canvas.getContext("2d");
|
|
4471
|
+
const img = new Image();
|
|
4472
|
+
img.onload = () => {
|
|
4473
|
+
// Vérifier les dimensions (max 1920x1080)
|
|
4474
|
+
const maxWidth = 1920;
|
|
4475
|
+
const maxHeight = 1080;
|
|
4476
|
+
let { width, height } = img;
|
|
4477
|
+
// Redimensionner si nécessaire
|
|
4478
|
+
if (width > maxWidth || height > maxHeight) {
|
|
4479
|
+
const ratio = Math.min(maxWidth / width, maxHeight / height);
|
|
4480
|
+
width *= ratio;
|
|
4481
|
+
height *= ratio;
|
|
4482
|
+
}
|
|
4483
|
+
canvas.width = width;
|
|
4484
|
+
canvas.height = height;
|
|
4485
|
+
// Dessiner l'image redimensionnée
|
|
4486
|
+
ctx?.drawImage(img, 0, 0, width, height);
|
|
4487
|
+
// Convertir en base64 avec compression
|
|
4488
|
+
canvas.toBlob((blob) => {
|
|
4489
|
+
if (blob) {
|
|
4490
|
+
const reader = new FileReader();
|
|
4491
|
+
reader.onload = (e) => {
|
|
4492
|
+
const base64 = e.target?.result;
|
|
4493
|
+
if (base64) {
|
|
4494
|
+
// Utiliser setResizableImage avec toutes les propriétés
|
|
4495
|
+
editor
|
|
4496
|
+
.chain()
|
|
4497
|
+
.focus()
|
|
4498
|
+
.setResizableImage({
|
|
4499
|
+
src: base64,
|
|
4500
|
+
alt: file.name,
|
|
4501
|
+
title: `${file.name} (${Math.round(width)}×${Math.round(height)})`,
|
|
4502
|
+
width: Math.round(width),
|
|
4503
|
+
height: Math.round(height),
|
|
4504
|
+
})
|
|
4505
|
+
.run();
|
|
4506
|
+
}
|
|
4507
|
+
};
|
|
4508
|
+
reader.readAsDataURL(blob);
|
|
4509
|
+
}
|
|
4510
|
+
}, file.type, 0.8 // qualité de compression
|
|
4511
|
+
);
|
|
4512
|
+
};
|
|
4513
|
+
img.onerror = () => {
|
|
4514
|
+
console.error(i18nService.editor().imageLoadError);
|
|
4515
|
+
};
|
|
4516
|
+
img.src = URL.createObjectURL(file);
|
|
4517
|
+
}
|
|
4518
|
+
catch (error) {
|
|
4519
|
+
console.error("Error uploading image:", error);
|
|
4520
|
+
}
|
|
4521
|
+
}
|
|
4522
|
+
document.body.removeChild(input);
|
|
4523
|
+
});
|
|
4524
|
+
document.body.appendChild(input);
|
|
4525
|
+
input.click();
|
|
4526
|
+
},
|
|
4527
|
+
},
|
|
4528
|
+
{
|
|
4529
|
+
title: slashCommands.horizontalRule.title,
|
|
4530
|
+
description: slashCommands.horizontalRule.description,
|
|
4531
|
+
icon: "horizontal_rule",
|
|
4532
|
+
keywords: slashCommands.horizontalRule.keywords,
|
|
4533
|
+
command: (editor) => editor.chain().focus().setHorizontalRule().run(),
|
|
4534
|
+
},
|
|
4535
|
+
{
|
|
4536
|
+
title: slashCommands.table.title,
|
|
4537
|
+
description: slashCommands.table.description,
|
|
4538
|
+
icon: "table_view",
|
|
4539
|
+
keywords: slashCommands.table.keywords,
|
|
4540
|
+
command: (editor) => editor.chain().focus().insertTable({ rows: 3, cols: 3 }).run(),
|
|
4541
|
+
},
|
|
4542
|
+
];
|
|
4543
|
+
}
|
|
4544
|
+
/**
|
|
4545
|
+
* Fonction utilitaire pour filtrer les slash commands selon les commandes actives
|
|
4546
|
+
*/
|
|
4547
|
+
function filterSlashCommands(activeCommands, i18nService) {
|
|
4548
|
+
const allCommands = createI18nSlashCommands(i18nService);
|
|
4549
|
+
return allCommands.filter((command, index) => {
|
|
4550
|
+
const commandKey = SLASH_COMMAND_KEYS[index];
|
|
4551
|
+
return commandKey && activeCommands.has(commandKey);
|
|
4552
|
+
});
|
|
4553
|
+
}
|
|
4554
|
+
|
|
4383
4555
|
// Configuration par défaut de la toolbar
|
|
4384
4556
|
const DEFAULT_TOOLBAR_CONFIG = {
|
|
4385
4557
|
bold: true,
|
|
@@ -4449,6 +4621,9 @@ const DEFAULT_CELL_MENU_CONFIG = {
|
|
|
4449
4621
|
mergeCells: true,
|
|
4450
4622
|
splitCell: true,
|
|
4451
4623
|
};
|
|
4624
|
+
const DEFAULT_SLASH_COMMANDS = {
|
|
4625
|
+
commands: [], // Sera rempli par filterSlashCommands
|
|
4626
|
+
};
|
|
4452
4627
|
class AngularTiptapEditorComponent {
|
|
4453
4628
|
constructor() {
|
|
4454
4629
|
// Nouveaux inputs avec signal
|
|
@@ -4539,7 +4714,15 @@ class AngularTiptapEditorComponent {
|
|
|
4539
4714
|
...this.imageUpload(),
|
|
4540
4715
|
}));
|
|
4541
4716
|
// Computed pour la configuration des slash commands
|
|
4542
|
-
this.slashCommandsConfigComputed = computed(() =>
|
|
4717
|
+
this.slashCommandsConfigComputed = computed(() => {
|
|
4718
|
+
const config = this.slashCommandsConfig();
|
|
4719
|
+
if (config) {
|
|
4720
|
+
return config;
|
|
4721
|
+
}
|
|
4722
|
+
// Configuration par défaut avec toutes les commandes
|
|
4723
|
+
const allCommands = filterSlashCommands(new Set(SLASH_COMMAND_KEYS), this.i18nService);
|
|
4724
|
+
return { commands: allCommands };
|
|
4725
|
+
});
|
|
4543
4726
|
this._destroyRef = inject(DestroyRef);
|
|
4544
4727
|
// NgControl pour gérer les FormControls
|
|
4545
4728
|
this.ngControl = inject(NgControl, { self: true, optional: true });
|
|
@@ -5031,181 +5214,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
5031
5214
|
`, 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"] }]
|
|
5032
5215
|
}], ctorParameters: () => [] });
|
|
5033
5216
|
|
|
5034
|
-
/**
|
|
5035
|
-
* Clés des commandes dans l'ordre de création
|
|
5036
|
-
*/
|
|
5037
|
-
const SLASH_COMMAND_KEYS = [
|
|
5038
|
-
"heading1",
|
|
5039
|
-
"heading2",
|
|
5040
|
-
"heading3",
|
|
5041
|
-
"bulletList",
|
|
5042
|
-
"orderedList",
|
|
5043
|
-
"blockquote",
|
|
5044
|
-
"code",
|
|
5045
|
-
"image",
|
|
5046
|
-
"horizontalRule",
|
|
5047
|
-
"table",
|
|
5048
|
-
];
|
|
5049
|
-
/**
|
|
5050
|
-
* Factory function pour créer les slash commands traduits
|
|
5051
|
-
*/
|
|
5052
|
-
function createI18nSlashCommands(i18nService) {
|
|
5053
|
-
const slashCommands = i18nService.slashCommands();
|
|
5054
|
-
return [
|
|
5055
|
-
{
|
|
5056
|
-
title: slashCommands.heading1.title,
|
|
5057
|
-
description: slashCommands.heading1.description,
|
|
5058
|
-
icon: "format_h1",
|
|
5059
|
-
keywords: slashCommands.heading1.keywords,
|
|
5060
|
-
command: (editor) => editor.chain().focus().toggleHeading({ level: 1 }).run(),
|
|
5061
|
-
},
|
|
5062
|
-
{
|
|
5063
|
-
title: slashCommands.heading2.title,
|
|
5064
|
-
description: slashCommands.heading2.description,
|
|
5065
|
-
icon: "format_h2",
|
|
5066
|
-
keywords: slashCommands.heading2.keywords,
|
|
5067
|
-
command: (editor) => editor.chain().focus().toggleHeading({ level: 2 }).run(),
|
|
5068
|
-
},
|
|
5069
|
-
{
|
|
5070
|
-
title: slashCommands.heading3.title,
|
|
5071
|
-
description: slashCommands.heading3.description,
|
|
5072
|
-
icon: "format_h3",
|
|
5073
|
-
keywords: slashCommands.heading3.keywords,
|
|
5074
|
-
command: (editor) => editor.chain().focus().toggleHeading({ level: 3 }).run(),
|
|
5075
|
-
},
|
|
5076
|
-
{
|
|
5077
|
-
title: slashCommands.bulletList.title,
|
|
5078
|
-
description: slashCommands.bulletList.description,
|
|
5079
|
-
icon: "format_list_bulleted",
|
|
5080
|
-
keywords: slashCommands.bulletList.keywords,
|
|
5081
|
-
command: (editor) => editor.chain().focus().toggleBulletList().run(),
|
|
5082
|
-
},
|
|
5083
|
-
{
|
|
5084
|
-
title: slashCommands.orderedList.title,
|
|
5085
|
-
description: slashCommands.orderedList.description,
|
|
5086
|
-
icon: "format_list_numbered",
|
|
5087
|
-
keywords: slashCommands.orderedList.keywords,
|
|
5088
|
-
command: (editor) => editor.chain().focus().toggleOrderedList().run(),
|
|
5089
|
-
},
|
|
5090
|
-
{
|
|
5091
|
-
title: slashCommands.blockquote.title,
|
|
5092
|
-
description: slashCommands.blockquote.description,
|
|
5093
|
-
icon: "format_quote",
|
|
5094
|
-
keywords: slashCommands.blockquote.keywords,
|
|
5095
|
-
command: (editor) => editor.chain().focus().toggleBlockquote().run(),
|
|
5096
|
-
},
|
|
5097
|
-
{
|
|
5098
|
-
title: slashCommands.code.title,
|
|
5099
|
-
description: slashCommands.code.description,
|
|
5100
|
-
icon: "code",
|
|
5101
|
-
keywords: slashCommands.code.keywords,
|
|
5102
|
-
command: (editor) => editor.chain().focus().toggleCodeBlock().run(),
|
|
5103
|
-
},
|
|
5104
|
-
{
|
|
5105
|
-
title: slashCommands.image.title,
|
|
5106
|
-
description: slashCommands.image.description,
|
|
5107
|
-
icon: "image",
|
|
5108
|
-
keywords: slashCommands.image.keywords,
|
|
5109
|
-
command: (editor) => {
|
|
5110
|
-
// Créer un input file temporaire pour sélectionner une image
|
|
5111
|
-
const input = document.createElement("input");
|
|
5112
|
-
input.type = "file";
|
|
5113
|
-
input.accept = "image/*";
|
|
5114
|
-
input.style.display = "none";
|
|
5115
|
-
input.addEventListener("change", async (e) => {
|
|
5116
|
-
const file = e.target.files?.[0];
|
|
5117
|
-
if (file && file.type.startsWith("image/")) {
|
|
5118
|
-
try {
|
|
5119
|
-
// Utiliser la méthode de compression unifiée
|
|
5120
|
-
const canvas = document.createElement("canvas");
|
|
5121
|
-
const ctx = canvas.getContext("2d");
|
|
5122
|
-
const img = new Image();
|
|
5123
|
-
img.onload = () => {
|
|
5124
|
-
// Vérifier les dimensions (max 1920x1080)
|
|
5125
|
-
const maxWidth = 1920;
|
|
5126
|
-
const maxHeight = 1080;
|
|
5127
|
-
let { width, height } = img;
|
|
5128
|
-
// Redimensionner si nécessaire
|
|
5129
|
-
if (width > maxWidth || height > maxHeight) {
|
|
5130
|
-
const ratio = Math.min(maxWidth / width, maxHeight / height);
|
|
5131
|
-
width *= ratio;
|
|
5132
|
-
height *= ratio;
|
|
5133
|
-
}
|
|
5134
|
-
canvas.width = width;
|
|
5135
|
-
canvas.height = height;
|
|
5136
|
-
// Dessiner l'image redimensionnée
|
|
5137
|
-
ctx?.drawImage(img, 0, 0, width, height);
|
|
5138
|
-
// Convertir en base64 avec compression
|
|
5139
|
-
canvas.toBlob((blob) => {
|
|
5140
|
-
if (blob) {
|
|
5141
|
-
const reader = new FileReader();
|
|
5142
|
-
reader.onload = (e) => {
|
|
5143
|
-
const base64 = e.target?.result;
|
|
5144
|
-
if (base64) {
|
|
5145
|
-
// Utiliser setResizableImage avec toutes les propriétés
|
|
5146
|
-
editor
|
|
5147
|
-
.chain()
|
|
5148
|
-
.focus()
|
|
5149
|
-
.setResizableImage({
|
|
5150
|
-
src: base64,
|
|
5151
|
-
alt: file.name,
|
|
5152
|
-
title: `${file.name} (${Math.round(width)}×${Math.round(height)})`,
|
|
5153
|
-
width: Math.round(width),
|
|
5154
|
-
height: Math.round(height),
|
|
5155
|
-
})
|
|
5156
|
-
.run();
|
|
5157
|
-
}
|
|
5158
|
-
};
|
|
5159
|
-
reader.readAsDataURL(blob);
|
|
5160
|
-
}
|
|
5161
|
-
}, file.type, 0.8 // qualité de compression
|
|
5162
|
-
);
|
|
5163
|
-
};
|
|
5164
|
-
img.onerror = () => {
|
|
5165
|
-
console.error(i18nService.editor().imageLoadError);
|
|
5166
|
-
};
|
|
5167
|
-
img.src = URL.createObjectURL(file);
|
|
5168
|
-
}
|
|
5169
|
-
catch (error) {
|
|
5170
|
-
console.error("Error uploading image:", error);
|
|
5171
|
-
}
|
|
5172
|
-
}
|
|
5173
|
-
document.body.removeChild(input);
|
|
5174
|
-
});
|
|
5175
|
-
document.body.appendChild(input);
|
|
5176
|
-
input.click();
|
|
5177
|
-
},
|
|
5178
|
-
},
|
|
5179
|
-
{
|
|
5180
|
-
title: slashCommands.horizontalRule.title,
|
|
5181
|
-
description: slashCommands.horizontalRule.description,
|
|
5182
|
-
icon: "horizontal_rule",
|
|
5183
|
-
keywords: slashCommands.horizontalRule.keywords,
|
|
5184
|
-
command: (editor) => editor.chain().focus().setHorizontalRule().run(),
|
|
5185
|
-
},
|
|
5186
|
-
{
|
|
5187
|
-
title: slashCommands.table.title,
|
|
5188
|
-
description: slashCommands.table.description,
|
|
5189
|
-
icon: "table_view",
|
|
5190
|
-
keywords: slashCommands.table.keywords,
|
|
5191
|
-
command: (editor) => editor.chain().focus().insertTable({ rows: 3, cols: 3 }).run(),
|
|
5192
|
-
},
|
|
5193
|
-
];
|
|
5194
|
-
}
|
|
5195
|
-
/**
|
|
5196
|
-
* Fonction utilitaire pour filtrer les slash commands selon les commandes actives
|
|
5197
|
-
* Utilise le service i18n injecté en interne
|
|
5198
|
-
*/
|
|
5199
|
-
function filterSlashCommands(activeCommands) {
|
|
5200
|
-
// Injecter le service i18n en interne
|
|
5201
|
-
const i18nService = inject(TiptapI18nService);
|
|
5202
|
-
const allCommands = createI18nSlashCommands(i18nService);
|
|
5203
|
-
return allCommands.filter((command, index) => {
|
|
5204
|
-
const commandKey = SLASH_COMMAND_KEYS[index];
|
|
5205
|
-
return commandKey && activeCommands.has(commandKey);
|
|
5206
|
-
});
|
|
5207
|
-
}
|
|
5208
|
-
|
|
5209
5217
|
/*
|
|
5210
5218
|
* Public API Surface of tiptap-editor
|
|
5211
5219
|
*/
|
|
@@ -5215,5 +5223,5 @@ function filterSlashCommands(activeCommands) {
|
|
|
5215
5223
|
* Generated bundle index. Do not edit.
|
|
5216
5224
|
*/
|
|
5217
5225
|
|
|
5218
|
-
export { AngularTiptapEditorComponent, DEFAULT_BUBBLE_MENU_CONFIG, DEFAULT_CELL_MENU_CONFIG, DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, DEFAULT_SLASH_COMMANDS, DEFAULT_TABLE_MENU_CONFIG, DEFAULT_TOOLBAR_CONFIG, EditorCommandsService, ImageService, NoopValueAccessorDirective, SLASH_COMMAND_KEYS, TiptapI18nService, createI18nSlashCommands, filterSlashCommands };
|
|
5226
|
+
export { AngularTiptapEditorComponent, DEFAULT_BUBBLE_MENU_CONFIG, DEFAULT_CELL_MENU_CONFIG, DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, DEFAULT_SLASH_COMMANDS$1 as DEFAULT_SLASH_COMMANDS, DEFAULT_TABLE_MENU_CONFIG, DEFAULT_TOOLBAR_CONFIG, EditorCommandsService, ImageService, NoopValueAccessorDirective, SLASH_COMMAND_KEYS, TiptapI18nService, createI18nSlashCommands, filterSlashCommands };
|
|
5219
5227
|
//# sourceMappingURL=flogeez-angular-tiptap-editor.mjs.map
|