@flogeez/angular-tiptap-editor 0.6.0 → 2.0.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 +22 -0
- package/README.md +93 -31
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +282 -207
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/index.d.ts +24 -19
- package/package.json +1 -1
- package/src/lib/styles/bubble-menu.global.css +3 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { input, output, ChangeDetectionStrategy, Component, signal, computed, Injectable, inject, effect, ViewChild, Directive, viewChild, DestroyRef, untracked } from '@angular/core';
|
|
3
3
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
4
|
-
import { Node as Node$1, nodeInputRule, mergeAttributes, Extension, Editor } from '@tiptap/core';
|
|
4
|
+
import { Node as Node$1, nodeInputRule, mergeAttributes, Extension, getAttributes, Editor } from '@tiptap/core';
|
|
5
5
|
import StarterKit from '@tiptap/starter-kit';
|
|
6
6
|
import Placeholder from '@tiptap/extension-placeholder';
|
|
7
7
|
import CharacterCount from '@tiptap/extension-character-count';
|
|
@@ -144,11 +144,11 @@ const ResizableImage = Node$1.create({
|
|
|
144
144
|
img.height = node.attrs["height"];
|
|
145
145
|
img.parentNode?.insertBefore(container, img);
|
|
146
146
|
container.appendChild(img);
|
|
147
|
-
//
|
|
147
|
+
// Add modern resize controls
|
|
148
148
|
const resizeControls = document.createElement("div");
|
|
149
149
|
resizeControls.className = "resize-controls";
|
|
150
150
|
resizeControls.style.display = "none";
|
|
151
|
-
//
|
|
151
|
+
// Create 8 handles for full resizing capability
|
|
152
152
|
const handles = ["nw", "n", "ne", "w", "e", "sw", "s", "se"];
|
|
153
153
|
handles.forEach((direction) => {
|
|
154
154
|
const handle = document.createElement("div");
|
|
@@ -156,27 +156,27 @@ const ResizableImage = Node$1.create({
|
|
|
156
156
|
handle.setAttribute("data-direction", direction);
|
|
157
157
|
resizeControls.appendChild(handle);
|
|
158
158
|
});
|
|
159
|
-
//
|
|
159
|
+
// Attach controls to container
|
|
160
160
|
container.appendChild(resizeControls);
|
|
161
|
-
// Variables
|
|
161
|
+
// Variables for resizing
|
|
162
162
|
let isResizing = false;
|
|
163
163
|
let startX = 0;
|
|
164
164
|
let startY = 0;
|
|
165
165
|
let startWidth = 0;
|
|
166
166
|
let startHeight = 0;
|
|
167
167
|
let aspectRatio = 1;
|
|
168
|
-
//
|
|
168
|
+
// Calculate aspect ratio
|
|
169
169
|
img.onload = () => {
|
|
170
170
|
aspectRatio = img.naturalWidth / img.naturalHeight;
|
|
171
171
|
};
|
|
172
|
-
//
|
|
172
|
+
// Resizing logic
|
|
173
173
|
const handleMouseDown = (e, direction) => {
|
|
174
174
|
e.preventDefault();
|
|
175
175
|
e.stopPropagation();
|
|
176
176
|
isResizing = true;
|
|
177
177
|
startX = e.clientX;
|
|
178
178
|
startY = e.clientY;
|
|
179
|
-
//
|
|
179
|
+
// Use current image dimensions instead of initial ones
|
|
180
180
|
startWidth =
|
|
181
181
|
parseInt(img.getAttribute("width") || "0") ||
|
|
182
182
|
node.attrs["width"] ||
|
|
@@ -185,7 +185,7 @@ const ResizableImage = Node$1.create({
|
|
|
185
185
|
parseInt(img.getAttribute("height") || "0") ||
|
|
186
186
|
node.attrs["height"] ||
|
|
187
187
|
img.naturalHeight;
|
|
188
|
-
//
|
|
188
|
+
// Add resizing class to body
|
|
189
189
|
document.body.classList.add("resizing");
|
|
190
190
|
const handleMouseMove = (e) => {
|
|
191
191
|
if (!isResizing)
|
|
@@ -194,7 +194,7 @@ const ResizableImage = Node$1.create({
|
|
|
194
194
|
const deltaY = e.clientY - startY;
|
|
195
195
|
let newWidth = startWidth;
|
|
196
196
|
let newHeight = startHeight;
|
|
197
|
-
//
|
|
197
|
+
// Resize according to direction
|
|
198
198
|
switch (direction) {
|
|
199
199
|
case "e":
|
|
200
200
|
newWidth = startWidth + deltaX;
|
|
@@ -229,17 +229,17 @@ const ResizableImage = Node$1.create({
|
|
|
229
229
|
newHeight = startHeight - deltaY;
|
|
230
230
|
break;
|
|
231
231
|
}
|
|
232
|
-
//
|
|
232
|
+
// Limits
|
|
233
233
|
newWidth = Math.max(50, Math.min(2000, newWidth));
|
|
234
234
|
newHeight = Math.max(50, Math.min(2000, newHeight));
|
|
235
|
-
//
|
|
235
|
+
// Update image attributes directly
|
|
236
236
|
img.setAttribute("width", Math.round(newWidth).toString());
|
|
237
237
|
img.setAttribute("height", Math.round(newHeight).toString());
|
|
238
238
|
};
|
|
239
239
|
const handleMouseUp = () => {
|
|
240
240
|
isResizing = false;
|
|
241
241
|
document.body.classList.remove("resizing");
|
|
242
|
-
//
|
|
242
|
+
// Update Tiptap node with new dimensions
|
|
243
243
|
if (typeof getPos === "function") {
|
|
244
244
|
const finalWidth = parseInt(img.getAttribute("width") || "0");
|
|
245
245
|
const finalHeight = parseInt(img.getAttribute("height") || "0");
|
|
@@ -256,7 +256,7 @@ const ResizableImage = Node$1.create({
|
|
|
256
256
|
document.addEventListener("mousemove", handleMouseMove);
|
|
257
257
|
document.addEventListener("mouseup", handleMouseUp);
|
|
258
258
|
};
|
|
259
|
-
//
|
|
259
|
+
// Add events to handles
|
|
260
260
|
resizeControls.addEventListener("mousedown", (e) => {
|
|
261
261
|
const target = e.target;
|
|
262
262
|
if (target.classList.contains("resize-handle")) {
|
|
@@ -541,6 +541,7 @@ const INITIAL_EDITOR_STATE = {
|
|
|
541
541
|
computedColor: null,
|
|
542
542
|
background: null,
|
|
543
543
|
computedBackground: null,
|
|
544
|
+
linkOpenOnClick: false,
|
|
544
545
|
},
|
|
545
546
|
can: {
|
|
546
547
|
toggleBold: false,
|
|
@@ -573,6 +574,7 @@ const INITIAL_EDITOR_STATE = {
|
|
|
573
574
|
toggleBulletList: false,
|
|
574
575
|
toggleOrderedList: false,
|
|
575
576
|
toggleBlockquote: false,
|
|
577
|
+
toggleCodeBlock: false,
|
|
576
578
|
setTextAlignLeft: false,
|
|
577
579
|
setTextAlignCenter: false,
|
|
578
580
|
setTextAlignRight: false,
|
|
@@ -605,22 +607,22 @@ const INITIAL_EDITOR_STATE = {
|
|
|
605
607
|
};
|
|
606
608
|
|
|
607
609
|
/**
|
|
608
|
-
*
|
|
609
|
-
*
|
|
610
|
+
* High-performance flat property merger.
|
|
611
|
+
* Processes sub-objects (marks, can, nodes) property by property.
|
|
610
612
|
*/
|
|
611
613
|
function fastMerge(target, source) {
|
|
612
614
|
if (!source)
|
|
613
615
|
return;
|
|
614
616
|
for (const key in source) {
|
|
615
617
|
const sourceVal = source[key];
|
|
616
|
-
//
|
|
618
|
+
// If the value is an object (marks, can, nodes, selection)
|
|
617
619
|
if (sourceVal !== null && typeof sourceVal === 'object' && !Array.isArray(sourceVal)) {
|
|
618
620
|
if (!target[key])
|
|
619
621
|
target[key] = {};
|
|
620
|
-
//
|
|
622
|
+
// Merge internal properties
|
|
621
623
|
for (const subKey in sourceVal) {
|
|
622
624
|
const subVal = sourceVal[subKey];
|
|
623
|
-
//
|
|
625
|
+
// TRUE priority rule for boolean state categories
|
|
624
626
|
if (typeof subVal === 'boolean' && (key === 'marks' || key === 'can' || key === 'nodes')) {
|
|
625
627
|
target[key][subKey] = target[key][subKey] || subVal;
|
|
626
628
|
}
|
|
@@ -630,7 +632,7 @@ function fastMerge(target, source) {
|
|
|
630
632
|
}
|
|
631
633
|
}
|
|
632
634
|
else {
|
|
633
|
-
//
|
|
635
|
+
// Simple value (isFocused, isEditable)
|
|
634
636
|
target[key] = sourceVal;
|
|
635
637
|
}
|
|
636
638
|
}
|
|
@@ -718,6 +720,7 @@ class TiptapButtonComponent {
|
|
|
718
720
|
[style.color]="color()"
|
|
719
721
|
[style.background-color]="backgroundColor()"
|
|
720
722
|
[attr.title]="title()"
|
|
723
|
+
[attr.aria-label]="title()"
|
|
721
724
|
(mousedown)="onMouseDown($event)"
|
|
722
725
|
(click)="onClick.emit($event)"
|
|
723
726
|
type="button"
|
|
@@ -732,7 +735,7 @@ class TiptapButtonComponent {
|
|
|
732
735
|
}
|
|
733
736
|
<ng-content></ng-content>
|
|
734
737
|
</button>
|
|
735
|
-
`, isInline: true, styles: [".tiptap-button{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;background:transparent;border-radius:var(--ate-border-radius, 8px);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);color:var(--ate-toolbar-button-color, var(--ate-text-secondary));position:relative;overflow:hidden}.tiptap-button:before{content:\"\";position:absolute;inset:0;background:var(--ate-primary);opacity:0;transition:opacity .2s ease;border-radius:var(--ate-border-radius, 8px)}.tiptap-button:hover:not(.has-custom-color){color:var(--ate-toolbar-button-active-color, var(--ate-primary));background:var(--ate-toolbar-button-hover-background, transparent);transform:translateY(-1px)}.tiptap-button.has-custom-color:hover:not(.has-custom-bg){background:var(--ate-toolbar-button-hover-background, transparent);transform:translateY(-1px)}.tiptap-button.has-custom-bg:hover{transform:translateY(-1px);filter:brightness(.9)}.tiptap-button:hover:before{opacity:.1}.tiptap-button:active{transform:translateY(0)}.tiptap-button.is-active:not(.has-custom-color){color:var(--ate-toolbar-button-active-color, var(--ate-primary));background:var(--ate-toolbar-button-active-background, var(--ate-primary-light))}.tiptap-button.is-active.has-custom-color{background:var(--ate-toolbar-button-active-background, var(--ate-primary-light))}.tiptap-button:disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.tiptap-button .material-symbols-outlined{font-size:20px;position:relative;z-index:1}.tiptap-button .material-symbols-outlined.icon-small{font-size:16px}.tiptap-button .material-symbols-outlined.icon-medium{font-size:20px}.tiptap-button .material-symbols-outlined.icon-large{font-size:24px}.tiptap-button.text-button{width:auto;padding:0 12px;font-size:14px;font-weight:500;gap:8px}.tiptap-button.color-button{width:28px;height:28px;border-radius:50%;border:2px solid transparent;transition:all .2s ease}.tiptap-button.color-button:hover{border-color:var(--ate-border);transform:scale(1.1)}.tiptap-button.color-button.is-active{border-color:var(--ate-primary);box-shadow:0 0 0 2px var(--ate-primary-light)}.tiptap-button.danger{color:var(--ate-error-color, #ef4444)}.tiptap-button.danger:hover{color:var(--ate-error-color, #ef4444);background:var(--ate-error-bg, rgba(239, 68, 68, .1))}.tiptap-button.danger:before{background:var(--ate-error-color, #ef4444)}.tiptap-button.small{width:24px;height:24px}.tiptap-button.medium{width:32px;height:32px}.tiptap-button.large{width:40px;height:40px}@keyframes pulse{0%,to{box-shadow:0 0 0 0 var(--ate-primary-light-alpha)}50%{box-shadow:0 0 0 4px transparent}}.tiptap-button.is-active.pulse{animation:pulse 2s infinite}@media (max-width: 768px){.tiptap-button{width:32px;height:32px}.tiptap-button .material-symbols-outlined{font-size:18px}.tiptap-button.text-button{padding:0 8px;font-size:13px}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
738
|
+
`, isInline: true, styles: [".tiptap-button{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;background:transparent;border-radius:var(--ate-button-border-radius, 8px);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);color:var(--ate-toolbar-button-color, var(--ate-text-secondary));position:relative;overflow:hidden}.tiptap-button:before{content:\"\";position:absolute;inset:0;background:var(--ate-primary);opacity:0;transition:opacity .2s ease;border-radius:var(--ate-button-border-radius, 8px)}.tiptap-button:hover:not(.has-custom-color){color:var(--ate-toolbar-button-active-color, var(--ate-primary));background:var(--ate-toolbar-button-hover-background, transparent);transform:translateY(-1px)}.tiptap-button.has-custom-color:hover:not(.has-custom-bg){background:var(--ate-toolbar-button-hover-background, transparent);transform:translateY(-1px)}.tiptap-button.has-custom-bg:hover{transform:translateY(-1px);filter:brightness(.9)}.tiptap-button:hover:before{opacity:.1}.tiptap-button:active{transform:translateY(0)}.tiptap-button.is-active:not(.has-custom-color){color:var(--ate-toolbar-button-active-color, var(--ate-primary));background:var(--ate-toolbar-button-active-background, var(--ate-primary-light))}.tiptap-button.is-active.has-custom-color{background:var(--ate-toolbar-button-active-background, var(--ate-primary-light))}.tiptap-button:disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.tiptap-button .material-symbols-outlined{font-size:20px;position:relative;z-index:1}.tiptap-button .material-symbols-outlined.icon-small{font-size:16px}.tiptap-button .material-symbols-outlined.icon-medium{font-size:20px}.tiptap-button .material-symbols-outlined.icon-large{font-size:24px}.tiptap-button.text-button{width:auto;padding:0 12px;font-size:14px;font-weight:500;gap:8px}.tiptap-button.color-button{width:28px;height:28px;border-radius:50%;border:2px solid transparent;transition:all .2s ease}.tiptap-button.color-button:hover{border-color:var(--ate-border);transform:scale(1.1)}.tiptap-button.color-button.is-active{border-color:var(--ate-primary);box-shadow:0 0 0 2px var(--ate-primary-light)}.tiptap-button.danger{color:var(--ate-error-color, #ef4444)}.tiptap-button.danger:hover{color:var(--ate-error-color, #ef4444);background:var(--ate-error-bg, rgba(239, 68, 68, .1))}.tiptap-button.danger:before{background:var(--ate-error-color, #ef4444)}.tiptap-button.small{width:24px;height:24px}.tiptap-button.medium{width:32px;height:32px}.tiptap-button.large{width:40px;height:40px}@keyframes pulse{0%,to{box-shadow:0 0 0 0 var(--ate-primary-light-alpha)}50%{box-shadow:0 0 0 4px transparent}}.tiptap-button.is-active.pulse{animation:pulse 2s infinite}@media (max-width: 768px){.tiptap-button{width:32px;height:32px}.tiptap-button .material-symbols-outlined{font-size:18px}.tiptap-button.text-button{padding:0 8px;font-size:13px}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
736
739
|
}
|
|
737
740
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: TiptapButtonComponent, decorators: [{
|
|
738
741
|
type: Component,
|
|
@@ -752,6 +755,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
752
755
|
[style.color]="color()"
|
|
753
756
|
[style.background-color]="backgroundColor()"
|
|
754
757
|
[attr.title]="title()"
|
|
758
|
+
[attr.aria-label]="title()"
|
|
755
759
|
(mousedown)="onMouseDown($event)"
|
|
756
760
|
(click)="onClick.emit($event)"
|
|
757
761
|
type="button"
|
|
@@ -766,7 +770,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
766
770
|
}
|
|
767
771
|
<ng-content></ng-content>
|
|
768
772
|
</button>
|
|
769
|
-
`, styles: [".tiptap-button{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;background:transparent;border-radius:var(--ate-border-radius, 8px);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);color:var(--ate-toolbar-button-color, var(--ate-text-secondary));position:relative;overflow:hidden}.tiptap-button:before{content:\"\";position:absolute;inset:0;background:var(--ate-primary);opacity:0;transition:opacity .2s ease;border-radius:var(--ate-border-radius, 8px)}.tiptap-button:hover:not(.has-custom-color){color:var(--ate-toolbar-button-active-color, var(--ate-primary));background:var(--ate-toolbar-button-hover-background, transparent);transform:translateY(-1px)}.tiptap-button.has-custom-color:hover:not(.has-custom-bg){background:var(--ate-toolbar-button-hover-background, transparent);transform:translateY(-1px)}.tiptap-button.has-custom-bg:hover{transform:translateY(-1px);filter:brightness(.9)}.tiptap-button:hover:before{opacity:.1}.tiptap-button:active{transform:translateY(0)}.tiptap-button.is-active:not(.has-custom-color){color:var(--ate-toolbar-button-active-color, var(--ate-primary));background:var(--ate-toolbar-button-active-background, var(--ate-primary-light))}.tiptap-button.is-active.has-custom-color{background:var(--ate-toolbar-button-active-background, var(--ate-primary-light))}.tiptap-button:disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.tiptap-button .material-symbols-outlined{font-size:20px;position:relative;z-index:1}.tiptap-button .material-symbols-outlined.icon-small{font-size:16px}.tiptap-button .material-symbols-outlined.icon-medium{font-size:20px}.tiptap-button .material-symbols-outlined.icon-large{font-size:24px}.tiptap-button.text-button{width:auto;padding:0 12px;font-size:14px;font-weight:500;gap:8px}.tiptap-button.color-button{width:28px;height:28px;border-radius:50%;border:2px solid transparent;transition:all .2s ease}.tiptap-button.color-button:hover{border-color:var(--ate-border);transform:scale(1.1)}.tiptap-button.color-button.is-active{border-color:var(--ate-primary);box-shadow:0 0 0 2px var(--ate-primary-light)}.tiptap-button.danger{color:var(--ate-error-color, #ef4444)}.tiptap-button.danger:hover{color:var(--ate-error-color, #ef4444);background:var(--ate-error-bg, rgba(239, 68, 68, .1))}.tiptap-button.danger:before{background:var(--ate-error-color, #ef4444)}.tiptap-button.small{width:24px;height:24px}.tiptap-button.medium{width:32px;height:32px}.tiptap-button.large{width:40px;height:40px}@keyframes pulse{0%,to{box-shadow:0 0 0 0 var(--ate-primary-light-alpha)}50%{box-shadow:0 0 0 4px transparent}}.tiptap-button.is-active.pulse{animation:pulse 2s infinite}@media (max-width: 768px){.tiptap-button{width:32px;height:32px}.tiptap-button .material-symbols-outlined{font-size:18px}.tiptap-button.text-button{padding:0 8px;font-size:13px}}\n"] }]
|
|
773
|
+
`, styles: [".tiptap-button{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;background:transparent;border-radius:var(--ate-button-border-radius, 8px);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);color:var(--ate-toolbar-button-color, var(--ate-text-secondary));position:relative;overflow:hidden}.tiptap-button:before{content:\"\";position:absolute;inset:0;background:var(--ate-primary);opacity:0;transition:opacity .2s ease;border-radius:var(--ate-button-border-radius, 8px)}.tiptap-button:hover:not(.has-custom-color){color:var(--ate-toolbar-button-active-color, var(--ate-primary));background:var(--ate-toolbar-button-hover-background, transparent);transform:translateY(-1px)}.tiptap-button.has-custom-color:hover:not(.has-custom-bg){background:var(--ate-toolbar-button-hover-background, transparent);transform:translateY(-1px)}.tiptap-button.has-custom-bg:hover{transform:translateY(-1px);filter:brightness(.9)}.tiptap-button:hover:before{opacity:.1}.tiptap-button:active{transform:translateY(0)}.tiptap-button.is-active:not(.has-custom-color){color:var(--ate-toolbar-button-active-color, var(--ate-primary));background:var(--ate-toolbar-button-active-background, var(--ate-primary-light))}.tiptap-button.is-active.has-custom-color{background:var(--ate-toolbar-button-active-background, var(--ate-primary-light))}.tiptap-button:disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.tiptap-button .material-symbols-outlined{font-size:20px;position:relative;z-index:1}.tiptap-button .material-symbols-outlined.icon-small{font-size:16px}.tiptap-button .material-symbols-outlined.icon-medium{font-size:20px}.tiptap-button .material-symbols-outlined.icon-large{font-size:24px}.tiptap-button.text-button{width:auto;padding:0 12px;font-size:14px;font-weight:500;gap:8px}.tiptap-button.color-button{width:28px;height:28px;border-radius:50%;border:2px solid transparent;transition:all .2s ease}.tiptap-button.color-button:hover{border-color:var(--ate-border);transform:scale(1.1)}.tiptap-button.color-button.is-active{border-color:var(--ate-primary);box-shadow:0 0 0 2px var(--ate-primary-light)}.tiptap-button.danger{color:var(--ate-error-color, #ef4444)}.tiptap-button.danger:hover{color:var(--ate-error-color, #ef4444);background:var(--ate-error-bg, rgba(239, 68, 68, .1))}.tiptap-button.danger:before{background:var(--ate-error-color, #ef4444)}.tiptap-button.small{width:24px;height:24px}.tiptap-button.medium{width:32px;height:32px}.tiptap-button.large{width:40px;height:40px}@keyframes pulse{0%,to{box-shadow:0 0 0 0 var(--ate-primary-light-alpha)}50%{box-shadow:0 0 0 4px transparent}}.tiptap-button.is-active.pulse{animation:pulse 2s infinite}@media (max-width: 768px){.tiptap-button{width:32px;height:32px}.tiptap-button .material-symbols-outlined{font-size:18px}.tiptap-button.text-button{padding:0 8px;font-size:13px}}\n"] }]
|
|
770
774
|
}] });
|
|
771
775
|
|
|
772
776
|
class TiptapSeparatorComponent {
|
|
@@ -806,7 +810,8 @@ const ENGLISH_TRANSLATIONS = {
|
|
|
806
810
|
italic: "Italic",
|
|
807
811
|
underline: "Underline",
|
|
808
812
|
strike: "Strikethrough",
|
|
809
|
-
code: "Code",
|
|
813
|
+
code: "Inline Code",
|
|
814
|
+
codeBlock: "Code Block",
|
|
810
815
|
superscript: "Superscript",
|
|
811
816
|
subscript: "Subscript",
|
|
812
817
|
highlight: "Highlight",
|
|
@@ -970,7 +975,8 @@ const FRENCH_TRANSLATIONS = {
|
|
|
970
975
|
italic: "Italique",
|
|
971
976
|
underline: "Souligné",
|
|
972
977
|
strike: "Barré",
|
|
973
|
-
code: "Code",
|
|
978
|
+
code: "Code en ligne",
|
|
979
|
+
codeBlock: "Bloc de code",
|
|
974
980
|
superscript: "Exposant",
|
|
975
981
|
subscript: "Indice",
|
|
976
982
|
highlight: "Surligner",
|
|
@@ -1144,10 +1150,12 @@ class TiptapI18nService {
|
|
|
1144
1150
|
en: ENGLISH_TRANSLATIONS,
|
|
1145
1151
|
fr: FRENCH_TRANSLATIONS,
|
|
1146
1152
|
});
|
|
1147
|
-
//
|
|
1153
|
+
// Public signals
|
|
1148
1154
|
this.currentLocale = this._currentLocale.asReadonly();
|
|
1155
|
+
/** All loaded translations (useful for dynamic key access) */
|
|
1156
|
+
this.allTranslations = this._translations.asReadonly();
|
|
1149
1157
|
this.translations = computed(() => this._translations()[this._currentLocale()]);
|
|
1150
|
-
//
|
|
1158
|
+
// Fast translation methods
|
|
1151
1159
|
this.t = computed(() => this.translations());
|
|
1152
1160
|
this.toolbar = computed(() => this.translations().toolbar);
|
|
1153
1161
|
this.bubbleMenu = computed(() => this.translations().bubbleMenu);
|
|
@@ -1156,7 +1164,7 @@ class TiptapI18nService {
|
|
|
1156
1164
|
this.imageUpload = computed(() => this.translations().imageUpload);
|
|
1157
1165
|
this.editor = computed(() => this.translations().editor);
|
|
1158
1166
|
this.common = computed(() => this.translations().common);
|
|
1159
|
-
//
|
|
1167
|
+
// Automatically detect browser language
|
|
1160
1168
|
this.detectBrowserLanguage();
|
|
1161
1169
|
}
|
|
1162
1170
|
setLocale(locale) {
|
|
@@ -1169,13 +1177,16 @@ class TiptapI18nService {
|
|
|
1169
1177
|
return Object.keys(this._translations());
|
|
1170
1178
|
}
|
|
1171
1179
|
addTranslations(locale, translations) {
|
|
1172
|
-
this._translations.update((current) =>
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
...current
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1180
|
+
this._translations.update((current) => {
|
|
1181
|
+
const existing = current[locale] || ENGLISH_TRANSLATIONS;
|
|
1182
|
+
return {
|
|
1183
|
+
...current,
|
|
1184
|
+
[locale]: {
|
|
1185
|
+
...existing,
|
|
1186
|
+
...translations,
|
|
1187
|
+
},
|
|
1188
|
+
};
|
|
1189
|
+
});
|
|
1179
1190
|
}
|
|
1180
1191
|
detectBrowserLanguage() {
|
|
1181
1192
|
const browserLang = navigator.language.toLowerCase();
|
|
@@ -1186,7 +1197,7 @@ class TiptapI18nService {
|
|
|
1186
1197
|
this._currentLocale.set("en");
|
|
1187
1198
|
}
|
|
1188
1199
|
}
|
|
1189
|
-
//
|
|
1200
|
+
// Utility methods for components
|
|
1190
1201
|
getToolbarTitle(key) {
|
|
1191
1202
|
return this.translations().toolbar[key];
|
|
1192
1203
|
}
|
|
@@ -1552,13 +1563,10 @@ class ImageService {
|
|
|
1552
1563
|
}, this.t().replacingImage, options);
|
|
1553
1564
|
}
|
|
1554
1565
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ImageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1555
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ImageService
|
|
1566
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ImageService }); }
|
|
1556
1567
|
}
|
|
1557
1568
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ImageService, decorators: [{
|
|
1558
|
-
type: Injectable
|
|
1559
|
-
args: [{
|
|
1560
|
-
providedIn: "root",
|
|
1561
|
-
}]
|
|
1569
|
+
type: Injectable
|
|
1562
1570
|
}] });
|
|
1563
1571
|
|
|
1564
1572
|
/**
|
|
@@ -1788,13 +1796,10 @@ class ColorPickerService {
|
|
|
1788
1796
|
return getContrastColor(color);
|
|
1789
1797
|
}
|
|
1790
1798
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ColorPickerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1791
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ColorPickerService
|
|
1799
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ColorPickerService }); }
|
|
1792
1800
|
}
|
|
1793
1801
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: ColorPickerService, decorators: [{
|
|
1794
|
-
type: Injectable
|
|
1795
|
-
args: [{
|
|
1796
|
-
providedIn: "root",
|
|
1797
|
-
}]
|
|
1802
|
+
type: Injectable
|
|
1798
1803
|
}] });
|
|
1799
1804
|
|
|
1800
1805
|
class LinkService {
|
|
@@ -1882,13 +1887,10 @@ class LinkService {
|
|
|
1882
1887
|
this.close();
|
|
1883
1888
|
}
|
|
1884
1889
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: LinkService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1885
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: LinkService
|
|
1890
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: LinkService }); }
|
|
1886
1891
|
}
|
|
1887
1892
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: LinkService, decorators: [{
|
|
1888
|
-
type: Injectable
|
|
1889
|
-
args: [{
|
|
1890
|
-
providedIn: "root",
|
|
1891
|
-
}]
|
|
1893
|
+
type: Injectable
|
|
1892
1894
|
}] });
|
|
1893
1895
|
|
|
1894
1896
|
class EditorCommandsService {
|
|
@@ -1988,6 +1990,9 @@ class EditorCommandsService {
|
|
|
1988
1990
|
case "toggleCode":
|
|
1989
1991
|
this.toggleCode(editor);
|
|
1990
1992
|
break;
|
|
1993
|
+
case "toggleCodeBlock":
|
|
1994
|
+
this.toggleCodeBlock(editor);
|
|
1995
|
+
break;
|
|
1991
1996
|
case "toggleUnderline":
|
|
1992
1997
|
this.toggleUnderline(editor);
|
|
1993
1998
|
break;
|
|
@@ -2113,6 +2118,11 @@ class EditorCommandsService {
|
|
|
2113
2118
|
return;
|
|
2114
2119
|
editor.chain().focus().toggleCode().run();
|
|
2115
2120
|
}
|
|
2121
|
+
toggleCodeBlock(editor) {
|
|
2122
|
+
if (!editor)
|
|
2123
|
+
return;
|
|
2124
|
+
editor.chain().focus().toggleCodeBlock().run();
|
|
2125
|
+
}
|
|
2116
2126
|
toggleUnderline(editor) {
|
|
2117
2127
|
if (!editor)
|
|
2118
2128
|
return;
|
|
@@ -2291,13 +2301,10 @@ class EditorCommandsService {
|
|
|
2291
2301
|
}
|
|
2292
2302
|
}
|
|
2293
2303
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: EditorCommandsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
2294
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: EditorCommandsService
|
|
2304
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: EditorCommandsService }); }
|
|
2295
2305
|
}
|
|
2296
2306
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: EditorCommandsService, decorators: [{
|
|
2297
|
-
type: Injectable
|
|
2298
|
-
args: [{
|
|
2299
|
-
providedIn: "root",
|
|
2300
|
-
}]
|
|
2307
|
+
type: Injectable
|
|
2301
2308
|
}] });
|
|
2302
2309
|
|
|
2303
2310
|
class TiptapColorPickerComponent {
|
|
@@ -2330,7 +2337,7 @@ class TiptapColorPickerComponent {
|
|
|
2330
2337
|
}
|
|
2331
2338
|
// For text mode, add contrast background if current color is too light
|
|
2332
2339
|
if (this.colorPickerSvc.getLuminance(color) > 200) {
|
|
2333
|
-
return "#
|
|
2340
|
+
return "#030617";
|
|
2334
2341
|
}
|
|
2335
2342
|
return "";
|
|
2336
2343
|
});
|
|
@@ -2379,6 +2386,7 @@ class TiptapColorPickerComponent {
|
|
|
2379
2386
|
class="btn-clear-badge"
|
|
2380
2387
|
type="button"
|
|
2381
2388
|
[title]="t().clear"
|
|
2389
|
+
[attr.aria-label]="t().clear"
|
|
2382
2390
|
(click)="onClear($event)"
|
|
2383
2391
|
>
|
|
2384
2392
|
<span class="material-symbols-outlined">close</span>
|
|
@@ -2407,6 +2415,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
2407
2415
|
class="btn-clear-badge"
|
|
2408
2416
|
type="button"
|
|
2409
2417
|
[title]="t().clear"
|
|
2418
|
+
[attr.aria-label]="t().clear"
|
|
2410
2419
|
(click)="onClear($event)"
|
|
2411
2420
|
>
|
|
2412
2421
|
<span class="material-symbols-outlined">close</span>
|
|
@@ -2422,6 +2431,7 @@ class TiptapToolbarComponent {
|
|
|
2422
2431
|
this.editor = input.required();
|
|
2423
2432
|
this.config = input.required();
|
|
2424
2433
|
this.imageUpload = input({});
|
|
2434
|
+
this.floating = input(false);
|
|
2425
2435
|
this.i18nService = inject(TiptapI18nService);
|
|
2426
2436
|
this.editorCommands = inject(EditorCommandsService);
|
|
2427
2437
|
this.t = this.i18nService.toolbar;
|
|
@@ -2434,8 +2444,8 @@ class TiptapToolbarComponent {
|
|
|
2434
2444
|
this.editorCommands.execute(editor, command, ...args);
|
|
2435
2445
|
}
|
|
2436
2446
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: TiptapToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2437
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: TiptapToolbarComponent, isStandalone: true, selector: "tiptap-toolbar", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
2438
|
-
<div class="tiptap-toolbar">
|
|
2447
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.0", type: TiptapToolbarComponent, isStandalone: true, selector: "tiptap-toolbar", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null }, floating: { classPropertyName: "floating", publicName: "floating", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
|
|
2448
|
+
<div class="tiptap-toolbar" [class.floating]="floating()">
|
|
2439
2449
|
@if (config().bold) {
|
|
2440
2450
|
<tiptap-button
|
|
2441
2451
|
icon="format_bold"
|
|
@@ -2476,6 +2486,14 @@ class TiptapToolbarComponent {
|
|
|
2476
2486
|
[disabled]="!state().can.toggleCode"
|
|
2477
2487
|
(onClick)="onCommand('toggleCode')"
|
|
2478
2488
|
/>
|
|
2489
|
+
} @if (config().codeBlock) {
|
|
2490
|
+
<tiptap-button
|
|
2491
|
+
icon="terminal"
|
|
2492
|
+
[title]="t().codeBlock"
|
|
2493
|
+
[active]="state().nodes.isCodeBlock"
|
|
2494
|
+
[disabled]="!state().can.toggleCodeBlock"
|
|
2495
|
+
(onClick)="onCommand('toggleCodeBlock')"
|
|
2496
|
+
/>
|
|
2479
2497
|
} @if (config().superscript) {
|
|
2480
2498
|
<tiptap-button
|
|
2481
2499
|
icon="superscript"
|
|
@@ -2660,7 +2678,7 @@ class TiptapToolbarComponent {
|
|
|
2660
2678
|
/>
|
|
2661
2679
|
}
|
|
2662
2680
|
</div>
|
|
2663
|
-
`, isInline: true, styles: [".tiptap-toolbar{display:flex;align-items:center;gap:4px;padding:
|
|
2681
|
+
`, isInline: true, styles: [":host{display:block;transition:opacity .3s ease}:host-context(.floating-toolbar){position:sticky;top:3rem;left:0;right:0;z-index:100;display:flex;height:0;overflow:visible;pointer-events:none;opacity:0}:host-context(.floating-toolbar:focus-within),:host-context(.floating-toolbar:hover){opacity:1}.tiptap-toolbar{display:flex;align-items:center;gap:4px;padding:var(--ate-toolbar-padding);background:var(--ate-toolbar-background);border-bottom:1px solid var(--ate-toolbar-border-color);flex-wrap:wrap;min-height:32px;position:relative;z-index:50;border-top-left-radius:calc(var(--ate-menu-border-radius, 8px) - var(--ate-border-width, 2px));border-top-right-radius:calc(var(--ate-menu-border-radius, 8px) - var(--ate-border-width, 2px))}.tiptap-toolbar.floating{pointer-events:auto;border-radius:var(--ate-menu-border-radius, 8px);border:1px solid var(--ate-menu-border)!important;box-shadow:var(--ate-menu-shadow)!important;background:var(--ate-menu-bg)!important;padding:var(--ate-menu-padding)!important;flex-wrap:nowrap;overflow-x:auto;max-width:95vw;scrollbar-width:none;transform:translateY(0);transition:transform .3s cubic-bezier(.4,0,.2,1)}.tiptap-toolbar.floating::-webkit-scrollbar{display:none}:host-context(.floating-toolbar:focus-within) .tiptap-toolbar.floating,:host-context(.floating-toolbar:hover) .tiptap-toolbar.floating{transform:translateY(-2rem)}@media (max-width: 768px){.tiptap-toolbar{padding:6px 8px;gap:2px}}@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"], dependencies: [{ kind: "component", type: TiptapButtonComponent, selector: "tiptap-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["onClick"] }, { kind: "component", type: TiptapSeparatorComponent, selector: "tiptap-separator", inputs: ["orientation", "size"] }, { kind: "component", type: TiptapColorPickerComponent, selector: "tiptap-color-picker", inputs: ["editor", "mode", "disabled", "anchorToText"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
2664
2682
|
}
|
|
2665
2683
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: TiptapToolbarComponent, decorators: [{
|
|
2666
2684
|
type: Component,
|
|
@@ -2669,7 +2687,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
2669
2687
|
TiptapSeparatorComponent,
|
|
2670
2688
|
TiptapColorPickerComponent,
|
|
2671
2689
|
], template: `
|
|
2672
|
-
<div class="tiptap-toolbar">
|
|
2690
|
+
<div class="tiptap-toolbar" [class.floating]="floating()">
|
|
2673
2691
|
@if (config().bold) {
|
|
2674
2692
|
<tiptap-button
|
|
2675
2693
|
icon="format_bold"
|
|
@@ -2710,6 +2728,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
2710
2728
|
[disabled]="!state().can.toggleCode"
|
|
2711
2729
|
(onClick)="onCommand('toggleCode')"
|
|
2712
2730
|
/>
|
|
2731
|
+
} @if (config().codeBlock) {
|
|
2732
|
+
<tiptap-button
|
|
2733
|
+
icon="terminal"
|
|
2734
|
+
[title]="t().codeBlock"
|
|
2735
|
+
[active]="state().nodes.isCodeBlock"
|
|
2736
|
+
[disabled]="!state().can.toggleCodeBlock"
|
|
2737
|
+
(onClick)="onCommand('toggleCodeBlock')"
|
|
2738
|
+
/>
|
|
2713
2739
|
} @if (config().superscript) {
|
|
2714
2740
|
<tiptap-button
|
|
2715
2741
|
icon="superscript"
|
|
@@ -2894,7 +2920,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
2894
2920
|
/>
|
|
2895
2921
|
}
|
|
2896
2922
|
</div>
|
|
2897
|
-
`, styles: [".tiptap-toolbar{display:flex;align-items:center;gap:4px;padding:
|
|
2923
|
+
`, styles: [":host{display:block;transition:opacity .3s ease}:host-context(.floating-toolbar){position:sticky;top:3rem;left:0;right:0;z-index:100;display:flex;height:0;overflow:visible;pointer-events:none;opacity:0}:host-context(.floating-toolbar:focus-within),:host-context(.floating-toolbar:hover){opacity:1}.tiptap-toolbar{display:flex;align-items:center;gap:4px;padding:var(--ate-toolbar-padding);background:var(--ate-toolbar-background);border-bottom:1px solid var(--ate-toolbar-border-color);flex-wrap:wrap;min-height:32px;position:relative;z-index:50;border-top-left-radius:calc(var(--ate-menu-border-radius, 8px) - var(--ate-border-width, 2px));border-top-right-radius:calc(var(--ate-menu-border-radius, 8px) - var(--ate-border-width, 2px))}.tiptap-toolbar.floating{pointer-events:auto;border-radius:var(--ate-menu-border-radius, 8px);border:1px solid var(--ate-menu-border)!important;box-shadow:var(--ate-menu-shadow)!important;background:var(--ate-menu-bg)!important;padding:var(--ate-menu-padding)!important;flex-wrap:nowrap;overflow-x:auto;max-width:95vw;scrollbar-width:none;transform:translateY(0);transition:transform .3s cubic-bezier(.4,0,.2,1)}.tiptap-toolbar.floating::-webkit-scrollbar{display:none}:host-context(.floating-toolbar:focus-within) .tiptap-toolbar.floating,:host-context(.floating-toolbar:hover) .tiptap-toolbar.floating{transform:translateY(-2rem)}@media (max-width: 768px){.tiptap-toolbar{padding:6px 8px;gap:2px}}@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"] }]
|
|
2898
2924
|
}] });
|
|
2899
2925
|
|
|
2900
2926
|
/**
|
|
@@ -3467,7 +3493,7 @@ class TiptapImageBubbleMenuComponent extends TiptapBaseBubbleMenu {
|
|
|
3467
3493
|
if (!ed)
|
|
3468
3494
|
return;
|
|
3469
3495
|
try {
|
|
3470
|
-
//
|
|
3496
|
+
// Use dedicated method to replace an existing image
|
|
3471
3497
|
await this.imageService.selectAndReplaceImage(ed, {
|
|
3472
3498
|
quality: 0.8,
|
|
3473
3499
|
maxWidth: 1920,
|
|
@@ -4582,6 +4608,7 @@ class TiptapColorBubbleMenuComponent {
|
|
|
4582
4608
|
type="text"
|
|
4583
4609
|
class="hex-input"
|
|
4584
4610
|
[value]="hexValue()"
|
|
4611
|
+
[attr.aria-label]="t().customColor"
|
|
4585
4612
|
(input)="onHexInput($event)"
|
|
4586
4613
|
(change)="onHexChange($event)"
|
|
4587
4614
|
(keydown.enter)="onApply($event)"
|
|
@@ -4605,6 +4632,7 @@ class TiptapColorBubbleMenuComponent {
|
|
|
4605
4632
|
type="color"
|
|
4606
4633
|
class="hidden-native-input"
|
|
4607
4634
|
[value]="currentColor()"
|
|
4635
|
+
[attr.aria-label]="t().customColor"
|
|
4608
4636
|
(input)="onNativeInput($event)"
|
|
4609
4637
|
(change)="onNativeChange($event)"
|
|
4610
4638
|
(focus)="onFocus()"
|
|
@@ -4666,6 +4694,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
4666
4694
|
type="text"
|
|
4667
4695
|
class="hex-input"
|
|
4668
4696
|
[value]="hexValue()"
|
|
4697
|
+
[attr.aria-label]="t().customColor"
|
|
4669
4698
|
(input)="onHexInput($event)"
|
|
4670
4699
|
(change)="onHexChange($event)"
|
|
4671
4700
|
(keydown.enter)="onApply($event)"
|
|
@@ -4689,6 +4718,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
4689
4718
|
type="color"
|
|
4690
4719
|
class="hidden-native-input"
|
|
4691
4720
|
[value]="currentColor()"
|
|
4721
|
+
[attr.aria-label]="t().customColor"
|
|
4692
4722
|
(input)="onNativeInput($event)"
|
|
4693
4723
|
(change)="onNativeChange($event)"
|
|
4694
4724
|
(focus)="onFocus()"
|
|
@@ -4805,7 +4835,7 @@ function createDefaultSlashCommands(i18n, commands, imageOptions) {
|
|
|
4805
4835
|
description: t.code.description,
|
|
4806
4836
|
icon: "code",
|
|
4807
4837
|
keywords: t.code.keywords,
|
|
4808
|
-
command: (editor) => commands.
|
|
4838
|
+
command: (editor) => commands.toggleCodeBlock(editor),
|
|
4809
4839
|
},
|
|
4810
4840
|
{
|
|
4811
4841
|
title: t.image.title,
|
|
@@ -4851,7 +4881,7 @@ function filterSlashCommands(config, i18n, commands, imageOptions) {
|
|
|
4851
4881
|
return filtered;
|
|
4852
4882
|
}
|
|
4853
4883
|
|
|
4854
|
-
//
|
|
4884
|
+
// Default command definitions are now centralized in src/lib/config/slash-commands.config.ts
|
|
4855
4885
|
class TiptapSlashCommandsComponent {
|
|
4856
4886
|
constructor() {
|
|
4857
4887
|
this.i18nService = inject(TiptapI18nService);
|
|
@@ -4859,11 +4889,11 @@ class TiptapSlashCommandsComponent {
|
|
|
4859
4889
|
this.config = input(undefined);
|
|
4860
4890
|
this.tippyInstance = null;
|
|
4861
4891
|
this.editorCommands = inject(EditorCommandsService);
|
|
4862
|
-
//
|
|
4892
|
+
// Local state
|
|
4863
4893
|
this.isActive = false;
|
|
4864
4894
|
this.currentQuery = signal("");
|
|
4865
4895
|
this.slashRange = null;
|
|
4866
|
-
// Signal
|
|
4896
|
+
// Signal for selected index
|
|
4867
4897
|
this.selectedIndex = signal(0);
|
|
4868
4898
|
// Toolbar interaction state (from centralized service)
|
|
4869
4899
|
this.isToolbarInteracting = this.editorCommands.isToolbarInteracting;
|
|
@@ -4872,7 +4902,7 @@ class TiptapSlashCommandsComponent {
|
|
|
4872
4902
|
if (config && config.commands) {
|
|
4873
4903
|
return config.commands;
|
|
4874
4904
|
}
|
|
4875
|
-
// Fallback
|
|
4905
|
+
// Fallback to default native commands
|
|
4876
4906
|
return createDefaultSlashCommands(this.i18nService, this.editorCommands);
|
|
4877
4907
|
});
|
|
4878
4908
|
this.filteredCommands = computed(() => {
|
|
@@ -4890,7 +4920,7 @@ class TiptapSlashCommandsComponent {
|
|
|
4890
4920
|
if (!ed)
|
|
4891
4921
|
return;
|
|
4892
4922
|
const { from } = ed.state.selection;
|
|
4893
|
-
//
|
|
4923
|
+
// Check if '/' was typed at the beginning of a line or after a space
|
|
4894
4924
|
const textBefore = ed.state.doc.textBetween(Math.max(0, from - 20), from, "\n");
|
|
4895
4925
|
const slashMatch = textBefore.match(/(?:^|\s)\/([^\/\s]*)$/);
|
|
4896
4926
|
if (slashMatch) {
|
|
@@ -4901,7 +4931,7 @@ class TiptapSlashCommandsComponent {
|
|
|
4901
4931
|
from: from - slashMatch[0].length + slashMatch[0].indexOf("/"),
|
|
4902
4932
|
to: from,
|
|
4903
4933
|
};
|
|
4904
|
-
//
|
|
4934
|
+
// Reset index if menu just became active
|
|
4905
4935
|
if (!wasActive) {
|
|
4906
4936
|
this.selectedIndex.set(0);
|
|
4907
4937
|
}
|
|
@@ -4922,7 +4952,7 @@ class TiptapSlashCommandsComponent {
|
|
|
4922
4952
|
setTimeout(() => this.hideTippy(), 100);
|
|
4923
4953
|
};
|
|
4924
4954
|
this.handleKeyDown = (event) => {
|
|
4925
|
-
//
|
|
4955
|
+
// Only handle keys if menu is active
|
|
4926
4956
|
if (!this.isActive || this.filteredCommands().length === 0) {
|
|
4927
4957
|
return;
|
|
4928
4958
|
}
|
|
@@ -4956,7 +4986,7 @@ class TiptapSlashCommandsComponent {
|
|
|
4956
4986
|
event.stopPropagation();
|
|
4957
4987
|
this.isActive = false;
|
|
4958
4988
|
this.hideTippy();
|
|
4959
|
-
//
|
|
4989
|
+
// Optional: remove the typed "/"
|
|
4960
4990
|
const ed = this.editor();
|
|
4961
4991
|
if (ed && this.slashRange) {
|
|
4962
4992
|
const { tr } = ed.state;
|
|
@@ -4970,20 +5000,19 @@ class TiptapSlashCommandsComponent {
|
|
|
4970
5000
|
const ed = this.editor();
|
|
4971
5001
|
if (!ed)
|
|
4972
5002
|
return;
|
|
4973
|
-
//
|
|
5003
|
+
// Clean up old listeners
|
|
4974
5004
|
ed.off("selectionUpdate", this.updateMenu);
|
|
4975
5005
|
ed.off("transaction", this.updateMenu);
|
|
4976
5006
|
ed.off("focus", this.updateMenu);
|
|
4977
5007
|
ed.off("blur", this.handleBlur);
|
|
4978
|
-
//
|
|
5008
|
+
// Add new listeners
|
|
4979
5009
|
ed.on("selectionUpdate", this.updateMenu);
|
|
4980
5010
|
ed.on("transaction", this.updateMenu);
|
|
4981
5011
|
ed.on("focus", this.updateMenu);
|
|
4982
5012
|
ed.on("blur", this.handleBlur);
|
|
4983
|
-
//
|
|
5013
|
+
// Use ProseMirror plugin system to intercept keys
|
|
4984
5014
|
this.addKeyboardPlugin(ed);
|
|
4985
|
-
//
|
|
4986
|
-
// Il sera appelé automatiquement quand l'éditeur sera prêt
|
|
5015
|
+
// updateMenu() will be called automatically when editor is ready
|
|
4987
5016
|
});
|
|
4988
5017
|
}
|
|
4989
5018
|
ngOnInit() {
|
|
@@ -5017,7 +5046,7 @@ class TiptapSlashCommandsComponent {
|
|
|
5017
5046
|
placement: "bottom-start",
|
|
5018
5047
|
theme: "slash-menu",
|
|
5019
5048
|
appendTo: (ref) => {
|
|
5020
|
-
//
|
|
5049
|
+
// Always try to climb up to editor host to inherit CSS variables
|
|
5021
5050
|
const host = this.editor().options.element.closest("angular-tiptap-editor");
|
|
5022
5051
|
return host || document.body;
|
|
5023
5052
|
},
|
|
@@ -5028,7 +5057,7 @@ class TiptapSlashCommandsComponent {
|
|
|
5028
5057
|
plugins: [sticky],
|
|
5029
5058
|
sticky: false,
|
|
5030
5059
|
getReferenceClientRect: () => this.getSlashRect(),
|
|
5031
|
-
//
|
|
5060
|
+
// Improve positioning with scroll
|
|
5032
5061
|
popperOptions: {
|
|
5033
5062
|
modifiers: [
|
|
5034
5063
|
{
|
|
@@ -5050,7 +5079,7 @@ class TiptapSlashCommandsComponent {
|
|
|
5050
5079
|
],
|
|
5051
5080
|
},
|
|
5052
5081
|
});
|
|
5053
|
-
//
|
|
5082
|
+
// Initial check after Tippy is initialized
|
|
5054
5083
|
this.updateMenu();
|
|
5055
5084
|
}
|
|
5056
5085
|
getSlashRect() {
|
|
@@ -5059,13 +5088,13 @@ class TiptapSlashCommandsComponent {
|
|
|
5059
5088
|
return new DOMRect(-9999, -9999, 0, 0);
|
|
5060
5089
|
}
|
|
5061
5090
|
try {
|
|
5062
|
-
//
|
|
5091
|
+
// Use ProseMirror coordinates for better precision
|
|
5063
5092
|
const coords = ed.view.coordsAtPos(this.slashRange.from);
|
|
5064
5093
|
return new DOMRect(coords.left, coords.top, 0, coords.bottom - coords.top);
|
|
5065
5094
|
}
|
|
5066
5095
|
catch (error) {
|
|
5067
5096
|
console.warn("Error calculating coordinates:", error);
|
|
5068
|
-
// Fallback
|
|
5097
|
+
// Fallback to window.getSelection
|
|
5069
5098
|
const selection = window.getSelection();
|
|
5070
5099
|
if (!selection || selection.rangeCount === 0) {
|
|
5071
5100
|
return new DOMRect(-9999, -9999, 0, 0);
|
|
@@ -5075,7 +5104,7 @@ class TiptapSlashCommandsComponent {
|
|
|
5075
5104
|
}
|
|
5076
5105
|
}
|
|
5077
5106
|
scrollToSelected() {
|
|
5078
|
-
//
|
|
5107
|
+
// Scroll to the selected element
|
|
5079
5108
|
if (this.menuRef?.nativeElement) {
|
|
5080
5109
|
const selectedItem = this.menuRef.nativeElement.querySelector(".slash-command-item.selected");
|
|
5081
5110
|
if (selectedItem) {
|
|
@@ -5099,28 +5128,27 @@ class TiptapSlashCommandsComponent {
|
|
|
5099
5128
|
const ed = this.editor();
|
|
5100
5129
|
if (!ed || !this.slashRange)
|
|
5101
5130
|
return;
|
|
5102
|
-
//
|
|
5131
|
+
// Remove slash text ("/")
|
|
5103
5132
|
const { tr } = ed.state;
|
|
5104
5133
|
tr.delete(this.slashRange.from, this.slashRange.to);
|
|
5105
5134
|
ed.view.dispatch(tr);
|
|
5106
|
-
//
|
|
5135
|
+
// Hide menu immediately
|
|
5107
5136
|
this.hideTippy();
|
|
5108
5137
|
this.isActive = false;
|
|
5109
|
-
//
|
|
5110
|
-
//
|
|
5111
|
-
// après la suppression du texte "/"
|
|
5138
|
+
// Give focus back to editor and execute command
|
|
5139
|
+
// Use a micro-delay to ensure ProseMirror DOM is stable after removing "/"
|
|
5112
5140
|
setTimeout(() => {
|
|
5113
5141
|
ed.commands.focus();
|
|
5114
5142
|
command.command(ed);
|
|
5115
5143
|
}, 10);
|
|
5116
5144
|
}
|
|
5117
5145
|
addKeyboardPlugin(ed) {
|
|
5118
|
-
//
|
|
5146
|
+
// Add a ProseMirror plugin to intercept keyboard events
|
|
5119
5147
|
const keyboardPlugin = new Plugin$1({
|
|
5120
5148
|
key: new PluginKey$1("slash-commands-keyboard"),
|
|
5121
5149
|
props: {
|
|
5122
5150
|
handleKeyDown: (view, event) => {
|
|
5123
|
-
//
|
|
5151
|
+
// Only handle if menu is active
|
|
5124
5152
|
if (!this.isActive || this.filteredCommands().length === 0) {
|
|
5125
5153
|
return false;
|
|
5126
5154
|
}
|
|
@@ -5150,7 +5178,7 @@ class TiptapSlashCommandsComponent {
|
|
|
5150
5178
|
event.preventDefault();
|
|
5151
5179
|
this.isActive = false;
|
|
5152
5180
|
this.hideTippy();
|
|
5153
|
-
//
|
|
5181
|
+
// Remove typed "/"
|
|
5154
5182
|
if (this.slashRange) {
|
|
5155
5183
|
const { tr } = view.state;
|
|
5156
5184
|
tr.delete(this.slashRange.from, this.slashRange.to);
|
|
@@ -5162,7 +5190,7 @@ class TiptapSlashCommandsComponent {
|
|
|
5162
5190
|
},
|
|
5163
5191
|
},
|
|
5164
5192
|
});
|
|
5165
|
-
//
|
|
5193
|
+
// Add plugin to editor
|
|
5166
5194
|
ed.view.updateState(ed.view.state.reconfigure({
|
|
5167
5195
|
plugins: [keyboardPlugin, ...ed.view.state.plugins],
|
|
5168
5196
|
}));
|
|
@@ -5187,7 +5215,7 @@ class TiptapSlashCommandsComponent {
|
|
|
5187
5215
|
</div>
|
|
5188
5216
|
}
|
|
5189
5217
|
</div>
|
|
5190
|
-
`, isInline: true, styles: [".slash-commands-menu{background:var(--ate-menu-bg)
|
|
5218
|
+
`, isInline: true, styles: [".slash-commands-menu{background:var(--ate-menu-bg);border:1px solid var(--ate-menu-border);border-radius:var(--ate-border-radius, 12px);box-shadow:var(--ate-menu-shadow);padding:6px;max-height:320px;overflow-y:auto;min-width:280px;outline:none;animation:slashMenuFadeIn .2s cubic-bezier(0,0,.2,1);scrollbar-width:thin;scrollbar-color:var(--ate-scrollbar-thumb) var(--ate-scrollbar-track)}.slash-commands-menu::-webkit-scrollbar{width:var(--ate-scrollbar-width)}.slash-commands-menu::-webkit-scrollbar-track{background:var(--ate-scrollbar-track)}.slash-commands-menu::-webkit-scrollbar-thumb{background:var(--ate-scrollbar-thumb);border:3px solid transparent;background-clip:content-box;border-radius:10px}.slash-commands-menu::-webkit-scrollbar-thumb:hover{background:var(--ate-scrollbar-thumb-hover);background-clip:content-box}@keyframes slashMenuFadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.slash-command-item{display:flex;align-items:center;gap:12px;padding:8px 12px;border-radius:var(--ate-border-radius, 8px);cursor:pointer;transition:all .15s ease;border:var(--ate-border-width, 1px) solid transparent;outline:none;margin-bottom:2px}.slash-command-item:last-child{margin-bottom:0}.slash-command-item:hover{background:var(--ate-surface-secondary)}.slash-command-item.selected{background:var(--ate-primary-light);border-color:var(--ate-primary-light-alpha)}.slash-command-icon{display:flex;align-items:center;justify-content:center;width:32px;height:32px;background:var(--ate-surface-tertiary);border-radius:var(--ate-border-radius, 8px);color:var(--ate-primary);flex-shrink:0;transition:all .15s ease}.slash-command-item.selected .slash-command-icon{background:var(--ate-primary);color:var(--ate-primary-contrast, #ffffff)}.slash-command-icon .material-symbols-outlined{font-size:18px}.slash-command-content{flex:1;min-width:0}.slash-command-title{font-weight:500;color:var(--ate-text);font-size:14px;margin-bottom:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.slash-command-description{color:var(--ate-text-secondary);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
5191
5219
|
}
|
|
5192
5220
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: TiptapSlashCommandsComponent, decorators: [{
|
|
5193
5221
|
type: Component,
|
|
@@ -5210,7 +5238,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
5210
5238
|
</div>
|
|
5211
5239
|
}
|
|
5212
5240
|
</div>
|
|
5213
|
-
`, styles: [".slash-commands-menu{background:var(--ate-menu-bg)
|
|
5241
|
+
`, styles: [".slash-commands-menu{background:var(--ate-menu-bg);border:1px solid var(--ate-menu-border);border-radius:var(--ate-border-radius, 12px);box-shadow:var(--ate-menu-shadow);padding:6px;max-height:320px;overflow-y:auto;min-width:280px;outline:none;animation:slashMenuFadeIn .2s cubic-bezier(0,0,.2,1);scrollbar-width:thin;scrollbar-color:var(--ate-scrollbar-thumb) var(--ate-scrollbar-track)}.slash-commands-menu::-webkit-scrollbar{width:var(--ate-scrollbar-width)}.slash-commands-menu::-webkit-scrollbar-track{background:var(--ate-scrollbar-track)}.slash-commands-menu::-webkit-scrollbar-thumb{background:var(--ate-scrollbar-thumb);border:3px solid transparent;background-clip:content-box;border-radius:10px}.slash-commands-menu::-webkit-scrollbar-thumb:hover{background:var(--ate-scrollbar-thumb-hover);background-clip:content-box}@keyframes slashMenuFadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.slash-command-item{display:flex;align-items:center;gap:12px;padding:8px 12px;border-radius:var(--ate-border-radius, 8px);cursor:pointer;transition:all .15s ease;border:var(--ate-border-width, 1px) solid transparent;outline:none;margin-bottom:2px}.slash-command-item:last-child{margin-bottom:0}.slash-command-item:hover{background:var(--ate-surface-secondary)}.slash-command-item.selected{background:var(--ate-primary-light);border-color:var(--ate-primary-light-alpha)}.slash-command-icon{display:flex;align-items:center;justify-content:center;width:32px;height:32px;background:var(--ate-surface-tertiary);border-radius:var(--ate-border-radius, 8px);color:var(--ate-primary);flex-shrink:0;transition:all .15s ease}.slash-command-item.selected .slash-command-icon{background:var(--ate-primary);color:var(--ate-primary-contrast, #ffffff)}.slash-command-icon .material-symbols-outlined{font-size:18px}.slash-command-content{flex:1;min-width:0}.slash-command-title{font-weight:500;color:var(--ate-text);font-size:14px;margin-bottom:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.slash-command-description{color:var(--ate-text-secondary);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
|
|
5214
5242
|
}], ctorParameters: () => [], propDecorators: { menuRef: [{
|
|
5215
5243
|
type: ViewChild,
|
|
5216
5244
|
args: ["menuRef", { static: false }]
|
|
@@ -5278,8 +5306,10 @@ const MarksCalculator = (editor) => {
|
|
|
5278
5306
|
const isCode = editor.isActive('code'); // Inline code mark
|
|
5279
5307
|
const isImage = editor.isActive('image') || editor.isActive('resizableImage');
|
|
5280
5308
|
// Check if marks are generally allowed based on context
|
|
5281
|
-
|
|
5282
|
-
|
|
5309
|
+
const marksAllowed = !isCodeBlock && !isImage;
|
|
5310
|
+
// For inline code specifically, we don't allow nesting OTHER marks inside it,
|
|
5311
|
+
// but the code mark ITSELF must be togglable to be removed.
|
|
5312
|
+
const isInsideInlineCode = isCode;
|
|
5283
5313
|
// 1. Resolve target element once for this calculation
|
|
5284
5314
|
const getTargetElement = () => {
|
|
5285
5315
|
if (typeof window === 'undefined' || !editor.view?.dom)
|
|
@@ -5312,7 +5342,7 @@ const MarksCalculator = (editor) => {
|
|
|
5312
5342
|
italic: editor.isActive('italic'),
|
|
5313
5343
|
underline: editor.isActive('underline'),
|
|
5314
5344
|
strike: editor.isActive('strike'),
|
|
5315
|
-
code:
|
|
5345
|
+
code: isCode,
|
|
5316
5346
|
superscript: editor.isActive('superscript'),
|
|
5317
5347
|
subscript: editor.isActive('subscript'),
|
|
5318
5348
|
highlight: editor.isActive('highlight'),
|
|
@@ -5322,19 +5352,20 @@ const MarksCalculator = (editor) => {
|
|
|
5322
5352
|
computedColor: colorMark || getStyle('color'),
|
|
5323
5353
|
background: backgroundMark,
|
|
5324
5354
|
computedBackground: backgroundMark || getStyle('background-color'),
|
|
5355
|
+
linkOpenOnClick: editor.extensionManager.extensions.find(ext => ext.name === 'link')?.options?.openOnClick ?? false,
|
|
5325
5356
|
},
|
|
5326
5357
|
can: {
|
|
5327
|
-
toggleBold: marksAllowed && editor.can().toggleBold(),
|
|
5328
|
-
toggleItalic: marksAllowed && editor.can().toggleItalic(),
|
|
5329
|
-
toggleUnderline: marksAllowed && editor.can().toggleUnderline(),
|
|
5330
|
-
toggleStrike: marksAllowed && editor.can().toggleStrike(),
|
|
5358
|
+
toggleBold: marksAllowed && !isInsideInlineCode && editor.can().toggleBold(),
|
|
5359
|
+
toggleItalic: marksAllowed && !isInsideInlineCode && editor.can().toggleItalic(),
|
|
5360
|
+
toggleUnderline: marksAllowed && !isInsideInlineCode && editor.can().toggleUnderline(),
|
|
5361
|
+
toggleStrike: marksAllowed && !isInsideInlineCode && editor.can().toggleStrike(),
|
|
5331
5362
|
toggleCode: marksAllowed && editor.can().toggleCode(),
|
|
5332
|
-
toggleHighlight: marksAllowed && editor.can().toggleHighlight(),
|
|
5333
|
-
toggleLink: marksAllowed && (editor.can().setLink({ href: '' }) || editor.can().unsetLink()),
|
|
5334
|
-
toggleSuperscript: marksAllowed && editor.can().toggleSuperscript(),
|
|
5335
|
-
toggleSubscript: marksAllowed && editor.can().toggleSubscript(),
|
|
5336
|
-
setColor: marksAllowed && editor.can().setColor(''),
|
|
5337
|
-
setHighlight: marksAllowed && editor.can().setHighlight(),
|
|
5363
|
+
toggleHighlight: marksAllowed && !isInsideInlineCode && editor.can().toggleHighlight(),
|
|
5364
|
+
toggleLink: marksAllowed && !isInsideInlineCode && (editor.can().setLink({ href: '' }) || editor.can().unsetLink()),
|
|
5365
|
+
toggleSuperscript: marksAllowed && !isInsideInlineCode && editor.can().toggleSuperscript(),
|
|
5366
|
+
toggleSubscript: marksAllowed && !isInsideInlineCode && editor.can().toggleSubscript(),
|
|
5367
|
+
setColor: marksAllowed && !isInsideInlineCode && editor.can().setColor(''),
|
|
5368
|
+
setHighlight: marksAllowed && !isInsideInlineCode && editor.can().setHighlight(),
|
|
5338
5369
|
undo: editor.can().undo(),
|
|
5339
5370
|
redo: editor.can().redo(),
|
|
5340
5371
|
}
|
|
@@ -5408,6 +5439,7 @@ const StructureCalculator = (editor) => {
|
|
|
5408
5439
|
toggleBulletList: editor.can().toggleBulletList(),
|
|
5409
5440
|
toggleOrderedList: editor.can().toggleOrderedList(),
|
|
5410
5441
|
toggleBlockquote: editor.can().toggleBlockquote(),
|
|
5442
|
+
toggleCodeBlock: editor.can().toggleCodeBlock(),
|
|
5411
5443
|
setTextAlignLeft: editor.can().setTextAlign('left'),
|
|
5412
5444
|
setTextAlignCenter: editor.can().setTextAlign('center'),
|
|
5413
5445
|
setTextAlignRight: editor.can().setTextAlign('right'),
|
|
@@ -5454,16 +5486,44 @@ const DiscoveryCalculator = (editor) => {
|
|
|
5454
5486
|
return state;
|
|
5455
5487
|
};
|
|
5456
5488
|
|
|
5457
|
-
|
|
5489
|
+
const LinkClickBehavior = Extension.create({
|
|
5490
|
+
name: 'linkClickBehavior',
|
|
5491
|
+
addProseMirrorPlugins() {
|
|
5492
|
+
return [
|
|
5493
|
+
new Plugin({
|
|
5494
|
+
key: new PluginKey('linkClickBehavior'),
|
|
5495
|
+
props: {
|
|
5496
|
+
handleClick(view, pos, event) {
|
|
5497
|
+
// handleClick only runs in the browser, but we guard it for absolute SSR safety
|
|
5498
|
+
if (typeof window === 'undefined')
|
|
5499
|
+
return false;
|
|
5500
|
+
// If editor is editable, let TipTap/BubbleMenu handle it
|
|
5501
|
+
if (view.editable)
|
|
5502
|
+
return false;
|
|
5503
|
+
const attrs = getAttributes(view.state, 'link');
|
|
5504
|
+
if (attrs['href']) {
|
|
5505
|
+
window.open(attrs['href'], '_blank', 'noopener,noreferrer');
|
|
5506
|
+
return true;
|
|
5507
|
+
}
|
|
5508
|
+
return false;
|
|
5509
|
+
}
|
|
5510
|
+
}
|
|
5511
|
+
})
|
|
5512
|
+
];
|
|
5513
|
+
}
|
|
5514
|
+
});
|
|
5515
|
+
|
|
5516
|
+
// Default toolbar configuration
|
|
5458
5517
|
const DEFAULT_TOOLBAR_CONFIG = {
|
|
5459
5518
|
bold: true,
|
|
5460
5519
|
italic: true,
|
|
5461
5520
|
underline: true,
|
|
5462
5521
|
strike: true,
|
|
5463
5522
|
code: true,
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5523
|
+
codeBlock: true,
|
|
5524
|
+
superscript: false, // Disabled by default (opt-in)
|
|
5525
|
+
subscript: false, // Disabled by default (opt-in)
|
|
5526
|
+
highlight: false, // Disabled by default (opt-in)
|
|
5467
5527
|
highlightPicker: true,
|
|
5468
5528
|
heading1: true,
|
|
5469
5529
|
heading2: true,
|
|
@@ -5471,21 +5531,21 @@ const DEFAULT_TOOLBAR_CONFIG = {
|
|
|
5471
5531
|
bulletList: true,
|
|
5472
5532
|
orderedList: true,
|
|
5473
5533
|
blockquote: true,
|
|
5474
|
-
alignLeft: false,
|
|
5475
|
-
alignCenter: false,
|
|
5476
|
-
alignRight: false,
|
|
5477
|
-
alignJustify: false,
|
|
5534
|
+
alignLeft: false, // Disabled by default (opt-in)
|
|
5535
|
+
alignCenter: false, // Disabled by default (opt-in)
|
|
5536
|
+
alignRight: false, // Disabled by default (opt-in)
|
|
5537
|
+
alignJustify: false, // Disabled by default (opt-in)
|
|
5478
5538
|
link: true,
|
|
5479
5539
|
image: true,
|
|
5480
|
-
horizontalRule:
|
|
5540
|
+
horizontalRule: false, // Disabled by default (opt-in)
|
|
5481
5541
|
table: true,
|
|
5482
5542
|
undo: true,
|
|
5483
5543
|
redo: true,
|
|
5484
|
-
clear: false, //
|
|
5544
|
+
clear: false, // Disabled by default (opt-in)
|
|
5485
5545
|
textColor: true,
|
|
5486
5546
|
separator: true,
|
|
5487
5547
|
};
|
|
5488
|
-
//
|
|
5548
|
+
// Default bubble menu configuration
|
|
5489
5549
|
const DEFAULT_BUBBLE_MENU_CONFIG = {
|
|
5490
5550
|
bold: true,
|
|
5491
5551
|
italic: true,
|
|
@@ -5500,7 +5560,7 @@ const DEFAULT_BUBBLE_MENU_CONFIG = {
|
|
|
5500
5560
|
link: true,
|
|
5501
5561
|
separator: true,
|
|
5502
5562
|
};
|
|
5503
|
-
//
|
|
5563
|
+
// Default image bubble menu configuration
|
|
5504
5564
|
const DEFAULT_IMAGE_BUBBLE_MENU_CONFIG = {
|
|
5505
5565
|
changeImage: true,
|
|
5506
5566
|
resizeSmall: true,
|
|
@@ -5510,7 +5570,7 @@ const DEFAULT_IMAGE_BUBBLE_MENU_CONFIG = {
|
|
|
5510
5570
|
deleteImage: true,
|
|
5511
5571
|
separator: true,
|
|
5512
5572
|
};
|
|
5513
|
-
//
|
|
5573
|
+
// Default table bubble menu configuration
|
|
5514
5574
|
const DEFAULT_TABLE_MENU_CONFIG = {
|
|
5515
5575
|
addRowBefore: true,
|
|
5516
5576
|
addRowAfter: true,
|
|
@@ -5523,6 +5583,7 @@ const DEFAULT_TABLE_MENU_CONFIG = {
|
|
|
5523
5583
|
deleteTable: true,
|
|
5524
5584
|
separator: true,
|
|
5525
5585
|
};
|
|
5586
|
+
// Default cell bubble menu configuration
|
|
5526
5587
|
const DEFAULT_CELL_MENU_CONFIG = {
|
|
5527
5588
|
mergeCells: true,
|
|
5528
5589
|
splitCell: true,
|
|
@@ -5543,6 +5604,7 @@ class AngularTiptapEditorComponent {
|
|
|
5543
5604
|
this.content = input("");
|
|
5544
5605
|
this.placeholder = input("");
|
|
5545
5606
|
this.editable = input(true);
|
|
5607
|
+
this.disabled = input(false);
|
|
5546
5608
|
this.minHeight = input(200);
|
|
5547
5609
|
this.height = input(undefined);
|
|
5548
5610
|
this.maxHeight = input(undefined);
|
|
@@ -5557,6 +5619,8 @@ class AngularTiptapEditorComponent {
|
|
|
5557
5619
|
this.customSlashCommands = input(undefined);
|
|
5558
5620
|
this.locale = input(undefined);
|
|
5559
5621
|
this.autofocus = input(false);
|
|
5622
|
+
this.seamless = input(false);
|
|
5623
|
+
this.floatingToolbar = input(false);
|
|
5560
5624
|
this.tiptapExtensions = input([]);
|
|
5561
5625
|
this.tiptapOptions = input({});
|
|
5562
5626
|
// Nouveaux inputs pour les bubble menus
|
|
@@ -5564,8 +5628,13 @@ class AngularTiptapEditorComponent {
|
|
|
5564
5628
|
this.bubbleMenu = input(DEFAULT_BUBBLE_MENU_CONFIG);
|
|
5565
5629
|
this.showImageBubbleMenu = input(true);
|
|
5566
5630
|
this.imageBubbleMenu = input(DEFAULT_IMAGE_BUBBLE_MENU_CONFIG);
|
|
5567
|
-
//
|
|
5631
|
+
// Configuration de la toolbar
|
|
5568
5632
|
this.toolbar = input({});
|
|
5633
|
+
// Configuration des menus de table
|
|
5634
|
+
this.showTableBubbleMenu = input(true);
|
|
5635
|
+
this.tableBubbleMenu = input(DEFAULT_TABLE_MENU_CONFIG);
|
|
5636
|
+
this.showCellBubbleMenu = input(true);
|
|
5637
|
+
this.cellBubbleMenu = input(DEFAULT_CELL_MENU_CONFIG);
|
|
5569
5638
|
/**
|
|
5570
5639
|
* Additionnal state calculators to extend the reactive editor state.
|
|
5571
5640
|
*/
|
|
@@ -5598,9 +5667,9 @@ class AngularTiptapEditorComponent {
|
|
|
5598
5667
|
this.editorUpdate = output();
|
|
5599
5668
|
this.editorFocus = output();
|
|
5600
5669
|
this.editorBlur = output();
|
|
5601
|
-
// ViewChild
|
|
5670
|
+
// ViewChild with signal
|
|
5602
5671
|
this.editorElement = viewChild.required("editorElement");
|
|
5603
|
-
//
|
|
5672
|
+
// Private signals for internal state
|
|
5604
5673
|
this._editor = signal(null);
|
|
5605
5674
|
this._characterCount = signal(0);
|
|
5606
5675
|
this._wordCount = signal(0);
|
|
@@ -5608,44 +5677,39 @@ class AngularTiptapEditorComponent {
|
|
|
5608
5677
|
this._editorFullyInitialized = signal(false);
|
|
5609
5678
|
// Anti-echo: track last emitted HTML to prevent cursor reset on parent echo
|
|
5610
5679
|
this.lastEmittedHtml = null;
|
|
5611
|
-
//
|
|
5680
|
+
// Read-only access to signals
|
|
5612
5681
|
this.editor = this._editor.asReadonly();
|
|
5613
5682
|
this.characterCount = this._characterCount.asReadonly();
|
|
5614
5683
|
this.wordCount = this._wordCount.asReadonly();
|
|
5615
5684
|
this.isDragOver = this._isDragOver.asReadonly();
|
|
5616
5685
|
this.editorFullyInitialized = this._editorFullyInitialized.asReadonly();
|
|
5617
|
-
|
|
5686
|
+
this._isFormControlDisabled = signal(false);
|
|
5687
|
+
this.isFormControlDisabled = this._isFormControlDisabled.asReadonly();
|
|
5688
|
+
// Combined disabled state (Input + FormControl)
|
|
5689
|
+
this.mergedDisabled = computed(() => this.disabled() || this.isFormControlDisabled());
|
|
5690
|
+
// Computed for editor states
|
|
5618
5691
|
this.isEditorReady = computed(() => this.editor() !== null);
|
|
5619
|
-
// Computed
|
|
5692
|
+
// Computed for toolbar configuration
|
|
5620
5693
|
this.toolbarConfig = computed(() => Object.keys(this.toolbar()).length === 0
|
|
5621
5694
|
? DEFAULT_TOOLBAR_CONFIG
|
|
5622
5695
|
: this.toolbar());
|
|
5623
|
-
// Computed
|
|
5696
|
+
// Computed for bubble menu configuration
|
|
5624
5697
|
this.bubbleMenuConfig = computed(() => Object.keys(this.bubbleMenu()).length === 0
|
|
5625
5698
|
? DEFAULT_BUBBLE_MENU_CONFIG
|
|
5626
5699
|
: { ...DEFAULT_BUBBLE_MENU_CONFIG, ...this.bubbleMenu() });
|
|
5627
|
-
// Computed
|
|
5700
|
+
// Computed for image bubble menu configuration
|
|
5628
5701
|
this.imageBubbleMenuConfig = computed(() => Object.keys(this.imageBubbleMenu()).length === 0
|
|
5629
5702
|
? DEFAULT_IMAGE_BUBBLE_MENU_CONFIG
|
|
5630
5703
|
: { ...DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ...this.imageBubbleMenu() });
|
|
5631
|
-
// Computed
|
|
5632
|
-
this.tableBubbleMenuConfig = computed(() => (
|
|
5633
|
-
|
|
5634
|
-
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
toggleHeaderRow: true,
|
|
5641
|
-
toggleHeaderColumn: true,
|
|
5642
|
-
}));
|
|
5643
|
-
// Computed pour la configuration du menu de cellules
|
|
5644
|
-
this.cellBubbleMenuConfig = computed(() => ({
|
|
5645
|
-
mergeCells: true,
|
|
5646
|
-
splitCell: true,
|
|
5647
|
-
}));
|
|
5648
|
-
// Computed pour la configuration de l'upload d'images
|
|
5704
|
+
// Computed for table bubble menu configuration
|
|
5705
|
+
this.tableBubbleMenuConfig = computed(() => Object.keys(this.tableBubbleMenu()).length === 0
|
|
5706
|
+
? DEFAULT_TABLE_MENU_CONFIG
|
|
5707
|
+
: { ...DEFAULT_TABLE_MENU_CONFIG, ...this.tableBubbleMenu() });
|
|
5708
|
+
// Computed for cell bubble menu configuration
|
|
5709
|
+
this.cellBubbleMenuConfig = computed(() => Object.keys(this.cellBubbleMenu()).length === 0
|
|
5710
|
+
? DEFAULT_CELL_MENU_CONFIG
|
|
5711
|
+
: { ...DEFAULT_CELL_MENU_CONFIG, ...this.cellBubbleMenu() });
|
|
5712
|
+
// Computed for image upload configuration
|
|
5649
5713
|
this.imageUploadConfig = computed(() => ({
|
|
5650
5714
|
maxSize: 5,
|
|
5651
5715
|
maxWidth: 1920,
|
|
@@ -5658,7 +5722,7 @@ class AngularTiptapEditorComponent {
|
|
|
5658
5722
|
quality: 0.8,
|
|
5659
5723
|
...this.imageUpload(),
|
|
5660
5724
|
}));
|
|
5661
|
-
// Computed
|
|
5725
|
+
// Computed for slash commands configuration
|
|
5662
5726
|
this.slashCommandsConfigComputed = computed(() => {
|
|
5663
5727
|
const customConfig = this.customSlashCommands();
|
|
5664
5728
|
if (customConfig) {
|
|
@@ -5670,22 +5734,27 @@ class AngularTiptapEditorComponent {
|
|
|
5670
5734
|
commands: filterSlashCommands(this.slashCommands(), this.i18nService, this.editorCommandsService, this.imageUploadConfig()),
|
|
5671
5735
|
};
|
|
5672
5736
|
});
|
|
5737
|
+
// Computed for current translations (allows per-instance override via [locale] input)
|
|
5738
|
+
this.currentTranslations = computed(() => {
|
|
5739
|
+
const localeOverride = this.locale();
|
|
5740
|
+
if (localeOverride) {
|
|
5741
|
+
// If a specific language is provided to this instance, try to retrieve it
|
|
5742
|
+
const allTranslations = this.i18nService.allTranslations();
|
|
5743
|
+
return allTranslations[localeOverride] || this.i18nService.translations();
|
|
5744
|
+
}
|
|
5745
|
+
// Otherwise, follow the global service language
|
|
5746
|
+
return this.i18nService.translations();
|
|
5747
|
+
});
|
|
5673
5748
|
this._destroyRef = inject(DestroyRef);
|
|
5674
|
-
// NgControl
|
|
5749
|
+
// NgControl for management of FormControls
|
|
5675
5750
|
this.ngControl = inject(NgControl, { self: true, optional: true });
|
|
5676
5751
|
this.i18nService = inject(TiptapI18nService);
|
|
5677
5752
|
this.editorCommandsService = inject(EditorCommandsService);
|
|
5753
|
+
// Access editor state via service
|
|
5678
5754
|
this.editorState = this.editorCommandsService.editorState;
|
|
5679
|
-
//
|
|
5755
|
+
// Effect to update editor content (with anti-echo)
|
|
5680
5756
|
effect(() => {
|
|
5681
|
-
const
|
|
5682
|
-
if (locale) {
|
|
5683
|
-
this.i18nService.setLocale(locale);
|
|
5684
|
-
}
|
|
5685
|
-
});
|
|
5686
|
-
// Effet pour mettre à jour le contenu de l'éditeur (avec anti-écho)
|
|
5687
|
-
effect(() => {
|
|
5688
|
-
const content = this.content(); // Seule dépendance réactive
|
|
5757
|
+
const content = this.content(); // Sole reactive dependency
|
|
5689
5758
|
untracked(() => {
|
|
5690
5759
|
const editor = this.editor();
|
|
5691
5760
|
const hasFormControl = !!this.ngControl?.control;
|
|
@@ -5697,19 +5766,19 @@ class AngularTiptapEditorComponent {
|
|
|
5697
5766
|
// Double sécurité : on vérifie le contenu actuel de l'éditeur
|
|
5698
5767
|
if (content === editor.getHTML())
|
|
5699
5768
|
return;
|
|
5700
|
-
//
|
|
5769
|
+
// Do not overwrite content if we have a FormControl and content is empty
|
|
5701
5770
|
if (hasFormControl && !content)
|
|
5702
5771
|
return;
|
|
5703
5772
|
editor.commands.setContent(content, false);
|
|
5704
5773
|
});
|
|
5705
5774
|
});
|
|
5706
|
-
//
|
|
5775
|
+
// Effect to update height properties
|
|
5707
5776
|
effect(() => {
|
|
5708
5777
|
const minHeight = this.minHeight();
|
|
5709
5778
|
const height = this.height();
|
|
5710
5779
|
const maxHeight = this.maxHeight();
|
|
5711
5780
|
const element = this.editorElement()?.nativeElement;
|
|
5712
|
-
//
|
|
5781
|
+
// Automatically calculate if scroll is needed
|
|
5713
5782
|
const needsScroll = height !== undefined || maxHeight !== undefined;
|
|
5714
5783
|
if (element) {
|
|
5715
5784
|
element.style.setProperty("--editor-min-height", `${minHeight}px`);
|
|
@@ -5721,7 +5790,10 @@ class AngularTiptapEditorComponent {
|
|
|
5721
5790
|
// Effect to monitor editability changes
|
|
5722
5791
|
effect(() => {
|
|
5723
5792
|
const currentEditor = this.editor();
|
|
5724
|
-
|
|
5793
|
+
// An editor is "editable" if it's not disabled and editable mode is ON
|
|
5794
|
+
const isEditable = this.editable() && !this.mergedDisabled();
|
|
5795
|
+
// An editor is "readonly" if it's explicitly non-editable and not disabled
|
|
5796
|
+
const isReadOnly = !this.editable() && !this.mergedDisabled();
|
|
5725
5797
|
if (currentEditor) {
|
|
5726
5798
|
this.editorCommandsService.setEditable(currentEditor, isEditable);
|
|
5727
5799
|
}
|
|
@@ -5731,13 +5803,6 @@ class AngularTiptapEditorComponent {
|
|
|
5731
5803
|
const handler = this.imageUploadHandler();
|
|
5732
5804
|
this.editorCommandsService.uploadHandler = handler || null;
|
|
5733
5805
|
});
|
|
5734
|
-
// Effect for table hover detection
|
|
5735
|
-
effect(() => {
|
|
5736
|
-
const currentEditor = this.editor();
|
|
5737
|
-
if (!currentEditor)
|
|
5738
|
-
return;
|
|
5739
|
-
// Table hover detection removed (replaced by bubble menu)
|
|
5740
|
-
});
|
|
5741
5806
|
// Effect to update character count limit dynamically
|
|
5742
5807
|
effect(() => {
|
|
5743
5808
|
const editor = this.editor();
|
|
@@ -5789,6 +5854,7 @@ class AngularTiptapEditorComponent {
|
|
|
5789
5854
|
class: "tiptap-link",
|
|
5790
5855
|
},
|
|
5791
5856
|
}),
|
|
5857
|
+
LinkClickBehavior,
|
|
5792
5858
|
Highlight.configure({
|
|
5793
5859
|
multicolor: true,
|
|
5794
5860
|
HTMLAttributes: {
|
|
@@ -5853,7 +5919,7 @@ class AngularTiptapEditorComponent {
|
|
|
5853
5919
|
element: this.editorElement().nativeElement,
|
|
5854
5920
|
extensions,
|
|
5855
5921
|
content: this.content(),
|
|
5856
|
-
editable: this.editable(),
|
|
5922
|
+
editable: this.editable() && !this.mergedDisabled(),
|
|
5857
5923
|
autofocus: this.autofocus(),
|
|
5858
5924
|
onUpdate: ({ editor, transaction }) => {
|
|
5859
5925
|
const html = editor.getHTML();
|
|
@@ -5973,6 +6039,7 @@ class AngularTiptapEditorComponent {
|
|
|
5973
6039
|
setupFormControlSubscription() {
|
|
5974
6040
|
const control = this.ngControl?.control;
|
|
5975
6041
|
if (control) {
|
|
6042
|
+
// Synchronize form control value with editor content
|
|
5976
6043
|
const formValue$ = concat(defer(() => of(control.value)), control.valueChanges);
|
|
5977
6044
|
formValue$
|
|
5978
6045
|
.pipe(tap((value) => {
|
|
@@ -5982,25 +6049,25 @@ class AngularTiptapEditorComponent {
|
|
|
5982
6049
|
}
|
|
5983
6050
|
}), takeUntilDestroyed(this._destroyRef))
|
|
5984
6051
|
.subscribe();
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
6052
|
+
// Synchronize form control status with editor disabled state
|
|
6053
|
+
const formStatus$ = concat(defer(() => of(control.status)), control.statusChanges);
|
|
6054
|
+
formStatus$
|
|
6055
|
+
.pipe(tap((status) => {
|
|
6056
|
+
this._isFormControlDisabled.set(status === 'DISABLED');
|
|
6057
|
+
}), takeUntilDestroyed(this._destroyRef))
|
|
6058
|
+
.subscribe();
|
|
5992
6059
|
}
|
|
5993
6060
|
}
|
|
5994
6061
|
onEditorClick(event) {
|
|
5995
6062
|
const editor = this.editor();
|
|
5996
|
-
if (!editor)
|
|
6063
|
+
if (!editor || !this.editable())
|
|
5997
6064
|
return;
|
|
5998
|
-
//
|
|
6065
|
+
// Verify if click is on the container element and not on the content
|
|
5999
6066
|
const target = event.target;
|
|
6000
6067
|
const editorElement = this.editorElement()?.nativeElement;
|
|
6001
6068
|
if (target === editorElement ||
|
|
6002
6069
|
target.classList.contains("tiptap-content")) {
|
|
6003
|
-
//
|
|
6070
|
+
// Click in the empty space, position the cursor at the end
|
|
6004
6071
|
setTimeout(() => {
|
|
6005
6072
|
const { doc } = editor.state;
|
|
6006
6073
|
const endPos = doc.content.size;
|
|
@@ -6010,20 +6077,20 @@ class AngularTiptapEditorComponent {
|
|
|
6010
6077
|
}
|
|
6011
6078
|
}
|
|
6012
6079
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AngularTiptapEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6013
|
-
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 }, showWordCount: { classPropertyName: "showWordCount", publicName: "showWordCount", 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 }, slashCommands: { classPropertyName: "slashCommands", publicName: "slashCommands", isSignal: true, isRequired: false, transformFunction: null }, customSlashCommands: { classPropertyName: "customSlashCommands", publicName: "customSlashCommands", 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 }, tiptapExtensions: { classPropertyName: "tiptapExtensions", publicName: "tiptapExtensions", isSignal: true, isRequired: false, transformFunction: null }, tiptapOptions: { classPropertyName: "tiptapOptions", publicName: "tiptapOptions", 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 }, stateCalculators: { classPropertyName: "stateCalculators", publicName: "stateCalculators", 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()" } }, providers: [
|
|
6080
|
+
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 }, disabled: { classPropertyName: "disabled", publicName: "disabled", 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 }, showWordCount: { classPropertyName: "showWordCount", publicName: "showWordCount", 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 }, slashCommands: { classPropertyName: "slashCommands", publicName: "slashCommands", isSignal: true, isRequired: false, transformFunction: null }, customSlashCommands: { classPropertyName: "customSlashCommands", publicName: "customSlashCommands", 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 }, seamless: { classPropertyName: "seamless", publicName: "seamless", isSignal: true, isRequired: false, transformFunction: null }, floatingToolbar: { classPropertyName: "floatingToolbar", publicName: "floatingToolbar", isSignal: true, isRequired: false, transformFunction: null }, tiptapExtensions: { classPropertyName: "tiptapExtensions", publicName: "tiptapExtensions", isSignal: true, isRequired: false, transformFunction: null }, tiptapOptions: { classPropertyName: "tiptapOptions", publicName: "tiptapOptions", 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 }, showTableBubbleMenu: { classPropertyName: "showTableBubbleMenu", publicName: "showTableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, tableBubbleMenu: { classPropertyName: "tableBubbleMenu", publicName: "tableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showCellBubbleMenu: { classPropertyName: "showCellBubbleMenu", publicName: "showCellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, cellBubbleMenu: { classPropertyName: "cellBubbleMenu", publicName: "cellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, stateCalculators: { classPropertyName: "stateCalculators", publicName: "stateCalculators", 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()", "class.floating-toolbar": "floatingToolbar()", "class.is-readonly": "!editable() && !mergedDisabled()", "class.is-disabled": "mergedDisabled()", "style.--ate-border-width": "seamless() || mergedDisabled() ? '0' : null", "style.--ate-background": "seamless() ? 'transparent' : (mergedDisabled() ? 'var(--ate-surface-tertiary)' : null)", "style.--ate-toolbar-border-color": "seamless() ? 'transparent' : null", "style.--ate-counter-background": "seamless() ? 'transparent' : null", "style.--ate-counter-border-color": "seamless() ? 'transparent' : null" } }, providers: [
|
|
6014
6081
|
EditorCommandsService,
|
|
6015
6082
|
ImageService,
|
|
6016
|
-
TiptapI18nService,
|
|
6017
6083
|
ColorPickerService,
|
|
6018
6084
|
LinkService,
|
|
6019
6085
|
], viewQueries: [{ propertyName: "editorElement", first: true, predicate: ["editorElement"], descendants: true, isSignal: true }], hostDirectives: [{ directive: NoopValueAccessorDirective }], ngImport: i0, template: `
|
|
6020
|
-
<div class="tiptap-editor"
|
|
6086
|
+
<div class="tiptap-editor">
|
|
6021
6087
|
<!-- Toolbar -->
|
|
6022
|
-
@if (showToolbar() && editor()) {
|
|
6088
|
+
@if (editable() && !mergedDisabled() && showToolbar() && editor()) {
|
|
6023
6089
|
<tiptap-toolbar
|
|
6024
6090
|
[editor]="editor()!"
|
|
6025
6091
|
[config]="toolbarConfig()"
|
|
6026
6092
|
[imageUpload]="imageUploadConfig()"
|
|
6093
|
+
[floating]="floatingToolbar()"
|
|
6027
6094
|
(mouseenter)="hideBubbleMenus()"
|
|
6028
6095
|
(mouseleave)="showBubbleMenus()"
|
|
6029
6096
|
/>
|
|
@@ -6040,7 +6107,7 @@ class AngularTiptapEditorComponent {
|
|
|
6040
6107
|
></div>
|
|
6041
6108
|
|
|
6042
6109
|
<!-- Text Bubble Menu -->
|
|
6043
|
-
@if (showBubbleMenu() && editor()) {
|
|
6110
|
+
@if (editable() && showBubbleMenu() && editor()) {
|
|
6044
6111
|
<tiptap-bubble-menu
|
|
6045
6112
|
[editor]="editor()!"
|
|
6046
6113
|
[config]="bubbleMenuConfig()"
|
|
@@ -6049,7 +6116,7 @@ class AngularTiptapEditorComponent {
|
|
|
6049
6116
|
}
|
|
6050
6117
|
|
|
6051
6118
|
<!-- Image Bubble Menu -->
|
|
6052
|
-
@if (showImageBubbleMenu() && editor()) {
|
|
6119
|
+
@if (editable() && showImageBubbleMenu() && editor()) {
|
|
6053
6120
|
<tiptap-image-bubble-menu
|
|
6054
6121
|
[editor]="editor()!"
|
|
6055
6122
|
[config]="imageBubbleMenuConfig()"
|
|
@@ -6058,7 +6125,7 @@ class AngularTiptapEditorComponent {
|
|
|
6058
6125
|
}
|
|
6059
6126
|
|
|
6060
6127
|
<!-- Link Bubble Menu -->
|
|
6061
|
-
@if (editor()) {
|
|
6128
|
+
@if (editable() && editor()) {
|
|
6062
6129
|
<tiptap-link-bubble-menu
|
|
6063
6130
|
[editor]="editor()!"
|
|
6064
6131
|
[style.display]="editorFullyInitialized() ? 'block' : 'none'"
|
|
@@ -6066,7 +6133,7 @@ class AngularTiptapEditorComponent {
|
|
|
6066
6133
|
}
|
|
6067
6134
|
|
|
6068
6135
|
<!-- Color Bubble Menu -->
|
|
6069
|
-
@if (editor()) {
|
|
6136
|
+
@if (editable() && editor()) {
|
|
6070
6137
|
<tiptap-color-bubble-menu
|
|
6071
6138
|
[editor]="editor()!"
|
|
6072
6139
|
[style.display]="editorFullyInitialized() ? 'block' : 'none'"
|
|
@@ -6074,7 +6141,7 @@ class AngularTiptapEditorComponent {
|
|
|
6074
6141
|
}
|
|
6075
6142
|
|
|
6076
6143
|
<!-- Slash Commands -->
|
|
6077
|
-
@if (enableSlashCommands() && editor()) {
|
|
6144
|
+
@if (editable() && enableSlashCommands() && editor()) {
|
|
6078
6145
|
<tiptap-slash-commands
|
|
6079
6146
|
[editor]="editor()!"
|
|
6080
6147
|
[config]="slashCommandsConfigComputed()"
|
|
@@ -6083,7 +6150,7 @@ class AngularTiptapEditorComponent {
|
|
|
6083
6150
|
}
|
|
6084
6151
|
|
|
6085
6152
|
<!-- Table Menu -->
|
|
6086
|
-
@if (editor()) {
|
|
6153
|
+
@if (editable() && editor()) {
|
|
6087
6154
|
<tiptap-table-bubble-menu
|
|
6088
6155
|
[editor]="editor()!"
|
|
6089
6156
|
[config]="tableBubbleMenuConfig()"
|
|
@@ -6092,7 +6159,7 @@ class AngularTiptapEditorComponent {
|
|
|
6092
6159
|
}
|
|
6093
6160
|
|
|
6094
6161
|
<!-- Cell Menu -->
|
|
6095
|
-
@if (editor()) {
|
|
6162
|
+
@if (editable() && editor()) {
|
|
6096
6163
|
<tiptap-cell-bubble-menu
|
|
6097
6164
|
[editor]="editor()!"
|
|
6098
6165
|
[config]="cellBubbleMenuConfig()"
|
|
@@ -6101,11 +6168,11 @@ class AngularTiptapEditorComponent {
|
|
|
6101
6168
|
}
|
|
6102
6169
|
|
|
6103
6170
|
<!-- Counters -->
|
|
6104
|
-
@if (showCharacterCount() || showWordCount()) {
|
|
6171
|
+
@if (editable() && !mergedDisabled() && (showCharacterCount() || showWordCount())) {
|
|
6105
6172
|
<div class="character-count" [class.limit-reached]="maxCharacters() && characterCount() >= maxCharacters()!">
|
|
6106
6173
|
@if (showCharacterCount()) {
|
|
6107
6174
|
{{ characterCount() }}
|
|
6108
|
-
{{
|
|
6175
|
+
{{ currentTranslations().editor.character }}{{ characterCount() > 1 ? "s" : "" }}
|
|
6109
6176
|
@if (maxCharacters()) {
|
|
6110
6177
|
/ {{ maxCharacters() }}
|
|
6111
6178
|
}
|
|
@@ -6117,17 +6184,25 @@ class AngularTiptapEditorComponent {
|
|
|
6117
6184
|
|
|
6118
6185
|
@if (showWordCount()) {
|
|
6119
6186
|
{{ wordCount() }}
|
|
6120
|
-
{{
|
|
6187
|
+
{{ currentTranslations().editor.word }}{{ wordCount() > 1 ? "s" : "" }}
|
|
6121
6188
|
}
|
|
6122
6189
|
</div>
|
|
6123
6190
|
}
|
|
6124
6191
|
</div>
|
|
6125
|
-
`, isInline: true, styles: [":host{--ate-primary: #2563eb;--ate-primary-contrast: #ffffff;--ate-primary-light: color-mix(in srgb, var(--ate-primary), transparent 90%);--ate-primary-lighter: color-mix(in srgb, var(--ate-primary), transparent 95%);--ate-primary-light-alpha: color-mix(in srgb, var(--ate-primary), transparent 85%);--ate-surface: #ffffff;--ate-surface-secondary: #f8f9fa;--ate-surface-tertiary: #f1f5f9;--ate-text: #2d3748;--ate-text-secondary: #64748b;--ate-text-muted: #a0aec0;--ate-border: #e2e8f0;--ate-highlight-bg: #fef08a;--ate-highlight-color: #854d0e;--ate-button-hover: #f1f5f9;--ate-button-active: #e2e8f0;--ate-menu-bg: rgba(255, 255, 255, .98);--ate-menu-border: var(--ate-border);--ate-menu-shadow: 0 10px 15px -3px rgba(0, 0, 0, .1), 0 4px 6px -2px rgba(0, 0, 0, .05);--ate-menu-blur: 16px;--ate-error-color: #c53030;--ate-error-bg: #fed7d7;--ate-error-border: #feb2b2;--ate-border-color: var(--ate-border);--ate-border-width: 2px;--ate-border-radius: 8px;--ate-focus-color: var(--ate-primary);--ate-background: var(--ate-surface);--ate-text-color: var(--ate-text);--ate-placeholder-color: var(--ate-text-muted);--ate-line-height: 1.6;--ate-content-padding: 16px;--ate-toolbar-background: var(--ate-surface-secondary);--ate-toolbar-border-color: var(--ate-border);--ate-toolbar-button-color: var(--ate-text-secondary);--ate-toolbar-button-hover-background: transparent;--ate-toolbar-button-active-background: var(--ate-primary-light);--ate-toolbar-button-active-color: var(--ate-primary);--ate-counter-color: var(--ate-text-secondary);--ate-counter-background: var(--ate-surface-secondary);--ate-counter-border-color: var(--ate-border);--ate-drag-background: #f0f8ff;--ate-drag-border-color: var(--ate-primary);--ate-blockquote-border-color: var(--ate-border);--ate-blockquote-background: var(--ate-surface-secondary);--ate-code-background: var(--ate-surface-secondary);--ate-code-color: var(--ate-text);--ate-code-block-background: #181825;--ate-code-block-color: #e2e8f0;--ate-code-border-color: var(--ate-border);--ate-code-block-border-color: var(--ate-border);--ate-image-border-radius: 8px;--ate-image-selected-color: var(--ate-primary);--ate-scrollbar-width: 10px;--ate-scrollbar-thumb: var(--ate-border);--ate-scrollbar-thumb-hover: var(--ate-text-muted);--ate-scrollbar-track: transparent;--ate-table-border-color: var(--ate-border);--ate-table-header-background: var(--ate-surface-secondary);--ate-table-header-color: var(--ate-text);--ate-table-cell-background: var(--ate-surface);--ate-table-cell-selected-background: var(--ate-primary-light);--ate-table-resize-handle-color: var(--ate-primary);--ate-table-row-hover-background: var(--ate-primary-lighter)}:host(.dark),:host([data-theme=\"dark\"]){--ate-primary: #3b82f6;--ate-primary-contrast: #ffffff;--ate-primary-light: color-mix(in srgb, var(--ate-primary), transparent 85%);--ate-primary-lighter: color-mix(in srgb, var(--ate-primary), transparent 92%);--ate-primary-light-alpha: color-mix(in srgb, var(--ate-primary), transparent 80%);--ate-surface: #020617;--ate-surface-secondary: #0f172a;--ate-surface-tertiary: #1e293b;--ate-text: #f8fafc;--ate-text-secondary: #94a3b8;--ate-text-muted: #64748b;--ate-border: #1e293b;--ate-highlight-bg: #854d0e;--ate-highlight-color: #fef08a;--ate-button-hover: #1e293b;--ate-button-active: #0f172a;--ate-menu-bg: rgba(15, 23, 42, .95);--ate-menu-border: rgba(255, 255, 255, .1);--ate-menu-shadow: 0 20px 25px -5px rgba(0, 0, 0, .3), 0 10px 10px -5px rgba(0, 0, 0, .2);--ate-menu-blur: 16px;--ate-error-color: #f87171;--ate-error-bg: #450a0a;--ate-error-border: #7f1d1d;--ate-drag-background: var(--ate-surface-tertiary);--ate-drag-border-color: var(--ate-primary);--ate-blockquote-border-color: var(--ate-primary);--ate-toolbar-button-active-background: var(--ate-primary-light);--ate-toolbar-button-active-color: var(--ate-primary);--ate-button-hover: var(--ate-surface-tertiary);--ate-button-active: var(--ate-surface-secondary);--ate-scrollbar-thumb: var(--ate-surface-tertiary);--ate-scrollbar-thumb-hover: var(--ate-text-muted)}:host(.fill-container){display:block;height:100%}.tiptap-editor{border:var(--ate-border-width) solid var(--ate-border-color);border-radius:var(--ate-border-radius);background:var(--ate-background);overflow:hidden;transition:border-color .2s ease;position:relative}.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:var(--ate-focus-color)}.tiptap-content{padding:var(--ate-content-padding);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;scrollbar-width:thin;scrollbar-color:var(--ate-scrollbar-thumb) var(--ate-scrollbar-track)}.tiptap-content::-webkit-scrollbar{width:var(--ate-scrollbar-width);height:var(--ate-scrollbar-width)}.tiptap-content::-webkit-scrollbar-track{background:var(--ate-scrollbar-track)}.tiptap-content::-webkit-scrollbar-thumb{background:var(--ate-scrollbar-thumb);border:3px solid transparent;background-clip:content-box;border-radius:10px}.tiptap-content::-webkit-scrollbar-thumb:hover{background:var(--ate-scrollbar-thumb-hover);background-clip:content-box}.tiptap-content.drag-over{background:var(--ate-drag-background);border:2px dashed var(--ate-drag-border-color)}.character-count{padding:8px var(--ate-content-padding);font-size:12px;color:var(--ate-counter-color);text-align:right;border-top:1px solid var(--ate-counter-border-color);background:var(--ate-counter-background);transition:color .2s ease;border-bottom-left-radius:calc(var(--ate-border-radius) - var(--ate-border-width));border-bottom-right-radius:calc(var(--ate-border-radius) - var(--ate-border-width))}.character-count.limit-reached{color:var(--ate-error-color, #ef4444);font-weight:600}:host ::ng-deep .ProseMirror{outline:none;line-height:var(--ate-line-height);color:var(--ate-text-color);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 var(--ate-blockquote-border-color);margin:1em 0;background:var(--ate-blockquote-background);padding:.5em 1em;border-radius:0 4px 4px 0}:host ::ng-deep .ProseMirror code{background:var(--ate-code-background);color:var(--ate-code-color);border:1px solid var(--ate-code-border-color);padding:.2em .4em;border-radius:3px;font-family:Monaco,Consolas,monospace;font-size:.9em}:host ::ng-deep .ProseMirror pre{background:var(--ate-code-block-background);color:var(--ate-code-block-color);border:1px solid var(--ate-code-block-border-color);padding:1em;border-radius:6px;overflow-x:auto;margin:1em 0}:host ::ng-deep .ProseMirror pre code{background:none;color:inherit;border:none;padding:0}:host ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:var(--ate-placeholder-color);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:var(--ate-image-border-radius)}:host ::ng-deep .ProseMirror img:hover{border-color:var(--ate-border-color);box-shadow:0 2px 4px #0000001a}:host ::ng-deep .ProseMirror img.ProseMirror-selectednode{border-color:var(--ate-image-selected-color);box-shadow:0 0 0 3px var(--ate-primary-light-alpha);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 var(--ate-primary);outline-offset:2px;border-radius:16px;box-shadow:0 0 0 4px var(--ate-primary-light-alpha)}: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:var(--ate-primary);border:2px solid var(--ate-surface);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:var(--ate-primary);box-shadow:0 3px 8px #0000004d}:host ::ng-deep .resize-handle:active{background:var(--ate-primary)}: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 var(--ate-table-border-color);border-bottom:1px solid var(--ate-table-border-color);box-sizing:border-box;min-width:1em;padding:8px 12px;position:relative;vertical-align:top;text-align:left}:host ::ng-deep .ProseMirror table td{background:var(--ate-table-cell-background)}:host ::ng-deep .ProseMirror table td:first-child,:host ::ng-deep .ProseMirror table th:first-child{border-left:1px solid var(--ate-table-border-color)}:host ::ng-deep .ProseMirror table tr:first-child td,:host ::ng-deep .ProseMirror table tr:first-child th{border-top:1px solid var(--ate-table-border-color)}: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:var(--ate-table-header-background);font-weight:600;color:var(--ate-table-header-color)}:host ::ng-deep .ProseMirror table .selectedCell:after{background:var(--ate-table-cell-selected-background);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:var(--ate-table-resize-handle-color);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:var(--ate-focus-color)}: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 tbody tr:hover td{background-color:var(--ate-table-row-hover-background)}\n"], dependencies: [{ kind: "component", type: TiptapToolbarComponent, selector: "tiptap-toolbar", inputs: ["editor", "config", "imageUpload"] }, { kind: "component", type: TiptapBubbleMenuComponent, selector: "tiptap-bubble-menu", inputs: ["config"] }, { kind: "component", type: TiptapImageBubbleMenuComponent, selector: "tiptap-image-bubble-menu", inputs: ["config"] }, { kind: "component", type: TiptapTableBubbleMenuComponent, selector: "tiptap-table-bubble-menu", inputs: ["config"] }, { kind: "component", type: TiptapCellBubbleMenuComponent, selector: "tiptap-cell-bubble-menu", inputs: ["config"] }, { kind: "component", type: TiptapSlashCommandsComponent, selector: "tiptap-slash-commands", inputs: ["editor", "config"] }, { kind: "component", type: TiptapLinkBubbleMenuComponent, selector: "tiptap-link-bubble-menu", inputs: ["editor"] }, { kind: "component", type: TiptapColorBubbleMenuComponent, selector: "tiptap-color-bubble-menu", inputs: ["editor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6192
|
+
`, isInline: true, styles: [":host{--ate-primary: #2563eb;--ate-primary-contrast: #ffffff;--ate-primary-light: color-mix(in srgb, var(--ate-primary), transparent 90%);--ate-primary-lighter: color-mix(in srgb, var(--ate-primary), transparent 95%);--ate-primary-light-alpha: color-mix(in srgb, var(--ate-primary), transparent 85%);--ate-surface: #ffffff;--ate-surface-secondary: #f8f9fa;--ate-surface-tertiary: #f1f5f9;--ate-text: #2d3748;--ate-text-secondary: #64748b;--ate-text-muted: #a0aec0;--ate-border: #e2e8f0;--ate-highlight-bg: #fef08a;--ate-highlight-color: #854d0e;--ate-button-hover: #f1f5f9;--ate-button-active: #e2e8f0;--ate-error-color: #c53030;--ate-error-bg: #fed7d7;--ate-error-border: #feb2b2;--ate-border-color: var(--ate-border);--ate-border-width: 2px;--ate-border-radius: 12px;--ate-focus-color: var(--ate-primary);--ate-background: var(--ate-surface);--ate-text-color: var(--ate-text);--ate-placeholder-color: var(--ate-text-muted);--ate-line-height: 1.6;--ate-content-padding: 16px;--ate-menu-bg: var(--ate-surface-secondary);--ate-menu-border: var(--ate-border);--ate-menu-border-radius: var(--ate-border-radius, 8px);--ate-menu-shadow: 0 10px 15px -3px rgba(0, 0, 0, .1), 0 4px 6px -2px rgba(0, 0, 0, .05);--ate-menu-padding: 6px;--ate-toolbar-padding: var(--ate-menu-padding);--ate-toolbar-background: var(--ate-surface-secondary);--ate-toolbar-border-color: var(--ate-border);--ate-toolbar-button-color: var(--ate-text-secondary);--ate-toolbar-button-hover-background: transparent;--ate-toolbar-button-active-background: var(--ate-primary-light);--ate-toolbar-button-active-color: var(--ate-primary);--ate-counter-color: var(--ate-text-secondary);--ate-counter-background: var(--ate-surface-secondary);--ate-counter-border-color: var(--ate-border);--ate-drag-background: #f0f8ff;--ate-drag-border-color: var(--ate-primary);--ate-blockquote-border-color: var(--ate-border);--ate-blockquote-background: var(--ate-surface-secondary);--ate-code-background: var(--ate-surface-secondary);--ate-code-color: var(--ate-text-secondary);--ate-code-border-color: var(--ate-border);--ate-code-block-background: #0f172a;--ate-code-block-color: #e2e8f0;--ate-code-block-border-color: var(--ate-border);--ate-image-border-radius: 8px;--ate-image-selected-color: var(--ate-primary);--ate-scrollbar-width: 10px;--ate-scrollbar-thumb: var(--ate-border);--ate-scrollbar-thumb-hover: var(--ate-text-muted);--ate-scrollbar-track: transparent;--ate-table-border-color: var(--ate-border);--ate-table-header-background: var(--ate-surface-secondary);--ate-table-header-color: var(--ate-text);--ate-table-cell-background: var(--ate-surface);--ate-table-cell-selected-background: var(--ate-primary-light);--ate-table-resize-handle-color: var(--ate-primary);--ate-table-row-hover-background: var(--ate-primary-lighter);--ate-button-border-radius: 8px}:host(.dark),:host([data-theme=\"dark\"]){--ate-primary: #3b82f6;--ate-primary-contrast: #ffffff;--ate-primary-light: color-mix(in srgb, var(--ate-primary), transparent 85%);--ate-primary-lighter: color-mix(in srgb, var(--ate-primary), transparent 92%);--ate-primary-light-alpha: color-mix(in srgb, var(--ate-primary), transparent 80%);--ate-surface: #020617;--ate-surface-secondary: #0f172a;--ate-surface-tertiary: #1e293b;--ate-text: #f8fafc;--ate-text-secondary: #94a3b8;--ate-text-muted: #64748b;--ate-border: #1e293b;--ate-highlight-bg: #854d0e;--ate-highlight-color: #fef08a;--ate-button-hover: #1e293b;--ate-button-active: #0f172a;--ate-menu-border: rgba(255, 255, 255, .1);--ate-menu-shadow: 0 20px 25px -5px rgba(0, 0, 0, .3), 0 10px 10px -5px rgba(0, 0, 0, .2);--ate-error-color: #f87171;--ate-error-bg: #450a0a;--ate-error-border: #7f1d1d;--ate-drag-background: var(--ate-surface-tertiary);--ate-drag-border-color: var(--ate-primary);--ate-blockquote-border-color: var(--ate-primary);--ate-toolbar-button-active-background: var(--ate-primary-light);--ate-toolbar-button-active-color: var(--ate-primary);--ate-button-hover: var(--ate-surface-tertiary);--ate-button-active: var(--ate-surface-secondary);--ate-scrollbar-thumb: var(--ate-surface-tertiary);--ate-scrollbar-thumb-hover: var(--ate-text-muted)}:host(.fill-container){display:block;height:100%}.tiptap-editor{border:var(--ate-border-width) solid var(--ate-border-color);border-radius:var(--ate-border-radius);background:var(--ate-background);overflow:hidden;transition:border-color .2s ease;position:relative}:host(.floating-toolbar) .tiptap-editor{overflow:visible}:host(.fill-container) .tiptap-editor{display:flex;flex-direction:column;height:100%}:host(.fill-container) .tiptap-content{flex:1;min-height:0;overflow-y:auto}.tiptap-editor:focus-within{border-color:var(--ate-focus-color)}.tiptap-content{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;scrollbar-width:thin;scrollbar-color:var(--ate-scrollbar-thumb) var(--ate-scrollbar-track)}:host(.is-disabled) .tiptap-content{cursor:not-allowed;opacity:.7;-webkit-user-select:none;user-select:none;pointer-events:none;background-color:var(--ate-surface-tertiary)}:host(.is-readonly) .tiptap-content{cursor:default;-webkit-user-select:text;user-select:text}:host(.is-readonly) .tiptap-content ::ng-deep .tiptap-link{cursor:pointer;pointer-events:auto}.tiptap-content::-webkit-scrollbar{width:var(--ate-scrollbar-width);height:var(--ate-scrollbar-width)}.tiptap-content::-webkit-scrollbar-track{background:var(--ate-scrollbar-track)}.tiptap-content::-webkit-scrollbar-thumb{background:var(--ate-scrollbar-thumb);border:3px solid transparent;background-clip:content-box;border-radius:10px}.tiptap-content::-webkit-scrollbar-thumb:hover{background:var(--ate-scrollbar-thumb-hover);background-clip:content-box}.tiptap-content.drag-over{background:var(--ate-drag-background);border:2px dashed var(--ate-drag-border-color)}.character-count{padding:8px var(--ate-content-padding);font-size:12px;color:var(--ate-counter-color);text-align:right;border-top:1px solid var(--ate-counter-border-color);background:var(--ate-counter-background);transition:color .2s ease;border-bottom-left-radius:calc(var(--ate-border-radius) - var(--ate-border-width));border-bottom-right-radius:calc(var(--ate-border-radius) - var(--ate-border-width))}.character-count.limit-reached{color:var(--ate-error-color, #ef4444);font-weight:600}:host ::ng-deep .ProseMirror{padding:var(--ate-content-padding);outline:none;line-height:var(--ate-line-height);color:var(--ate-text-color);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 var(--ate-blockquote-border-color);margin:1em 0;background:var(--ate-blockquote-background);padding:.5em 1em;border-radius:0 4px 4px 0}:host ::ng-deep .ProseMirror code{background:var(--ate-code-background);color:var(--ate-code-color);border:1px solid var(--ate-code-border-color);padding:.15em .4em;border-radius:4px;font-family:JetBrains Mono,Fira Code,Monaco,Consolas,monospace;font-size:.85em;font-weight:500}:host ::ng-deep .ProseMirror pre{background:var(--ate-code-block-background);color:var(--ate-code-block-color);border:1px solid var(--ate-code-block-border-color);padding:1em;border-radius:var(--ate-border-radius);overflow-x:auto;margin:1em 0}:host ::ng-deep .ProseMirror pre code{background:none;color:inherit;border:none;padding:0}:host ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:var(--ate-placeholder-color);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:var(--ate-image-border-radius)}:host ::ng-deep .ProseMirror img:hover{border-color:var(--ate-border-color);box-shadow:0 2px 4px #0000001a}:host ::ng-deep .ProseMirror img.ProseMirror-selectednode{border-color:var(--ate-image-selected-color);box-shadow:0 0 0 3px var(--ate-primary-light-alpha);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 var(--ate-primary);outline-offset:2px;border-radius:16px;box-shadow:0 0 0 4px var(--ate-primary-light-alpha)}: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:var(--ate-primary);border:2px solid var(--ate-surface);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:var(--ate-primary);box-shadow:0 3px 8px #0000004d}:host ::ng-deep .resize-handle:active{background:var(--ate-primary)}: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 var(--ate-table-border-color);border-bottom:1px solid var(--ate-table-border-color);box-sizing:border-box;min-width:1em;padding:8px 12px;position:relative;vertical-align:top;text-align:left}:host ::ng-deep .ProseMirror table td{background:var(--ate-table-cell-background)}:host ::ng-deep .ProseMirror table td:first-child,:host ::ng-deep .ProseMirror table th:first-child{border-left:1px solid var(--ate-table-border-color)}:host ::ng-deep .ProseMirror table tr:first-child td,:host ::ng-deep .ProseMirror table tr:first-child th{border-top:1px solid var(--ate-table-border-color)}: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:var(--ate-table-header-background);font-weight:600;color:var(--ate-table-header-color)}:host ::ng-deep .ProseMirror table .selectedCell:after{background:var(--ate-table-cell-selected-background);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:var(--ate-table-resize-handle-color);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:var(--ate-focus-color)}: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 tbody tr:hover td{background-color:var(--ate-table-row-hover-background)}\n"], dependencies: [{ kind: "component", type: TiptapToolbarComponent, selector: "tiptap-toolbar", inputs: ["editor", "config", "imageUpload", "floating"] }, { kind: "component", type: TiptapBubbleMenuComponent, selector: "tiptap-bubble-menu", inputs: ["config"] }, { kind: "component", type: TiptapImageBubbleMenuComponent, selector: "tiptap-image-bubble-menu", inputs: ["config"] }, { kind: "component", type: TiptapTableBubbleMenuComponent, selector: "tiptap-table-bubble-menu", inputs: ["config"] }, { kind: "component", type: TiptapCellBubbleMenuComponent, selector: "tiptap-cell-bubble-menu", inputs: ["config"] }, { kind: "component", type: TiptapSlashCommandsComponent, selector: "tiptap-slash-commands", inputs: ["editor", "config"] }, { kind: "component", type: TiptapLinkBubbleMenuComponent, selector: "tiptap-link-bubble-menu", inputs: ["editor"] }, { kind: "component", type: TiptapColorBubbleMenuComponent, selector: "tiptap-color-bubble-menu", inputs: ["editor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
6126
6193
|
}
|
|
6127
6194
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AngularTiptapEditorComponent, decorators: [{
|
|
6128
6195
|
type: Component,
|
|
6129
6196
|
args: [{ selector: "angular-tiptap-editor", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [NoopValueAccessorDirective], host: {
|
|
6130
6197
|
'[class.fill-container]': 'fillContainer()',
|
|
6198
|
+
'[class.floating-toolbar]': 'floatingToolbar()',
|
|
6199
|
+
'[class.is-readonly]': '!editable() && !mergedDisabled()',
|
|
6200
|
+
'[class.is-disabled]': 'mergedDisabled()',
|
|
6201
|
+
'[style.--ate-border-width]': "seamless() || mergedDisabled() ? '0' : null",
|
|
6202
|
+
'[style.--ate-background]': "seamless() ? 'transparent' : (mergedDisabled() ? 'var(--ate-surface-tertiary)' : null)",
|
|
6203
|
+
'[style.--ate-toolbar-border-color]': "seamless() ? 'transparent' : null",
|
|
6204
|
+
'[style.--ate-counter-background]': "seamless() ? 'transparent' : null",
|
|
6205
|
+
'[style.--ate-counter-border-color]': "seamless() ? 'transparent' : null",
|
|
6131
6206
|
}, imports: [
|
|
6132
6207
|
TiptapToolbarComponent,
|
|
6133
6208
|
TiptapBubbleMenuComponent,
|
|
@@ -6140,17 +6215,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6140
6215
|
], providers: [
|
|
6141
6216
|
EditorCommandsService,
|
|
6142
6217
|
ImageService,
|
|
6143
|
-
TiptapI18nService,
|
|
6144
6218
|
ColorPickerService,
|
|
6145
6219
|
LinkService,
|
|
6146
6220
|
], template: `
|
|
6147
|
-
<div class="tiptap-editor"
|
|
6221
|
+
<div class="tiptap-editor">
|
|
6148
6222
|
<!-- Toolbar -->
|
|
6149
|
-
@if (showToolbar() && editor()) {
|
|
6223
|
+
@if (editable() && !mergedDisabled() && showToolbar() && editor()) {
|
|
6150
6224
|
<tiptap-toolbar
|
|
6151
6225
|
[editor]="editor()!"
|
|
6152
6226
|
[config]="toolbarConfig()"
|
|
6153
6227
|
[imageUpload]="imageUploadConfig()"
|
|
6228
|
+
[floating]="floatingToolbar()"
|
|
6154
6229
|
(mouseenter)="hideBubbleMenus()"
|
|
6155
6230
|
(mouseleave)="showBubbleMenus()"
|
|
6156
6231
|
/>
|
|
@@ -6167,7 +6242,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6167
6242
|
></div>
|
|
6168
6243
|
|
|
6169
6244
|
<!-- Text Bubble Menu -->
|
|
6170
|
-
@if (showBubbleMenu() && editor()) {
|
|
6245
|
+
@if (editable() && showBubbleMenu() && editor()) {
|
|
6171
6246
|
<tiptap-bubble-menu
|
|
6172
6247
|
[editor]="editor()!"
|
|
6173
6248
|
[config]="bubbleMenuConfig()"
|
|
@@ -6176,7 +6251,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6176
6251
|
}
|
|
6177
6252
|
|
|
6178
6253
|
<!-- Image Bubble Menu -->
|
|
6179
|
-
@if (showImageBubbleMenu() && editor()) {
|
|
6254
|
+
@if (editable() && showImageBubbleMenu() && editor()) {
|
|
6180
6255
|
<tiptap-image-bubble-menu
|
|
6181
6256
|
[editor]="editor()!"
|
|
6182
6257
|
[config]="imageBubbleMenuConfig()"
|
|
@@ -6185,7 +6260,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6185
6260
|
}
|
|
6186
6261
|
|
|
6187
6262
|
<!-- Link Bubble Menu -->
|
|
6188
|
-
@if (editor()) {
|
|
6263
|
+
@if (editable() && editor()) {
|
|
6189
6264
|
<tiptap-link-bubble-menu
|
|
6190
6265
|
[editor]="editor()!"
|
|
6191
6266
|
[style.display]="editorFullyInitialized() ? 'block' : 'none'"
|
|
@@ -6193,7 +6268,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6193
6268
|
}
|
|
6194
6269
|
|
|
6195
6270
|
<!-- Color Bubble Menu -->
|
|
6196
|
-
@if (editor()) {
|
|
6271
|
+
@if (editable() && editor()) {
|
|
6197
6272
|
<tiptap-color-bubble-menu
|
|
6198
6273
|
[editor]="editor()!"
|
|
6199
6274
|
[style.display]="editorFullyInitialized() ? 'block' : 'none'"
|
|
@@ -6201,7 +6276,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6201
6276
|
}
|
|
6202
6277
|
|
|
6203
6278
|
<!-- Slash Commands -->
|
|
6204
|
-
@if (enableSlashCommands() && editor()) {
|
|
6279
|
+
@if (editable() && enableSlashCommands() && editor()) {
|
|
6205
6280
|
<tiptap-slash-commands
|
|
6206
6281
|
[editor]="editor()!"
|
|
6207
6282
|
[config]="slashCommandsConfigComputed()"
|
|
@@ -6210,7 +6285,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6210
6285
|
}
|
|
6211
6286
|
|
|
6212
6287
|
<!-- Table Menu -->
|
|
6213
|
-
@if (editor()) {
|
|
6288
|
+
@if (editable() && editor()) {
|
|
6214
6289
|
<tiptap-table-bubble-menu
|
|
6215
6290
|
[editor]="editor()!"
|
|
6216
6291
|
[config]="tableBubbleMenuConfig()"
|
|
@@ -6219,7 +6294,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6219
6294
|
}
|
|
6220
6295
|
|
|
6221
6296
|
<!-- Cell Menu -->
|
|
6222
|
-
@if (editor()) {
|
|
6297
|
+
@if (editable() && editor()) {
|
|
6223
6298
|
<tiptap-cell-bubble-menu
|
|
6224
6299
|
[editor]="editor()!"
|
|
6225
6300
|
[config]="cellBubbleMenuConfig()"
|
|
@@ -6228,11 +6303,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6228
6303
|
}
|
|
6229
6304
|
|
|
6230
6305
|
<!-- Counters -->
|
|
6231
|
-
@if (showCharacterCount() || showWordCount()) {
|
|
6306
|
+
@if (editable() && !mergedDisabled() && (showCharacterCount() || showWordCount())) {
|
|
6232
6307
|
<div class="character-count" [class.limit-reached]="maxCharacters() && characterCount() >= maxCharacters()!">
|
|
6233
6308
|
@if (showCharacterCount()) {
|
|
6234
6309
|
{{ characterCount() }}
|
|
6235
|
-
{{
|
|
6310
|
+
{{ currentTranslations().editor.character }}{{ characterCount() > 1 ? "s" : "" }}
|
|
6236
6311
|
@if (maxCharacters()) {
|
|
6237
6312
|
/ {{ maxCharacters() }}
|
|
6238
6313
|
}
|
|
@@ -6244,12 +6319,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6244
6319
|
|
|
6245
6320
|
@if (showWordCount()) {
|
|
6246
6321
|
{{ wordCount() }}
|
|
6247
|
-
{{
|
|
6322
|
+
{{ currentTranslations().editor.word }}{{ wordCount() > 1 ? "s" : "" }}
|
|
6248
6323
|
}
|
|
6249
6324
|
</div>
|
|
6250
6325
|
}
|
|
6251
6326
|
</div>
|
|
6252
|
-
`, styles: [":host{--ate-primary: #2563eb;--ate-primary-contrast: #ffffff;--ate-primary-light: color-mix(in srgb, var(--ate-primary), transparent 90%);--ate-primary-lighter: color-mix(in srgb, var(--ate-primary), transparent 95%);--ate-primary-light-alpha: color-mix(in srgb, var(--ate-primary), transparent 85%);--ate-surface: #ffffff;--ate-surface-secondary: #f8f9fa;--ate-surface-tertiary: #f1f5f9;--ate-text: #2d3748;--ate-text-secondary: #64748b;--ate-text-muted: #a0aec0;--ate-border: #e2e8f0;--ate-highlight-bg: #fef08a;--ate-highlight-color: #854d0e;--ate-button-hover: #f1f5f9;--ate-button-active: #e2e8f0;--ate-menu-bg: rgba(255, 255, 255, .98);--ate-menu-border: var(--ate-border);--ate-menu-shadow: 0 10px 15px -3px rgba(0, 0, 0, .1), 0 4px 6px -2px rgba(0, 0, 0, .05);--ate-menu-blur: 16px;--ate-error-color: #c53030;--ate-error-bg: #fed7d7;--ate-error-border: #feb2b2;--ate-border-color: var(--ate-border);--ate-border-width: 2px;--ate-border-radius: 8px;--ate-focus-color: var(--ate-primary);--ate-background: var(--ate-surface);--ate-text-color: var(--ate-text);--ate-placeholder-color: var(--ate-text-muted);--ate-line-height: 1.6;--ate-content-padding: 16px;--ate-toolbar-background: var(--ate-surface-secondary);--ate-toolbar-border-color: var(--ate-border);--ate-toolbar-button-color: var(--ate-text-secondary);--ate-toolbar-button-hover-background: transparent;--ate-toolbar-button-active-background: var(--ate-primary-light);--ate-toolbar-button-active-color: var(--ate-primary);--ate-counter-color: var(--ate-text-secondary);--ate-counter-background: var(--ate-surface-secondary);--ate-counter-border-color: var(--ate-border);--ate-drag-background: #f0f8ff;--ate-drag-border-color: var(--ate-primary);--ate-blockquote-border-color: var(--ate-border);--ate-blockquote-background: var(--ate-surface-secondary);--ate-code-background: var(--ate-surface-secondary);--ate-code-color: var(--ate-text);--ate-code-block-background: #181825;--ate-code-block-color: #e2e8f0;--ate-code-border-color: var(--ate-border);--ate-code-block-border-color: var(--ate-border);--ate-image-border-radius: 8px;--ate-image-selected-color: var(--ate-primary);--ate-scrollbar-width: 10px;--ate-scrollbar-thumb: var(--ate-border);--ate-scrollbar-thumb-hover: var(--ate-text-muted);--ate-scrollbar-track: transparent;--ate-table-border-color: var(--ate-border);--ate-table-header-background: var(--ate-surface-secondary);--ate-table-header-color: var(--ate-text);--ate-table-cell-background: var(--ate-surface);--ate-table-cell-selected-background: var(--ate-primary-light);--ate-table-resize-handle-color: var(--ate-primary);--ate-table-row-hover-background: var(--ate-primary-lighter)}:host(.dark),:host([data-theme=\"dark\"]){--ate-primary: #3b82f6;--ate-primary-contrast: #ffffff;--ate-primary-light: color-mix(in srgb, var(--ate-primary), transparent 85%);--ate-primary-lighter: color-mix(in srgb, var(--ate-primary), transparent 92%);--ate-primary-light-alpha: color-mix(in srgb, var(--ate-primary), transparent 80%);--ate-surface: #020617;--ate-surface-secondary: #0f172a;--ate-surface-tertiary: #1e293b;--ate-text: #f8fafc;--ate-text-secondary: #94a3b8;--ate-text-muted: #64748b;--ate-border: #1e293b;--ate-highlight-bg: #854d0e;--ate-highlight-color: #fef08a;--ate-button-hover: #1e293b;--ate-button-active: #0f172a;--ate-menu-bg: rgba(15, 23, 42, .95);--ate-menu-border: rgba(255, 255, 255, .1);--ate-menu-shadow: 0 20px 25px -5px rgba(0, 0, 0, .3), 0 10px 10px -5px rgba(0, 0, 0, .2);--ate-menu-blur: 16px;--ate-error-color: #f87171;--ate-error-bg: #450a0a;--ate-error-border: #7f1d1d;--ate-drag-background: var(--ate-surface-tertiary);--ate-drag-border-color: var(--ate-primary);--ate-blockquote-border-color: var(--ate-primary);--ate-toolbar-button-active-background: var(--ate-primary-light);--ate-toolbar-button-active-color: var(--ate-primary);--ate-button-hover: var(--ate-surface-tertiary);--ate-button-active: var(--ate-surface-secondary);--ate-scrollbar-thumb: var(--ate-surface-tertiary);--ate-scrollbar-thumb-hover: var(--ate-text-muted)}:host(.fill-container){display:block;height:100%}.tiptap-editor{border:var(--ate-border-width) solid var(--ate-border-color);border-radius:var(--ate-border-radius);background:var(--ate-background);overflow:hidden;transition:border-color .2s ease;position:relative}.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:var(--ate-focus-color)}.tiptap-content{padding:var(--ate-content-padding);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;scrollbar-width:thin;scrollbar-color:var(--ate-scrollbar-thumb) var(--ate-scrollbar-track)}.tiptap-content::-webkit-scrollbar{width:var(--ate-scrollbar-width);height:var(--ate-scrollbar-width)}.tiptap-content::-webkit-scrollbar-track{background:var(--ate-scrollbar-track)}.tiptap-content::-webkit-scrollbar-thumb{background:var(--ate-scrollbar-thumb);border:3px solid transparent;background-clip:content-box;border-radius:10px}.tiptap-content::-webkit-scrollbar-thumb:hover{background:var(--ate-scrollbar-thumb-hover);background-clip:content-box}.tiptap-content.drag-over{background:var(--ate-drag-background);border:2px dashed var(--ate-drag-border-color)}.character-count{padding:8px var(--ate-content-padding);font-size:12px;color:var(--ate-counter-color);text-align:right;border-top:1px solid var(--ate-counter-border-color);background:var(--ate-counter-background);transition:color .2s ease;border-bottom-left-radius:calc(var(--ate-border-radius) - var(--ate-border-width));border-bottom-right-radius:calc(var(--ate-border-radius) - var(--ate-border-width))}.character-count.limit-reached{color:var(--ate-error-color, #ef4444);font-weight:600}:host ::ng-deep .ProseMirror{outline:none;line-height:var(--ate-line-height);color:var(--ate-text-color);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 var(--ate-blockquote-border-color);margin:1em 0;background:var(--ate-blockquote-background);padding:.5em 1em;border-radius:0 4px 4px 0}:host ::ng-deep .ProseMirror code{background:var(--ate-code-background);color:var(--ate-code-color);border:1px solid var(--ate-code-border-color);padding:.2em .4em;border-radius:3px;font-family:Monaco,Consolas,monospace;font-size:.9em}:host ::ng-deep .ProseMirror pre{background:var(--ate-code-block-background);color:var(--ate-code-block-color);border:1px solid var(--ate-code-block-border-color);padding:1em;border-radius:6px;overflow-x:auto;margin:1em 0}:host ::ng-deep .ProseMirror pre code{background:none;color:inherit;border:none;padding:0}:host ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:var(--ate-placeholder-color);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:var(--ate-image-border-radius)}:host ::ng-deep .ProseMirror img:hover{border-color:var(--ate-border-color);box-shadow:0 2px 4px #0000001a}:host ::ng-deep .ProseMirror img.ProseMirror-selectednode{border-color:var(--ate-image-selected-color);box-shadow:0 0 0 3px var(--ate-primary-light-alpha);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 var(--ate-primary);outline-offset:2px;border-radius:16px;box-shadow:0 0 0 4px var(--ate-primary-light-alpha)}: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:var(--ate-primary);border:2px solid var(--ate-surface);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:var(--ate-primary);box-shadow:0 3px 8px #0000004d}:host ::ng-deep .resize-handle:active{background:var(--ate-primary)}: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 var(--ate-table-border-color);border-bottom:1px solid var(--ate-table-border-color);box-sizing:border-box;min-width:1em;padding:8px 12px;position:relative;vertical-align:top;text-align:left}:host ::ng-deep .ProseMirror table td{background:var(--ate-table-cell-background)}:host ::ng-deep .ProseMirror table td:first-child,:host ::ng-deep .ProseMirror table th:first-child{border-left:1px solid var(--ate-table-border-color)}:host ::ng-deep .ProseMirror table tr:first-child td,:host ::ng-deep .ProseMirror table tr:first-child th{border-top:1px solid var(--ate-table-border-color)}: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:var(--ate-table-header-background);font-weight:600;color:var(--ate-table-header-color)}:host ::ng-deep .ProseMirror table .selectedCell:after{background:var(--ate-table-cell-selected-background);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:var(--ate-table-resize-handle-color);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:var(--ate-focus-color)}: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 tbody tr:hover td{background-color:var(--ate-table-row-hover-background)}\n"] }]
|
|
6327
|
+
`, styles: [":host{--ate-primary: #2563eb;--ate-primary-contrast: #ffffff;--ate-primary-light: color-mix(in srgb, var(--ate-primary), transparent 90%);--ate-primary-lighter: color-mix(in srgb, var(--ate-primary), transparent 95%);--ate-primary-light-alpha: color-mix(in srgb, var(--ate-primary), transparent 85%);--ate-surface: #ffffff;--ate-surface-secondary: #f8f9fa;--ate-surface-tertiary: #f1f5f9;--ate-text: #2d3748;--ate-text-secondary: #64748b;--ate-text-muted: #a0aec0;--ate-border: #e2e8f0;--ate-highlight-bg: #fef08a;--ate-highlight-color: #854d0e;--ate-button-hover: #f1f5f9;--ate-button-active: #e2e8f0;--ate-error-color: #c53030;--ate-error-bg: #fed7d7;--ate-error-border: #feb2b2;--ate-border-color: var(--ate-border);--ate-border-width: 2px;--ate-border-radius: 12px;--ate-focus-color: var(--ate-primary);--ate-background: var(--ate-surface);--ate-text-color: var(--ate-text);--ate-placeholder-color: var(--ate-text-muted);--ate-line-height: 1.6;--ate-content-padding: 16px;--ate-menu-bg: var(--ate-surface-secondary);--ate-menu-border: var(--ate-border);--ate-menu-border-radius: var(--ate-border-radius, 8px);--ate-menu-shadow: 0 10px 15px -3px rgba(0, 0, 0, .1), 0 4px 6px -2px rgba(0, 0, 0, .05);--ate-menu-padding: 6px;--ate-toolbar-padding: var(--ate-menu-padding);--ate-toolbar-background: var(--ate-surface-secondary);--ate-toolbar-border-color: var(--ate-border);--ate-toolbar-button-color: var(--ate-text-secondary);--ate-toolbar-button-hover-background: transparent;--ate-toolbar-button-active-background: var(--ate-primary-light);--ate-toolbar-button-active-color: var(--ate-primary);--ate-counter-color: var(--ate-text-secondary);--ate-counter-background: var(--ate-surface-secondary);--ate-counter-border-color: var(--ate-border);--ate-drag-background: #f0f8ff;--ate-drag-border-color: var(--ate-primary);--ate-blockquote-border-color: var(--ate-border);--ate-blockquote-background: var(--ate-surface-secondary);--ate-code-background: var(--ate-surface-secondary);--ate-code-color: var(--ate-text-secondary);--ate-code-border-color: var(--ate-border);--ate-code-block-background: #0f172a;--ate-code-block-color: #e2e8f0;--ate-code-block-border-color: var(--ate-border);--ate-image-border-radius: 8px;--ate-image-selected-color: var(--ate-primary);--ate-scrollbar-width: 10px;--ate-scrollbar-thumb: var(--ate-border);--ate-scrollbar-thumb-hover: var(--ate-text-muted);--ate-scrollbar-track: transparent;--ate-table-border-color: var(--ate-border);--ate-table-header-background: var(--ate-surface-secondary);--ate-table-header-color: var(--ate-text);--ate-table-cell-background: var(--ate-surface);--ate-table-cell-selected-background: var(--ate-primary-light);--ate-table-resize-handle-color: var(--ate-primary);--ate-table-row-hover-background: var(--ate-primary-lighter);--ate-button-border-radius: 8px}:host(.dark),:host([data-theme=\"dark\"]){--ate-primary: #3b82f6;--ate-primary-contrast: #ffffff;--ate-primary-light: color-mix(in srgb, var(--ate-primary), transparent 85%);--ate-primary-lighter: color-mix(in srgb, var(--ate-primary), transparent 92%);--ate-primary-light-alpha: color-mix(in srgb, var(--ate-primary), transparent 80%);--ate-surface: #020617;--ate-surface-secondary: #0f172a;--ate-surface-tertiary: #1e293b;--ate-text: #f8fafc;--ate-text-secondary: #94a3b8;--ate-text-muted: #64748b;--ate-border: #1e293b;--ate-highlight-bg: #854d0e;--ate-highlight-color: #fef08a;--ate-button-hover: #1e293b;--ate-button-active: #0f172a;--ate-menu-border: rgba(255, 255, 255, .1);--ate-menu-shadow: 0 20px 25px -5px rgba(0, 0, 0, .3), 0 10px 10px -5px rgba(0, 0, 0, .2);--ate-error-color: #f87171;--ate-error-bg: #450a0a;--ate-error-border: #7f1d1d;--ate-drag-background: var(--ate-surface-tertiary);--ate-drag-border-color: var(--ate-primary);--ate-blockquote-border-color: var(--ate-primary);--ate-toolbar-button-active-background: var(--ate-primary-light);--ate-toolbar-button-active-color: var(--ate-primary);--ate-button-hover: var(--ate-surface-tertiary);--ate-button-active: var(--ate-surface-secondary);--ate-scrollbar-thumb: var(--ate-surface-tertiary);--ate-scrollbar-thumb-hover: var(--ate-text-muted)}:host(.fill-container){display:block;height:100%}.tiptap-editor{border:var(--ate-border-width) solid var(--ate-border-color);border-radius:var(--ate-border-radius);background:var(--ate-background);overflow:hidden;transition:border-color .2s ease;position:relative}:host(.floating-toolbar) .tiptap-editor{overflow:visible}:host(.fill-container) .tiptap-editor{display:flex;flex-direction:column;height:100%}:host(.fill-container) .tiptap-content{flex:1;min-height:0;overflow-y:auto}.tiptap-editor:focus-within{border-color:var(--ate-focus-color)}.tiptap-content{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;scrollbar-width:thin;scrollbar-color:var(--ate-scrollbar-thumb) var(--ate-scrollbar-track)}:host(.is-disabled) .tiptap-content{cursor:not-allowed;opacity:.7;-webkit-user-select:none;user-select:none;pointer-events:none;background-color:var(--ate-surface-tertiary)}:host(.is-readonly) .tiptap-content{cursor:default;-webkit-user-select:text;user-select:text}:host(.is-readonly) .tiptap-content ::ng-deep .tiptap-link{cursor:pointer;pointer-events:auto}.tiptap-content::-webkit-scrollbar{width:var(--ate-scrollbar-width);height:var(--ate-scrollbar-width)}.tiptap-content::-webkit-scrollbar-track{background:var(--ate-scrollbar-track)}.tiptap-content::-webkit-scrollbar-thumb{background:var(--ate-scrollbar-thumb);border:3px solid transparent;background-clip:content-box;border-radius:10px}.tiptap-content::-webkit-scrollbar-thumb:hover{background:var(--ate-scrollbar-thumb-hover);background-clip:content-box}.tiptap-content.drag-over{background:var(--ate-drag-background);border:2px dashed var(--ate-drag-border-color)}.character-count{padding:8px var(--ate-content-padding);font-size:12px;color:var(--ate-counter-color);text-align:right;border-top:1px solid var(--ate-counter-border-color);background:var(--ate-counter-background);transition:color .2s ease;border-bottom-left-radius:calc(var(--ate-border-radius) - var(--ate-border-width));border-bottom-right-radius:calc(var(--ate-border-radius) - var(--ate-border-width))}.character-count.limit-reached{color:var(--ate-error-color, #ef4444);font-weight:600}:host ::ng-deep .ProseMirror{padding:var(--ate-content-padding);outline:none;line-height:var(--ate-line-height);color:var(--ate-text-color);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 var(--ate-blockquote-border-color);margin:1em 0;background:var(--ate-blockquote-background);padding:.5em 1em;border-radius:0 4px 4px 0}:host ::ng-deep .ProseMirror code{background:var(--ate-code-background);color:var(--ate-code-color);border:1px solid var(--ate-code-border-color);padding:.15em .4em;border-radius:4px;font-family:JetBrains Mono,Fira Code,Monaco,Consolas,monospace;font-size:.85em;font-weight:500}:host ::ng-deep .ProseMirror pre{background:var(--ate-code-block-background);color:var(--ate-code-block-color);border:1px solid var(--ate-code-block-border-color);padding:1em;border-radius:var(--ate-border-radius);overflow-x:auto;margin:1em 0}:host ::ng-deep .ProseMirror pre code{background:none;color:inherit;border:none;padding:0}:host ::ng-deep .ProseMirror p.is-editor-empty:first-child:before{content:attr(data-placeholder);color:var(--ate-placeholder-color);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:var(--ate-image-border-radius)}:host ::ng-deep .ProseMirror img:hover{border-color:var(--ate-border-color);box-shadow:0 2px 4px #0000001a}:host ::ng-deep .ProseMirror img.ProseMirror-selectednode{border-color:var(--ate-image-selected-color);box-shadow:0 0 0 3px var(--ate-primary-light-alpha);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 var(--ate-primary);outline-offset:2px;border-radius:16px;box-shadow:0 0 0 4px var(--ate-primary-light-alpha)}: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:var(--ate-primary);border:2px solid var(--ate-surface);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:var(--ate-primary);box-shadow:0 3px 8px #0000004d}:host ::ng-deep .resize-handle:active{background:var(--ate-primary)}: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 var(--ate-table-border-color);border-bottom:1px solid var(--ate-table-border-color);box-sizing:border-box;min-width:1em;padding:8px 12px;position:relative;vertical-align:top;text-align:left}:host ::ng-deep .ProseMirror table td{background:var(--ate-table-cell-background)}:host ::ng-deep .ProseMirror table td:first-child,:host ::ng-deep .ProseMirror table th:first-child{border-left:1px solid var(--ate-table-border-color)}:host ::ng-deep .ProseMirror table tr:first-child td,:host ::ng-deep .ProseMirror table tr:first-child th{border-top:1px solid var(--ate-table-border-color)}: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:var(--ate-table-header-background);font-weight:600;color:var(--ate-table-header-color)}:host ::ng-deep .ProseMirror table .selectedCell:after{background:var(--ate-table-cell-selected-background);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:var(--ate-table-resize-handle-color);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:var(--ate-focus-color)}: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 tbody tr:hover td{background-color:var(--ate-table-row-hover-background)}\n"] }]
|
|
6253
6328
|
}], ctorParameters: () => [] });
|
|
6254
6329
|
|
|
6255
6330
|
/*
|