@flogeez/angular-tiptap-editor 0.6.0 → 2.0.1
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 +35 -0
- package/README.md +93 -31
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +283 -207
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/index.d.ts +25 -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-sub-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-sub-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-sub-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-sub-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:var(--ate-menu-padding);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:var(--ate-menu-padding);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-sub-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:var(--ate-menu-padding);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:var(--ate-menu-padding);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-sub-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,11 +5604,13 @@ 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);
|
|
5549
5611
|
this.fillContainer = input(false);
|
|
5550
5612
|
this.showToolbar = input(true);
|
|
5613
|
+
this.showFooter = input(true);
|
|
5551
5614
|
this.showCharacterCount = input(true);
|
|
5552
5615
|
this.showWordCount = input(true);
|
|
5553
5616
|
this.maxCharacters = input(undefined);
|
|
@@ -5557,6 +5620,8 @@ class AngularTiptapEditorComponent {
|
|
|
5557
5620
|
this.customSlashCommands = input(undefined);
|
|
5558
5621
|
this.locale = input(undefined);
|
|
5559
5622
|
this.autofocus = input(false);
|
|
5623
|
+
this.seamless = input(false);
|
|
5624
|
+
this.floatingToolbar = input(false);
|
|
5560
5625
|
this.tiptapExtensions = input([]);
|
|
5561
5626
|
this.tiptapOptions = input({});
|
|
5562
5627
|
// Nouveaux inputs pour les bubble menus
|
|
@@ -5564,8 +5629,13 @@ class AngularTiptapEditorComponent {
|
|
|
5564
5629
|
this.bubbleMenu = input(DEFAULT_BUBBLE_MENU_CONFIG);
|
|
5565
5630
|
this.showImageBubbleMenu = input(true);
|
|
5566
5631
|
this.imageBubbleMenu = input(DEFAULT_IMAGE_BUBBLE_MENU_CONFIG);
|
|
5567
|
-
//
|
|
5632
|
+
// Configuration de la toolbar
|
|
5568
5633
|
this.toolbar = input({});
|
|
5634
|
+
// Configuration des menus de table
|
|
5635
|
+
this.showTableBubbleMenu = input(true);
|
|
5636
|
+
this.tableBubbleMenu = input(DEFAULT_TABLE_MENU_CONFIG);
|
|
5637
|
+
this.showCellBubbleMenu = input(true);
|
|
5638
|
+
this.cellBubbleMenu = input(DEFAULT_CELL_MENU_CONFIG);
|
|
5569
5639
|
/**
|
|
5570
5640
|
* Additionnal state calculators to extend the reactive editor state.
|
|
5571
5641
|
*/
|
|
@@ -5598,9 +5668,9 @@ class AngularTiptapEditorComponent {
|
|
|
5598
5668
|
this.editorUpdate = output();
|
|
5599
5669
|
this.editorFocus = output();
|
|
5600
5670
|
this.editorBlur = output();
|
|
5601
|
-
// ViewChild
|
|
5671
|
+
// ViewChild with signal
|
|
5602
5672
|
this.editorElement = viewChild.required("editorElement");
|
|
5603
|
-
//
|
|
5673
|
+
// Private signals for internal state
|
|
5604
5674
|
this._editor = signal(null);
|
|
5605
5675
|
this._characterCount = signal(0);
|
|
5606
5676
|
this._wordCount = signal(0);
|
|
@@ -5608,44 +5678,39 @@ class AngularTiptapEditorComponent {
|
|
|
5608
5678
|
this._editorFullyInitialized = signal(false);
|
|
5609
5679
|
// Anti-echo: track last emitted HTML to prevent cursor reset on parent echo
|
|
5610
5680
|
this.lastEmittedHtml = null;
|
|
5611
|
-
//
|
|
5681
|
+
// Read-only access to signals
|
|
5612
5682
|
this.editor = this._editor.asReadonly();
|
|
5613
5683
|
this.characterCount = this._characterCount.asReadonly();
|
|
5614
5684
|
this.wordCount = this._wordCount.asReadonly();
|
|
5615
5685
|
this.isDragOver = this._isDragOver.asReadonly();
|
|
5616
5686
|
this.editorFullyInitialized = this._editorFullyInitialized.asReadonly();
|
|
5617
|
-
|
|
5687
|
+
this._isFormControlDisabled = signal(false);
|
|
5688
|
+
this.isFormControlDisabled = this._isFormControlDisabled.asReadonly();
|
|
5689
|
+
// Combined disabled state (Input + FormControl)
|
|
5690
|
+
this.mergedDisabled = computed(() => this.disabled() || this.isFormControlDisabled());
|
|
5691
|
+
// Computed for editor states
|
|
5618
5692
|
this.isEditorReady = computed(() => this.editor() !== null);
|
|
5619
|
-
// Computed
|
|
5693
|
+
// Computed for toolbar configuration
|
|
5620
5694
|
this.toolbarConfig = computed(() => Object.keys(this.toolbar()).length === 0
|
|
5621
5695
|
? DEFAULT_TOOLBAR_CONFIG
|
|
5622
5696
|
: this.toolbar());
|
|
5623
|
-
// Computed
|
|
5697
|
+
// Computed for bubble menu configuration
|
|
5624
5698
|
this.bubbleMenuConfig = computed(() => Object.keys(this.bubbleMenu()).length === 0
|
|
5625
5699
|
? DEFAULT_BUBBLE_MENU_CONFIG
|
|
5626
5700
|
: { ...DEFAULT_BUBBLE_MENU_CONFIG, ...this.bubbleMenu() });
|
|
5627
|
-
// Computed
|
|
5701
|
+
// Computed for image bubble menu configuration
|
|
5628
5702
|
this.imageBubbleMenuConfig = computed(() => Object.keys(this.imageBubbleMenu()).length === 0
|
|
5629
5703
|
? DEFAULT_IMAGE_BUBBLE_MENU_CONFIG
|
|
5630
5704
|
: { ...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
|
|
5705
|
+
// Computed for table bubble menu configuration
|
|
5706
|
+
this.tableBubbleMenuConfig = computed(() => Object.keys(this.tableBubbleMenu()).length === 0
|
|
5707
|
+
? DEFAULT_TABLE_MENU_CONFIG
|
|
5708
|
+
: { ...DEFAULT_TABLE_MENU_CONFIG, ...this.tableBubbleMenu() });
|
|
5709
|
+
// Computed for cell bubble menu configuration
|
|
5710
|
+
this.cellBubbleMenuConfig = computed(() => Object.keys(this.cellBubbleMenu()).length === 0
|
|
5711
|
+
? DEFAULT_CELL_MENU_CONFIG
|
|
5712
|
+
: { ...DEFAULT_CELL_MENU_CONFIG, ...this.cellBubbleMenu() });
|
|
5713
|
+
// Computed for image upload configuration
|
|
5649
5714
|
this.imageUploadConfig = computed(() => ({
|
|
5650
5715
|
maxSize: 5,
|
|
5651
5716
|
maxWidth: 1920,
|
|
@@ -5658,7 +5723,7 @@ class AngularTiptapEditorComponent {
|
|
|
5658
5723
|
quality: 0.8,
|
|
5659
5724
|
...this.imageUpload(),
|
|
5660
5725
|
}));
|
|
5661
|
-
// Computed
|
|
5726
|
+
// Computed for slash commands configuration
|
|
5662
5727
|
this.slashCommandsConfigComputed = computed(() => {
|
|
5663
5728
|
const customConfig = this.customSlashCommands();
|
|
5664
5729
|
if (customConfig) {
|
|
@@ -5670,22 +5735,27 @@ class AngularTiptapEditorComponent {
|
|
|
5670
5735
|
commands: filterSlashCommands(this.slashCommands(), this.i18nService, this.editorCommandsService, this.imageUploadConfig()),
|
|
5671
5736
|
};
|
|
5672
5737
|
});
|
|
5738
|
+
// Computed for current translations (allows per-instance override via [locale] input)
|
|
5739
|
+
this.currentTranslations = computed(() => {
|
|
5740
|
+
const localeOverride = this.locale();
|
|
5741
|
+
if (localeOverride) {
|
|
5742
|
+
// If a specific language is provided to this instance, try to retrieve it
|
|
5743
|
+
const allTranslations = this.i18nService.allTranslations();
|
|
5744
|
+
return allTranslations[localeOverride] || this.i18nService.translations();
|
|
5745
|
+
}
|
|
5746
|
+
// Otherwise, follow the global service language
|
|
5747
|
+
return this.i18nService.translations();
|
|
5748
|
+
});
|
|
5673
5749
|
this._destroyRef = inject(DestroyRef);
|
|
5674
|
-
// NgControl
|
|
5750
|
+
// NgControl for management of FormControls
|
|
5675
5751
|
this.ngControl = inject(NgControl, { self: true, optional: true });
|
|
5676
5752
|
this.i18nService = inject(TiptapI18nService);
|
|
5677
5753
|
this.editorCommandsService = inject(EditorCommandsService);
|
|
5754
|
+
// Access editor state via service
|
|
5678
5755
|
this.editorState = this.editorCommandsService.editorState;
|
|
5679
|
-
//
|
|
5756
|
+
// Effect to update editor content (with anti-echo)
|
|
5680
5757
|
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
|
|
5758
|
+
const content = this.content(); // Sole reactive dependency
|
|
5689
5759
|
untracked(() => {
|
|
5690
5760
|
const editor = this.editor();
|
|
5691
5761
|
const hasFormControl = !!this.ngControl?.control;
|
|
@@ -5697,19 +5767,19 @@ class AngularTiptapEditorComponent {
|
|
|
5697
5767
|
// Double sécurité : on vérifie le contenu actuel de l'éditeur
|
|
5698
5768
|
if (content === editor.getHTML())
|
|
5699
5769
|
return;
|
|
5700
|
-
//
|
|
5770
|
+
// Do not overwrite content if we have a FormControl and content is empty
|
|
5701
5771
|
if (hasFormControl && !content)
|
|
5702
5772
|
return;
|
|
5703
5773
|
editor.commands.setContent(content, false);
|
|
5704
5774
|
});
|
|
5705
5775
|
});
|
|
5706
|
-
//
|
|
5776
|
+
// Effect to update height properties
|
|
5707
5777
|
effect(() => {
|
|
5708
5778
|
const minHeight = this.minHeight();
|
|
5709
5779
|
const height = this.height();
|
|
5710
5780
|
const maxHeight = this.maxHeight();
|
|
5711
5781
|
const element = this.editorElement()?.nativeElement;
|
|
5712
|
-
//
|
|
5782
|
+
// Automatically calculate if scroll is needed
|
|
5713
5783
|
const needsScroll = height !== undefined || maxHeight !== undefined;
|
|
5714
5784
|
if (element) {
|
|
5715
5785
|
element.style.setProperty("--editor-min-height", `${minHeight}px`);
|
|
@@ -5721,7 +5791,10 @@ class AngularTiptapEditorComponent {
|
|
|
5721
5791
|
// Effect to monitor editability changes
|
|
5722
5792
|
effect(() => {
|
|
5723
5793
|
const currentEditor = this.editor();
|
|
5724
|
-
|
|
5794
|
+
// An editor is "editable" if it's not disabled and editable mode is ON
|
|
5795
|
+
const isEditable = this.editable() && !this.mergedDisabled();
|
|
5796
|
+
// An editor is "readonly" if it's explicitly non-editable and not disabled
|
|
5797
|
+
const isReadOnly = !this.editable() && !this.mergedDisabled();
|
|
5725
5798
|
if (currentEditor) {
|
|
5726
5799
|
this.editorCommandsService.setEditable(currentEditor, isEditable);
|
|
5727
5800
|
}
|
|
@@ -5731,13 +5804,6 @@ class AngularTiptapEditorComponent {
|
|
|
5731
5804
|
const handler = this.imageUploadHandler();
|
|
5732
5805
|
this.editorCommandsService.uploadHandler = handler || null;
|
|
5733
5806
|
});
|
|
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
5807
|
// Effect to update character count limit dynamically
|
|
5742
5808
|
effect(() => {
|
|
5743
5809
|
const editor = this.editor();
|
|
@@ -5789,6 +5855,7 @@ class AngularTiptapEditorComponent {
|
|
|
5789
5855
|
class: "tiptap-link",
|
|
5790
5856
|
},
|
|
5791
5857
|
}),
|
|
5858
|
+
LinkClickBehavior,
|
|
5792
5859
|
Highlight.configure({
|
|
5793
5860
|
multicolor: true,
|
|
5794
5861
|
HTMLAttributes: {
|
|
@@ -5853,7 +5920,7 @@ class AngularTiptapEditorComponent {
|
|
|
5853
5920
|
element: this.editorElement().nativeElement,
|
|
5854
5921
|
extensions,
|
|
5855
5922
|
content: this.content(),
|
|
5856
|
-
editable: this.editable(),
|
|
5923
|
+
editable: this.editable() && !this.mergedDisabled(),
|
|
5857
5924
|
autofocus: this.autofocus(),
|
|
5858
5925
|
onUpdate: ({ editor, transaction }) => {
|
|
5859
5926
|
const html = editor.getHTML();
|
|
@@ -5973,6 +6040,7 @@ class AngularTiptapEditorComponent {
|
|
|
5973
6040
|
setupFormControlSubscription() {
|
|
5974
6041
|
const control = this.ngControl?.control;
|
|
5975
6042
|
if (control) {
|
|
6043
|
+
// Synchronize form control value with editor content
|
|
5976
6044
|
const formValue$ = concat(defer(() => of(control.value)), control.valueChanges);
|
|
5977
6045
|
formValue$
|
|
5978
6046
|
.pipe(tap((value) => {
|
|
@@ -5982,25 +6050,25 @@ class AngularTiptapEditorComponent {
|
|
|
5982
6050
|
}
|
|
5983
6051
|
}), takeUntilDestroyed(this._destroyRef))
|
|
5984
6052
|
.subscribe();
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
6053
|
+
// Synchronize form control status with editor disabled state
|
|
6054
|
+
const formStatus$ = concat(defer(() => of(control.status)), control.statusChanges);
|
|
6055
|
+
formStatus$
|
|
6056
|
+
.pipe(tap((status) => {
|
|
6057
|
+
this._isFormControlDisabled.set(status === 'DISABLED');
|
|
6058
|
+
}), takeUntilDestroyed(this._destroyRef))
|
|
6059
|
+
.subscribe();
|
|
5992
6060
|
}
|
|
5993
6061
|
}
|
|
5994
6062
|
onEditorClick(event) {
|
|
5995
6063
|
const editor = this.editor();
|
|
5996
|
-
if (!editor)
|
|
6064
|
+
if (!editor || !this.editable())
|
|
5997
6065
|
return;
|
|
5998
|
-
//
|
|
6066
|
+
// Verify if click is on the container element and not on the content
|
|
5999
6067
|
const target = event.target;
|
|
6000
6068
|
const editorElement = this.editorElement()?.nativeElement;
|
|
6001
6069
|
if (target === editorElement ||
|
|
6002
6070
|
target.classList.contains("tiptap-content")) {
|
|
6003
|
-
//
|
|
6071
|
+
// Click in the empty space, position the cursor at the end
|
|
6004
6072
|
setTimeout(() => {
|
|
6005
6073
|
const { doc } = editor.state;
|
|
6006
6074
|
const endPos = doc.content.size;
|
|
@@ -6010,20 +6078,20 @@ class AngularTiptapEditorComponent {
|
|
|
6010
6078
|
}
|
|
6011
6079
|
}
|
|
6012
6080
|
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: [
|
|
6081
|
+
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 }, showFooter: { classPropertyName: "showFooter", publicName: "showFooter", 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
6082
|
EditorCommandsService,
|
|
6015
6083
|
ImageService,
|
|
6016
|
-
TiptapI18nService,
|
|
6017
6084
|
ColorPickerService,
|
|
6018
6085
|
LinkService,
|
|
6019
6086
|
], viewQueries: [{ propertyName: "editorElement", first: true, predicate: ["editorElement"], descendants: true, isSignal: true }], hostDirectives: [{ directive: NoopValueAccessorDirective }], ngImport: i0, template: `
|
|
6020
|
-
<div class="tiptap-editor"
|
|
6087
|
+
<div class="tiptap-editor">
|
|
6021
6088
|
<!-- Toolbar -->
|
|
6022
|
-
@if (showToolbar() && editor()) {
|
|
6089
|
+
@if (editable() && !mergedDisabled() && showToolbar() && editor()) {
|
|
6023
6090
|
<tiptap-toolbar
|
|
6024
6091
|
[editor]="editor()!"
|
|
6025
6092
|
[config]="toolbarConfig()"
|
|
6026
6093
|
[imageUpload]="imageUploadConfig()"
|
|
6094
|
+
[floating]="floatingToolbar()"
|
|
6027
6095
|
(mouseenter)="hideBubbleMenus()"
|
|
6028
6096
|
(mouseleave)="showBubbleMenus()"
|
|
6029
6097
|
/>
|
|
@@ -6040,7 +6108,7 @@ class AngularTiptapEditorComponent {
|
|
|
6040
6108
|
></div>
|
|
6041
6109
|
|
|
6042
6110
|
<!-- Text Bubble Menu -->
|
|
6043
|
-
@if (showBubbleMenu() && editor()) {
|
|
6111
|
+
@if (editable() && showBubbleMenu() && editor()) {
|
|
6044
6112
|
<tiptap-bubble-menu
|
|
6045
6113
|
[editor]="editor()!"
|
|
6046
6114
|
[config]="bubbleMenuConfig()"
|
|
@@ -6049,7 +6117,7 @@ class AngularTiptapEditorComponent {
|
|
|
6049
6117
|
}
|
|
6050
6118
|
|
|
6051
6119
|
<!-- Image Bubble Menu -->
|
|
6052
|
-
@if (showImageBubbleMenu() && editor()) {
|
|
6120
|
+
@if (editable() && showImageBubbleMenu() && editor()) {
|
|
6053
6121
|
<tiptap-image-bubble-menu
|
|
6054
6122
|
[editor]="editor()!"
|
|
6055
6123
|
[config]="imageBubbleMenuConfig()"
|
|
@@ -6058,7 +6126,7 @@ class AngularTiptapEditorComponent {
|
|
|
6058
6126
|
}
|
|
6059
6127
|
|
|
6060
6128
|
<!-- Link Bubble Menu -->
|
|
6061
|
-
@if (editor()) {
|
|
6129
|
+
@if (editable() && editor()) {
|
|
6062
6130
|
<tiptap-link-bubble-menu
|
|
6063
6131
|
[editor]="editor()!"
|
|
6064
6132
|
[style.display]="editorFullyInitialized() ? 'block' : 'none'"
|
|
@@ -6066,7 +6134,7 @@ class AngularTiptapEditorComponent {
|
|
|
6066
6134
|
}
|
|
6067
6135
|
|
|
6068
6136
|
<!-- Color Bubble Menu -->
|
|
6069
|
-
@if (editor()) {
|
|
6137
|
+
@if (editable() && editor()) {
|
|
6070
6138
|
<tiptap-color-bubble-menu
|
|
6071
6139
|
[editor]="editor()!"
|
|
6072
6140
|
[style.display]="editorFullyInitialized() ? 'block' : 'none'"
|
|
@@ -6074,7 +6142,7 @@ class AngularTiptapEditorComponent {
|
|
|
6074
6142
|
}
|
|
6075
6143
|
|
|
6076
6144
|
<!-- Slash Commands -->
|
|
6077
|
-
@if (enableSlashCommands() && editor()) {
|
|
6145
|
+
@if (editable() && enableSlashCommands() && editor()) {
|
|
6078
6146
|
<tiptap-slash-commands
|
|
6079
6147
|
[editor]="editor()!"
|
|
6080
6148
|
[config]="slashCommandsConfigComputed()"
|
|
@@ -6083,7 +6151,7 @@ class AngularTiptapEditorComponent {
|
|
|
6083
6151
|
}
|
|
6084
6152
|
|
|
6085
6153
|
<!-- Table Menu -->
|
|
6086
|
-
@if (editor()) {
|
|
6154
|
+
@if (editable() && editor()) {
|
|
6087
6155
|
<tiptap-table-bubble-menu
|
|
6088
6156
|
[editor]="editor()!"
|
|
6089
6157
|
[config]="tableBubbleMenuConfig()"
|
|
@@ -6092,7 +6160,7 @@ class AngularTiptapEditorComponent {
|
|
|
6092
6160
|
}
|
|
6093
6161
|
|
|
6094
6162
|
<!-- Cell Menu -->
|
|
6095
|
-
@if (editor()) {
|
|
6163
|
+
@if (editable() && editor()) {
|
|
6096
6164
|
<tiptap-cell-bubble-menu
|
|
6097
6165
|
[editor]="editor()!"
|
|
6098
6166
|
[config]="cellBubbleMenuConfig()"
|
|
@@ -6101,11 +6169,11 @@ class AngularTiptapEditorComponent {
|
|
|
6101
6169
|
}
|
|
6102
6170
|
|
|
6103
6171
|
<!-- Counters -->
|
|
6104
|
-
@if (showCharacterCount() || showWordCount()) {
|
|
6172
|
+
@if (editable() && !mergedDisabled() && showFooter() && (showCharacterCount() || showWordCount())) {
|
|
6105
6173
|
<div class="character-count" [class.limit-reached]="maxCharacters() && characterCount() >= maxCharacters()!">
|
|
6106
6174
|
@if (showCharacterCount()) {
|
|
6107
6175
|
{{ characterCount() }}
|
|
6108
|
-
{{
|
|
6176
|
+
{{ currentTranslations().editor.character }}{{ characterCount() > 1 ? "s" : "" }}
|
|
6109
6177
|
@if (maxCharacters()) {
|
|
6110
6178
|
/ {{ maxCharacters() }}
|
|
6111
6179
|
}
|
|
@@ -6117,17 +6185,25 @@ class AngularTiptapEditorComponent {
|
|
|
6117
6185
|
|
|
6118
6186
|
@if (showWordCount()) {
|
|
6119
6187
|
{{ wordCount() }}
|
|
6120
|
-
{{
|
|
6188
|
+
{{ currentTranslations().editor.word }}{{ wordCount() > 1 ? "s" : "" }}
|
|
6121
6189
|
}
|
|
6122
6190
|
</div>
|
|
6123
6191
|
}
|
|
6124
6192
|
</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 }); }
|
|
6193
|
+
`, 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-sub-border-radius: 8px;--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-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: var(--ate-sub-border-radius);--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-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
6194
|
}
|
|
6127
6195
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImport: i0, type: AngularTiptapEditorComponent, decorators: [{
|
|
6128
6196
|
type: Component,
|
|
6129
6197
|
args: [{ selector: "angular-tiptap-editor", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [NoopValueAccessorDirective], host: {
|
|
6130
6198
|
'[class.fill-container]': 'fillContainer()',
|
|
6199
|
+
'[class.floating-toolbar]': 'floatingToolbar()',
|
|
6200
|
+
'[class.is-readonly]': '!editable() && !mergedDisabled()',
|
|
6201
|
+
'[class.is-disabled]': 'mergedDisabled()',
|
|
6202
|
+
'[style.--ate-border-width]': "seamless() || mergedDisabled() ? '0' : null",
|
|
6203
|
+
'[style.--ate-background]': "seamless() ? 'transparent' : (mergedDisabled() ? 'var(--ate-surface-tertiary)' : null)",
|
|
6204
|
+
'[style.--ate-toolbar-border-color]': "seamless() ? 'transparent' : null",
|
|
6205
|
+
'[style.--ate-counter-background]': "seamless() ? 'transparent' : null",
|
|
6206
|
+
'[style.--ate-counter-border-color]': "seamless() ? 'transparent' : null",
|
|
6131
6207
|
}, imports: [
|
|
6132
6208
|
TiptapToolbarComponent,
|
|
6133
6209
|
TiptapBubbleMenuComponent,
|
|
@@ -6140,17 +6216,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6140
6216
|
], providers: [
|
|
6141
6217
|
EditorCommandsService,
|
|
6142
6218
|
ImageService,
|
|
6143
|
-
TiptapI18nService,
|
|
6144
6219
|
ColorPickerService,
|
|
6145
6220
|
LinkService,
|
|
6146
6221
|
], template: `
|
|
6147
|
-
<div class="tiptap-editor"
|
|
6222
|
+
<div class="tiptap-editor">
|
|
6148
6223
|
<!-- Toolbar -->
|
|
6149
|
-
@if (showToolbar() && editor()) {
|
|
6224
|
+
@if (editable() && !mergedDisabled() && showToolbar() && editor()) {
|
|
6150
6225
|
<tiptap-toolbar
|
|
6151
6226
|
[editor]="editor()!"
|
|
6152
6227
|
[config]="toolbarConfig()"
|
|
6153
6228
|
[imageUpload]="imageUploadConfig()"
|
|
6229
|
+
[floating]="floatingToolbar()"
|
|
6154
6230
|
(mouseenter)="hideBubbleMenus()"
|
|
6155
6231
|
(mouseleave)="showBubbleMenus()"
|
|
6156
6232
|
/>
|
|
@@ -6167,7 +6243,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6167
6243
|
></div>
|
|
6168
6244
|
|
|
6169
6245
|
<!-- Text Bubble Menu -->
|
|
6170
|
-
@if (showBubbleMenu() && editor()) {
|
|
6246
|
+
@if (editable() && showBubbleMenu() && editor()) {
|
|
6171
6247
|
<tiptap-bubble-menu
|
|
6172
6248
|
[editor]="editor()!"
|
|
6173
6249
|
[config]="bubbleMenuConfig()"
|
|
@@ -6176,7 +6252,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6176
6252
|
}
|
|
6177
6253
|
|
|
6178
6254
|
<!-- Image Bubble Menu -->
|
|
6179
|
-
@if (showImageBubbleMenu() && editor()) {
|
|
6255
|
+
@if (editable() && showImageBubbleMenu() && editor()) {
|
|
6180
6256
|
<tiptap-image-bubble-menu
|
|
6181
6257
|
[editor]="editor()!"
|
|
6182
6258
|
[config]="imageBubbleMenuConfig()"
|
|
@@ -6185,7 +6261,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6185
6261
|
}
|
|
6186
6262
|
|
|
6187
6263
|
<!-- Link Bubble Menu -->
|
|
6188
|
-
@if (editor()) {
|
|
6264
|
+
@if (editable() && editor()) {
|
|
6189
6265
|
<tiptap-link-bubble-menu
|
|
6190
6266
|
[editor]="editor()!"
|
|
6191
6267
|
[style.display]="editorFullyInitialized() ? 'block' : 'none'"
|
|
@@ -6193,7 +6269,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6193
6269
|
}
|
|
6194
6270
|
|
|
6195
6271
|
<!-- Color Bubble Menu -->
|
|
6196
|
-
@if (editor()) {
|
|
6272
|
+
@if (editable() && editor()) {
|
|
6197
6273
|
<tiptap-color-bubble-menu
|
|
6198
6274
|
[editor]="editor()!"
|
|
6199
6275
|
[style.display]="editorFullyInitialized() ? 'block' : 'none'"
|
|
@@ -6201,7 +6277,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6201
6277
|
}
|
|
6202
6278
|
|
|
6203
6279
|
<!-- Slash Commands -->
|
|
6204
|
-
@if (enableSlashCommands() && editor()) {
|
|
6280
|
+
@if (editable() && enableSlashCommands() && editor()) {
|
|
6205
6281
|
<tiptap-slash-commands
|
|
6206
6282
|
[editor]="editor()!"
|
|
6207
6283
|
[config]="slashCommandsConfigComputed()"
|
|
@@ -6210,7 +6286,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6210
6286
|
}
|
|
6211
6287
|
|
|
6212
6288
|
<!-- Table Menu -->
|
|
6213
|
-
@if (editor()) {
|
|
6289
|
+
@if (editable() && editor()) {
|
|
6214
6290
|
<tiptap-table-bubble-menu
|
|
6215
6291
|
[editor]="editor()!"
|
|
6216
6292
|
[config]="tableBubbleMenuConfig()"
|
|
@@ -6219,7 +6295,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6219
6295
|
}
|
|
6220
6296
|
|
|
6221
6297
|
<!-- Cell Menu -->
|
|
6222
|
-
@if (editor()) {
|
|
6298
|
+
@if (editable() && editor()) {
|
|
6223
6299
|
<tiptap-cell-bubble-menu
|
|
6224
6300
|
[editor]="editor()!"
|
|
6225
6301
|
[config]="cellBubbleMenuConfig()"
|
|
@@ -6228,11 +6304,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6228
6304
|
}
|
|
6229
6305
|
|
|
6230
6306
|
<!-- Counters -->
|
|
6231
|
-
@if (showCharacterCount() || showWordCount()) {
|
|
6307
|
+
@if (editable() && !mergedDisabled() && showFooter() && (showCharacterCount() || showWordCount())) {
|
|
6232
6308
|
<div class="character-count" [class.limit-reached]="maxCharacters() && characterCount() >= maxCharacters()!">
|
|
6233
6309
|
@if (showCharacterCount()) {
|
|
6234
6310
|
{{ characterCount() }}
|
|
6235
|
-
{{
|
|
6311
|
+
{{ currentTranslations().editor.character }}{{ characterCount() > 1 ? "s" : "" }}
|
|
6236
6312
|
@if (maxCharacters()) {
|
|
6237
6313
|
/ {{ maxCharacters() }}
|
|
6238
6314
|
}
|
|
@@ -6244,12 +6320,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.0", ngImpor
|
|
|
6244
6320
|
|
|
6245
6321
|
@if (showWordCount()) {
|
|
6246
6322
|
{{ wordCount() }}
|
|
6247
|
-
{{
|
|
6323
|
+
{{ currentTranslations().editor.word }}{{ wordCount() > 1 ? "s" : "" }}
|
|
6248
6324
|
}
|
|
6249
6325
|
</div>
|
|
6250
6326
|
}
|
|
6251
6327
|
</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"] }]
|
|
6328
|
+
`, 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-sub-border-radius: 8px;--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-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: var(--ate-sub-border-radius);--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-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
6329
|
}], ctorParameters: () => [] });
|
|
6254
6330
|
|
|
6255
6331
|
/*
|