@flogeez/angular-tiptap-editor 3.0.0 → 3.0.2

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.
@@ -4,11 +4,9 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
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, CharacterCount } from '@tiptap/extensions';
7
- import { Underline } from '@tiptap/extension-underline';
8
7
  import { Superscript } from '@tiptap/extension-superscript';
9
8
  import { Subscript } from '@tiptap/extension-subscript';
10
9
  import { TextAlign } from '@tiptap/extension-text-align';
11
- import { Link } from '@tiptap/extension-link';
12
10
  import { Highlight } from '@tiptap/extension-highlight';
13
11
  import { TextStyle } from '@tiptap/extension-text-style';
14
12
  import { Color } from '@tiptap/extension-color';
@@ -121,6 +119,13 @@ const AteResizableImage = Node$1.create({
121
119
  },
122
120
  addNodeView() {
123
121
  return ({ node, getPos, editor }) => {
122
+ const wrapper = document.createElement("div");
123
+ wrapper.className = "resizable-image-wrapper";
124
+ wrapper.style.display = "block";
125
+ if (node.attrs["textAlign"]) {
126
+ wrapper.style.textAlign = node.attrs["textAlign"];
127
+ wrapper.setAttribute("data-align", node.attrs["textAlign"]);
128
+ }
124
129
  const container = document.createElement("div");
125
130
  container.className = "resizable-image-container";
126
131
  container.style.position = "relative";
@@ -130,20 +135,32 @@ const AteResizableImage = Node$1.create({
130
135
  img.alt = node.attrs["alt"] || "";
131
136
  img.title = node.attrs["title"] || "";
132
137
  img.className = "ate-image";
138
+ img.style.display = "inline-block"; // Ensure it respects container text-align
133
139
  if (node.attrs["width"]) {
134
140
  img.width = node.attrs["width"];
135
141
  }
136
142
  if (node.attrs["height"]) {
137
143
  img.height = node.attrs["height"];
138
144
  }
139
- img.parentNode?.insertBefore(container, img);
145
+ wrapper.appendChild(container);
140
146
  container.appendChild(img);
147
+ // Allow selection in read-only mode to show bubble menu/download
148
+ img.addEventListener("click", e => {
149
+ if (!editor.isEditable) {
150
+ e.preventDefault();
151
+ e.stopPropagation();
152
+ const pos = getPos();
153
+ if (typeof pos === "number") {
154
+ editor.commands.setNodeSelection(pos);
155
+ editor.view.focus();
156
+ }
157
+ }
158
+ });
141
159
  // Add modern resize controls
142
160
  const resizeControls = document.createElement("div");
143
161
  resizeControls.className = "resize-controls";
144
- resizeControls.style.display = "none";
145
- // Create 8 handles for full resizing capability
146
- const handles = ["nw", "n", "ne", "w", "e", "sw", "s", "se"];
162
+ // Create 2 handles (sides only) for a minimalist UI
163
+ const handles = ["w", "e"];
147
164
  handles.forEach(direction => {
148
165
  const handle = document.createElement("div");
149
166
  handle.className = `resize-handle resize-handle-${direction}`;
@@ -155,7 +172,6 @@ const AteResizableImage = Node$1.create({
155
172
  // Variables for resizing
156
173
  let isResizing = false;
157
174
  let startX = 0;
158
- let startY = 0;
159
175
  let startWidth = 0;
160
176
  let startHeight = 0;
161
177
  let aspectRatio = 1;
@@ -169,7 +185,6 @@ const AteResizableImage = Node$1.create({
169
185
  e.stopPropagation();
170
186
  isResizing = true;
171
187
  startX = e.clientX;
172
- startY = e.clientY;
173
188
  // Use current image dimensions instead of initial ones
174
189
  startWidth =
175
190
  parseInt(img.getAttribute("width") || "0") || node.attrs["width"] || img.naturalWidth;
@@ -182,7 +197,6 @@ const AteResizableImage = Node$1.create({
182
197
  return;
183
198
  }
184
199
  const deltaX = e.clientX - startX;
185
- const deltaY = e.clientY - startY;
186
200
  let newWidth = startWidth;
187
201
  let newHeight = startHeight;
188
202
  // Resize according to direction
@@ -195,30 +209,6 @@ const AteResizableImage = Node$1.create({
195
209
  newWidth = startWidth - deltaX;
196
210
  newHeight = newWidth / aspectRatio;
197
211
  break;
198
- case "s":
199
- newHeight = startHeight + deltaY;
200
- newWidth = newHeight * aspectRatio;
201
- break;
202
- case "n":
203
- newHeight = startHeight - deltaY;
204
- newWidth = newHeight * aspectRatio;
205
- break;
206
- case "se":
207
- newWidth = startWidth + deltaX;
208
- newHeight = startHeight + deltaY;
209
- break;
210
- case "sw":
211
- newWidth = startWidth - deltaX;
212
- newHeight = startHeight + deltaY;
213
- break;
214
- case "ne":
215
- newWidth = startWidth + deltaX;
216
- newHeight = startHeight - deltaY;
217
- break;
218
- case "nw":
219
- newWidth = startWidth - deltaX;
220
- newHeight = startHeight - deltaY;
221
- break;
222
212
  }
223
213
  // Limits
224
214
  newWidth = Math.max(50, Math.min(2000, newWidth));
@@ -259,17 +249,17 @@ const AteResizableImage = Node$1.create({
259
249
  });
260
250
  // Proper selection management via ProseMirror lifecycle
261
251
  const selectNode = () => {
262
- resizeControls.style.display = "block";
252
+ wrapper.classList.add("selected");
263
253
  container.classList.add("selected");
264
254
  img.classList.add("selected");
265
255
  };
266
256
  const deselectNode = () => {
267
- resizeControls.style.display = "none";
257
+ wrapper.classList.remove("selected");
268
258
  container.classList.remove("selected");
269
259
  img.classList.remove("selected");
270
260
  };
271
261
  return {
272
- dom: container,
262
+ dom: wrapper,
273
263
  selectNode,
274
264
  deselectNode,
275
265
  update: updatedNode => {
@@ -285,8 +275,21 @@ const AteResizableImage = Node$1.create({
285
275
  if (updatedNode.attrs["height"]) {
286
276
  img.height = updatedNode.attrs["height"];
287
277
  }
278
+ if (updatedNode.attrs["textAlign"]) {
279
+ wrapper.style.textAlign = updatedNode.attrs["textAlign"];
280
+ wrapper.setAttribute("data-align", updatedNode.attrs["textAlign"]);
281
+ }
282
+ else {
283
+ wrapper.style.textAlign = "";
284
+ wrapper.removeAttribute("data-align");
285
+ }
288
286
  return true;
289
287
  },
288
+ stopEvent: (event) => {
289
+ const target = event.target;
290
+ return !!target.closest(".resize-controls");
291
+ },
292
+ ignoreMutation: () => true,
290
293
  };
291
294
  };
292
295
  },
@@ -769,33 +772,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
769
772
  }], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: true }] }], active: [{ type: i0.Input, args: [{ isSignal: true, alias: "active", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], backgroundColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "backgroundColor", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], iconSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconSize", required: false }] }], buttonClick: [{ type: i0.Output, args: ["buttonClick"] }] } });
770
773
 
771
774
  class AteSeparatorComponent {
772
- constructor() {
773
- this.orientation = input("vertical", ...(ngDevMode ? [{ debugName: "orientation" }] : []));
774
- this.size = input("medium", ...(ngDevMode ? [{ debugName: "size" }] : []));
775
- }
776
775
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteSeparatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
777
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.16", type: AteSeparatorComponent, isStandalone: true, selector: "ate-separator", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
778
- <div
779
- class="ate-separator"
780
- [class.vertical]="orientation() === 'vertical'"
781
- [class.horizontal]="orientation() === 'horizontal'"
782
- [class.small]="size() === 'small'"
783
- [class.medium]="size() === 'medium'"
784
- [class.large]="size() === 'large'"></div>
785
- `, isInline: true, styles: [".ate-separator{background-color:var(--ate-border, #e2e8f0);margin:0}.ate-separator.vertical{width:1px;height:24px;margin:0 8px}.ate-separator.horizontal{height:1px;width:100%;margin:8px 0}.ate-separator.small.vertical{height:16px;margin:0 4px}.ate-separator.small.horizontal{margin:4px 0}.ate-separator.medium.vertical{height:24px;margin:0 8px}.ate-separator.medium.horizontal{margin:8px 0}.ate-separator.large.vertical{height:32px;margin:0 12px}.ate-separator.large.horizontal{margin:12px 0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
776
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: AteSeparatorComponent, isStandalone: true, selector: "ate-separator", ngImport: i0, template: `<div class="ate-separator"></div>`, isInline: true, styles: [".ate-separator{width:1px;height:24px;background-color:var(--ate-border, #e2e8f0);margin:0 var(--ate-menu-gap, 2px);flex-shrink:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
786
777
  }
787
778
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteSeparatorComponent, decorators: [{
788
779
  type: Component,
789
- args: [{ selector: "ate-separator", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
790
- <div
791
- class="ate-separator"
792
- [class.vertical]="orientation() === 'vertical'"
793
- [class.horizontal]="orientation() === 'horizontal'"
794
- [class.small]="size() === 'small'"
795
- [class.medium]="size() === 'medium'"
796
- [class.large]="size() === 'large'"></div>
797
- `, styles: [".ate-separator{background-color:var(--ate-border, #e2e8f0);margin:0}.ate-separator.vertical{width:1px;height:24px;margin:0 8px}.ate-separator.horizontal{height:1px;width:100%;margin:8px 0}.ate-separator.small.vertical{height:16px;margin:0 4px}.ate-separator.small.horizontal{margin:4px 0}.ate-separator.medium.vertical{height:24px;margin:0 8px}.ate-separator.medium.horizontal{margin:8px 0}.ate-separator.large.vertical{height:32px;margin:0 12px}.ate-separator.large.horizontal{margin:12px 0}\n"] }]
798
- }], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
780
+ args: [{ selector: "ate-separator", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `<div class="ate-separator"></div>`, styles: [".ate-separator{width:1px;height:24px;background-color:var(--ate-border, #e2e8f0);margin:0 var(--ate-menu-gap, 2px);flex-shrink:0}\n"] }]
781
+ }] });
799
782
 
800
783
  const ENGLISH_TRANSLATIONS = {
801
784
  toolbar: {
@@ -927,11 +910,15 @@ const ENGLISH_TRANSLATIONS = {
927
910
  invalidFileType: "Invalid file type",
928
911
  dragDropText: "Drag and drop images here",
929
912
  changeImage: "Change Image",
913
+ downloadImage: "Download Image",
930
914
  deleteImage: "Delete Image",
931
915
  resizeSmall: "Small",
932
916
  resizeMedium: "Medium",
933
917
  resizeLarge: "Large",
934
918
  resizeOriginal: "Original",
919
+ alignLeft: "Align Left",
920
+ alignCenter: "Align Center",
921
+ alignRight: "Align Right",
935
922
  resizing: "Resizing...",
936
923
  compressing: "Compressing...",
937
924
  compressionError: "Error during compression",
@@ -1094,11 +1081,15 @@ const FRENCH_TRANSLATIONS = {
1094
1081
  invalidFileType: "Type de fichier invalide",
1095
1082
  dragDropText: "Glissez et déposez des images ici",
1096
1083
  changeImage: "Changer l'image",
1084
+ downloadImage: "Télécharger l'image",
1097
1085
  deleteImage: "Supprimer l'image",
1098
1086
  resizeSmall: "Petit",
1099
1087
  resizeMedium: "Moyen",
1100
1088
  resizeLarge: "Grand",
1101
1089
  resizeOriginal: "Original",
1090
+ alignLeft: "Aligner à gauche",
1091
+ alignCenter: "Aligner au centre",
1092
+ alignRight: "Aligner à droite",
1102
1093
  resizing: "Redimensionnement...",
1103
1094
  compressing: "Compression...",
1104
1095
  compressionError: "Erreur lors de la compression",
@@ -1330,6 +1321,46 @@ class AteImageService {
1330
1321
  this.clearSelection();
1331
1322
  }
1332
1323
  }
1324
+ /** Download the current image */
1325
+ downloadImage(editor) {
1326
+ const attrs = editor.getAttributes("resizableImage");
1327
+ if (!attrs || !attrs["src"]) {
1328
+ return;
1329
+ }
1330
+ const src = attrs["src"];
1331
+ const fileName = attrs["alt"] || "image";
1332
+ // Detect if it's base64 or remote URL
1333
+ if (src.startsWith("data:") ||
1334
+ src.startsWith("blob:") ||
1335
+ src.startsWith(window.location.origin)) {
1336
+ const link = document.createElement("a");
1337
+ link.href = src;
1338
+ link.download = fileName;
1339
+ document.body.appendChild(link);
1340
+ link.click();
1341
+ document.body.removeChild(link);
1342
+ }
1343
+ else {
1344
+ // For remote URLs, we try to fetch it to bypass cross-origin restrictions on 'download' attribute
1345
+ fetch(src)
1346
+ .then(response => response.blob())
1347
+ .then(blob => {
1348
+ const url = window.URL.createObjectURL(blob);
1349
+ const link = document.createElement("a");
1350
+ link.href = url;
1351
+ link.download = fileName;
1352
+ document.body.appendChild(link);
1353
+ link.click();
1354
+ document.body.removeChild(link);
1355
+ window.URL.revokeObjectURL(url);
1356
+ })
1357
+ .catch(err => {
1358
+ console.error("Error downloading image:", err);
1359
+ // Fallback to opening in new tab
1360
+ window.open(src, "_blank");
1361
+ });
1362
+ }
1363
+ }
1333
1364
  updateSelectedImage(attributes) {
1334
1365
  const current = this.selectedImage();
1335
1366
  if (current) {
@@ -2406,6 +2437,9 @@ class AteEditorCommandsService {
2406
2437
  throw error;
2407
2438
  }
2408
2439
  }
2440
+ downloadImage(editor) {
2441
+ this.imageService.downloadImage(editor);
2442
+ }
2409
2443
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteEditorCommandsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2410
2444
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteEditorCommandsService }); }
2411
2445
  }
@@ -2796,7 +2830,7 @@ class AteToolbarComponent {
2796
2830
  }
2797
2831
  }
2798
2832
  </div>
2799
- `, 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}.ate-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, 12px) - var(--ate-border-width, 2px));border-top-right-radius:calc(var(--ate-menu-border-radius, 12px) - var(--ate-border-width, 2px))}.ate-toolbar.floating{pointer-events:auto;border-radius:var(--ate-menu-border-radius, 12px);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)}.ate-toolbar.floating::-webkit-scrollbar{display:none}:host-context(.floating-toolbar:focus-within) .ate-toolbar.floating,:host-context(.floating-toolbar:hover) .ate-toolbar.floating{transform:translateY(-2rem)}@media (max-width: 768px){.ate-toolbar{padding:6px 8px;gap:2px}}@keyframes toolbarSlideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.ate-toolbar{animation:toolbarSlideIn .3s cubic-bezier(.4,0,.2,1)}\n"], dependencies: [{ kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "component", type: AteSeparatorComponent, selector: "ate-separator", inputs: ["orientation", "size"] }, { kind: "component", type: AteColorPickerComponent, selector: "ate-color-picker", inputs: ["editor", "mode", "disabled", "anchorToText"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2833
+ `, 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}.ate-toolbar{display:flex;align-items:center;gap:var(--ate-toolbar-gap);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, 12px) - var(--ate-border-width, 2px));border-top-right-radius:calc(var(--ate-menu-border-radius, 12px) - var(--ate-border-width, 2px))}.ate-toolbar.floating{pointer-events:auto;border-radius:var(--ate-menu-border-radius, 12px);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)}.ate-toolbar.floating::-webkit-scrollbar{display:none}:host-context(.floating-toolbar:focus-within) .ate-toolbar.floating,:host-context(.floating-toolbar:hover) .ate-toolbar.floating{transform:translateY(-2rem)}@keyframes toolbarSlideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.ate-toolbar{animation:toolbarSlideIn .3s cubic-bezier(.4,0,.2,1)}\n"], dependencies: [{ kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "component", type: AteSeparatorComponent, selector: "ate-separator" }, { kind: "component", type: AteColorPickerComponent, selector: "ate-color-picker", inputs: ["editor", "mode", "disabled", "anchorToText"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2800
2834
  }
2801
2835
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteToolbarComponent, decorators: [{
2802
2836
  type: Component,
@@ -3049,9 +3083,141 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3049
3083
  }
3050
3084
  }
3051
3085
  </div>
3052
- `, 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}.ate-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, 12px) - var(--ate-border-width, 2px));border-top-right-radius:calc(var(--ate-menu-border-radius, 12px) - var(--ate-border-width, 2px))}.ate-toolbar.floating{pointer-events:auto;border-radius:var(--ate-menu-border-radius, 12px);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)}.ate-toolbar.floating::-webkit-scrollbar{display:none}:host-context(.floating-toolbar:focus-within) .ate-toolbar.floating,:host-context(.floating-toolbar:hover) .ate-toolbar.floating{transform:translateY(-2rem)}@media (max-width: 768px){.ate-toolbar{padding:6px 8px;gap:2px}}@keyframes toolbarSlideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.ate-toolbar{animation:toolbarSlideIn .3s cubic-bezier(.4,0,.2,1)}\n"] }]
3086
+ `, 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}.ate-toolbar{display:flex;align-items:center;gap:var(--ate-toolbar-gap);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, 12px) - var(--ate-border-width, 2px));border-top-right-radius:calc(var(--ate-menu-border-radius, 12px) - var(--ate-border-width, 2px))}.ate-toolbar.floating{pointer-events:auto;border-radius:var(--ate-menu-border-radius, 12px);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)}.ate-toolbar.floating::-webkit-scrollbar{display:none}:host-context(.floating-toolbar:focus-within) .ate-toolbar.floating,:host-context(.floating-toolbar:hover) .ate-toolbar.floating{transform:translateY(-2rem)}@keyframes toolbarSlideIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}.ate-toolbar{animation:toolbarSlideIn .3s cubic-bezier(.4,0,.2,1)}\n"] }]
3053
3087
  }], propDecorators: { editor: [{ type: i0.Input, args: [{ isSignal: true, alias: "editor", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: true }] }], imageUpload: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageUpload", required: false }] }], floating: [{ type: i0.Input, args: [{ isSignal: true, alias: "floating", required: false }] }] } });
3054
3088
 
3089
+ // Default toolbar configuration
3090
+ const ATE_DEFAULT_TOOLBAR_CONFIG = {
3091
+ bold: true,
3092
+ italic: true,
3093
+ underline: true,
3094
+ strike: true,
3095
+ code: true,
3096
+ codeBlock: true,
3097
+ superscript: false, // Disabled by default (opt-in)
3098
+ subscript: false, // Disabled by default (opt-in)
3099
+ highlight: false, // Disabled by default (opt-in)
3100
+ highlightPicker: true,
3101
+ heading1: true,
3102
+ heading2: true,
3103
+ heading3: true,
3104
+ bulletList: true,
3105
+ orderedList: true,
3106
+ blockquote: true,
3107
+ alignLeft: false, // Disabled by default (opt-in)
3108
+ alignCenter: false, // Disabled by default (opt-in)
3109
+ alignRight: false, // Disabled by default (opt-in)
3110
+ alignJustify: false, // Disabled by default (opt-in)
3111
+ link: true,
3112
+ image: true,
3113
+ horizontalRule: false, // Disabled by default (opt-in)
3114
+ table: true,
3115
+ undo: true,
3116
+ redo: true,
3117
+ clear: false, // Disabled by default (opt-in)
3118
+ textColor: true,
3119
+ separator: true,
3120
+ };
3121
+ // Default bubble menu configuration
3122
+ const ATE_DEFAULT_BUBBLE_MENU_CONFIG = {
3123
+ bold: true,
3124
+ italic: true,
3125
+ underline: true,
3126
+ strike: true,
3127
+ code: true,
3128
+ superscript: false,
3129
+ subscript: false,
3130
+ highlight: false,
3131
+ highlightPicker: true,
3132
+ textColor: true,
3133
+ link: true,
3134
+ separator: true,
3135
+ };
3136
+ // Default image bubble menu configuration
3137
+ const ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG = {
3138
+ changeImage: true,
3139
+ downloadImage: true,
3140
+ resizeSmall: true,
3141
+ resizeMedium: true,
3142
+ resizeLarge: true,
3143
+ resizeOriginal: true,
3144
+ alignLeft: true,
3145
+ alignCenter: true,
3146
+ alignRight: true,
3147
+ deleteImage: true,
3148
+ separator: true,
3149
+ };
3150
+ // Default table bubble menu configuration
3151
+ const ATE_DEFAULT_TABLE_MENU_CONFIG = {
3152
+ addRowBefore: true,
3153
+ addRowAfter: true,
3154
+ deleteRow: true,
3155
+ addColumnBefore: true,
3156
+ addColumnAfter: true,
3157
+ deleteColumn: true,
3158
+ toggleHeaderRow: true,
3159
+ toggleHeaderColumn: true,
3160
+ deleteTable: true,
3161
+ separator: true,
3162
+ };
3163
+ // Default cell bubble menu configuration
3164
+ const ATE_DEFAULT_CELL_MENU_CONFIG = {
3165
+ mergeCells: true,
3166
+ splitCell: true,
3167
+ };
3168
+ // Default image upload configuration
3169
+ const ATE_DEFAULT_IMAGE_UPLOAD_CONFIG = {
3170
+ maxSize: 5, // 5MB
3171
+ maxWidth: 1920,
3172
+ maxHeight: 1080,
3173
+ allowedTypes: ["image/jpeg", "image/png", "image/gif", "image/webp"],
3174
+ quality: 0.8,
3175
+ };
3176
+ /**
3177
+ * Ultimate default configuration for the Angular Tiptap Editor.
3178
+ * This serves as the 'Level 4' fallback in the configuration hierarchy:
3179
+ * 1. Component Inputs (Le Roi)
3180
+ * 2. Component [config] (Le Prince)
3181
+ * 3. Global provideAteEditor() (Le Duc)
3182
+ * 4. ATE_DEFAULT_CONFIG (Le Peuple)
3183
+ */
3184
+ const ATE_DEFAULT_CONFIG = {
3185
+ theme: "auto",
3186
+ mode: "classic",
3187
+ height: "auto",
3188
+ minHeight: "200px",
3189
+ maxHeight: "none",
3190
+ fillContainer: false,
3191
+ autofocus: false,
3192
+ editable: true,
3193
+ disabled: false,
3194
+ spellcheck: true,
3195
+ enableOfficePaste: true,
3196
+ showToolbar: true,
3197
+ showFooter: true,
3198
+ showCharacterCount: true,
3199
+ showWordCount: true,
3200
+ showEditToggle: false,
3201
+ showBubbleMenu: true,
3202
+ showImageBubbleMenu: true,
3203
+ downloadImage: true,
3204
+ showTableMenu: true,
3205
+ showCellMenu: true,
3206
+ enableSlashCommands: true,
3207
+ floatingToolbar: false,
3208
+ toolbar: ATE_DEFAULT_TOOLBAR_CONFIG,
3209
+ bubbleMenu: ATE_DEFAULT_BUBBLE_MENU_CONFIG,
3210
+ imageBubbleMenu: ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG,
3211
+ imageUpload: ATE_DEFAULT_IMAGE_UPLOAD_CONFIG,
3212
+ tableBubbleMenu: ATE_DEFAULT_TABLE_MENU_CONFIG,
3213
+ cellBubbleMenu: ATE_DEFAULT_CELL_MENU_CONFIG,
3214
+ slashCommands: {},
3215
+ tiptapExtensions: [],
3216
+ tiptapOptions: {},
3217
+ stateCalculators: [],
3218
+ angularNodes: [],
3219
+ };
3220
+
3055
3221
  /**
3056
3222
  * Base abstract class for all Bubble Menus (Text, Image, Table, Cell).
3057
3223
  * Handles common logic for Tippy.js initialization, positioning, and visibility.
@@ -3261,31 +3427,9 @@ class AteBubbleMenuComponent extends AteBaseBubbleMenu {
3261
3427
  this.onMouseDown = () => {
3262
3428
  this.hideTippy();
3263
3429
  };
3264
- this.config = input({
3265
- bold: true,
3266
- italic: true,
3267
- underline: true,
3268
- strike: true,
3269
- code: true,
3270
- superscript: false,
3271
- subscript: false,
3272
- highlight: true,
3273
- textColor: false,
3274
- link: true,
3275
- separator: true,
3276
- }, ...(ngDevMode ? [{ debugName: "config" }] : []));
3430
+ this.config = input(ATE_DEFAULT_BUBBLE_MENU_CONFIG, ...(ngDevMode ? [{ debugName: "config" }] : []));
3277
3431
  this.bubbleMenuConfig = computed(() => ({
3278
- bold: true,
3279
- italic: true,
3280
- underline: true,
3281
- strike: true,
3282
- code: true,
3283
- superscript: false,
3284
- subscript: false,
3285
- highlight: true,
3286
- textColor: false,
3287
- link: true,
3288
- separator: true,
3432
+ ...ATE_DEFAULT_BUBBLE_MENU_CONFIG,
3289
3433
  ...this.config(),
3290
3434
  }), ...(ngDevMode ? [{ debugName: "bubbleMenuConfig" }] : []));
3291
3435
  }
@@ -3543,41 +3687,93 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3543
3687
  }]
3544
3688
  }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }] } });
3545
3689
 
3690
+ /**
3691
+ * Clés des options du menu bulle de texte
3692
+ */
3693
+ const ATE_BUBBLE_MENU_KEYS = [
3694
+ "bold",
3695
+ "italic",
3696
+ "underline",
3697
+ "strike",
3698
+ "code",
3699
+ "superscript",
3700
+ "subscript",
3701
+ "highlight",
3702
+ "highlightPicker",
3703
+ "textColor",
3704
+ "link",
3705
+ "separator",
3706
+ ];
3707
+ /**
3708
+ * Clés des options du menu bulle d'image
3709
+ */
3710
+ const ATE_IMAGE_BUBBLE_MENU_KEYS = [
3711
+ "changeImage",
3712
+ "downloadImage",
3713
+ "resizeSmall",
3714
+ "resizeMedium",
3715
+ "resizeLarge",
3716
+ "resizeOriginal",
3717
+ "alignLeft",
3718
+ "alignCenter",
3719
+ "alignRight",
3720
+ "deleteImage",
3721
+ "separator",
3722
+ ];
3723
+ /**
3724
+ * Clés des options du menu de table
3725
+ */
3726
+ const ATE_TABLE_BUBBLE_MENU_KEYS = [
3727
+ "addRowBefore",
3728
+ "addRowAfter",
3729
+ "deleteRow",
3730
+ "addColumnBefore",
3731
+ "addColumnAfter",
3732
+ "deleteColumn",
3733
+ "deleteTable",
3734
+ "toggleHeaderRow",
3735
+ "toggleHeaderColumn",
3736
+ "separator",
3737
+ ];
3738
+ /**
3739
+ * Clés des options du menu de cellule
3740
+ */
3741
+ const ATE_CELL_BUBBLE_MENU_KEYS = ["mergeCells", "splitCell"];
3742
+
3546
3743
  class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3547
3744
  constructor() {
3548
3745
  super(...arguments);
3549
3746
  this.t = this.i18nService.imageUpload;
3550
3747
  this.imageService = inject(AteImageService);
3551
- this.config = input({
3552
- changeImage: true,
3553
- resizeSmall: true,
3554
- resizeMedium: true,
3555
- resizeLarge: true,
3556
- resizeOriginal: true,
3557
- deleteImage: true,
3558
- separator: true,
3559
- }, ...(ngDevMode ? [{ debugName: "config" }] : []));
3748
+ this.config = input(ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ...(ngDevMode ? [{ debugName: "config" }] : []));
3560
3749
  this.imageUpload = input({}, ...(ngDevMode ? [{ debugName: "imageUpload" }] : []));
3561
- this.imageBubbleMenuConfig = computed(() => ({
3562
- changeImage: this.config().changeImage ?? true,
3563
- resizeSmall: this.config().resizeSmall ?? true,
3564
- resizeMedium: this.config().resizeMedium ?? true,
3565
- resizeLarge: this.config().resizeLarge ?? true,
3566
- resizeOriginal: this.config().resizeOriginal ?? true,
3567
- deleteImage: this.config().deleteImage ?? true,
3568
- separator: this.config().separator ?? true,
3569
- }), ...(ngDevMode ? [{ debugName: "imageBubbleMenuConfig" }] : []));
3750
+ this.imageBubbleMenuConfig = computed(() => {
3751
+ const c = this.config();
3752
+ const result = {};
3753
+ ATE_IMAGE_BUBBLE_MENU_KEYS.forEach(key => {
3754
+ result[key] = c[key] ?? true;
3755
+ });
3756
+ return result;
3757
+ }, ...(ngDevMode ? [{ debugName: "imageBubbleMenuConfig" }] : []));
3758
+ this.hasAlignmentButtons = computed(() => this.imageBubbleMenuConfig().alignLeft ||
3759
+ this.imageBubbleMenuConfig().alignCenter ||
3760
+ this.imageBubbleMenuConfig().alignRight, ...(ngDevMode ? [{ debugName: "hasAlignmentButtons" }] : []));
3570
3761
  this.hasResizeButtons = computed(() => {
3571
3762
  const c = this.imageBubbleMenuConfig();
3572
3763
  return c.resizeSmall || c.resizeMedium || c.resizeLarge || c.resizeOriginal;
3573
3764
  }, ...(ngDevMode ? [{ debugName: "hasResizeButtons" }] : []));
3574
3765
  }
3575
3766
  shouldShow() {
3576
- const { nodes, isEditable, isFocused } = this.state();
3767
+ const { nodes, isEditable, isFocused, selection } = this.state();
3577
3768
  if (this.editorCommands.linkEditMode() || this.editorCommands.colorEditMode()) {
3578
3769
  return false;
3579
3770
  }
3580
- return nodes.isImage && isEditable && isFocused;
3771
+ // In read-only mode, focus reporting can be unreliable,
3772
+ // so we show the menu as long as an image is selected.
3773
+ if (!isEditable) {
3774
+ return nodes.isImage && selection.type === "node";
3775
+ }
3776
+ return nodes.isImage && isFocused;
3581
3777
  }
3582
3778
  getSelectionRect() {
3583
3779
  const ed = this.editor();
@@ -3615,6 +3811,9 @@ class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3615
3811
  case "changeImage":
3616
3812
  this.changeImage();
3617
3813
  break;
3814
+ case "downloadImage":
3815
+ this.editorCommands.downloadImage(editor);
3816
+ break;
3618
3817
  case "resizeSmall":
3619
3818
  this.imageService.resizeImageToSmall(editor);
3620
3819
  break;
@@ -3630,6 +3829,15 @@ class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3630
3829
  case "deleteImage":
3631
3830
  this.deleteImage();
3632
3831
  break;
3832
+ case "alignLeft":
3833
+ editor.chain().focus().setTextAlign("left").run();
3834
+ break;
3835
+ case "alignCenter":
3836
+ editor.chain().focus().setTextAlign("center").run();
3837
+ break;
3838
+ case "alignRight":
3839
+ editor.chain().focus().setTextAlign("right").run();
3840
+ break;
3633
3841
  }
3634
3842
  }
3635
3843
  async changeImage() {
@@ -3654,46 +3862,81 @@ class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3654
3862
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteImageBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3655
3863
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AteImageBubbleMenuComponent, isStandalone: true, selector: "ate-image-bubble-menu", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
3656
3864
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
3657
- @if (imageBubbleMenuConfig().changeImage) {
3865
+ @if (imageBubbleMenuConfig().changeImage && editor().isEditable) {
3658
3866
  <ate-button
3659
3867
  icon="drive_file_rename_outline"
3660
3868
  [title]="t().changeImage"
3661
3869
  (buttonClick)="onCommand('changeImage', $event)"></ate-button>
3662
3870
  }
3663
- @if (imageBubbleMenuConfig().separator && hasResizeButtons()) {
3871
+ @if (imageBubbleMenuConfig().downloadImage) {
3872
+ <ate-button
3873
+ icon="download"
3874
+ [title]="t().downloadImage"
3875
+ (buttonClick)="onCommand('downloadImage', $event)"></ate-button>
3876
+ }
3877
+ @if (imageBubbleMenuConfig().separator && hasResizeButtons() && editor().isEditable) {
3664
3878
  <ate-separator />
3665
3879
  }
3666
- @if (imageBubbleMenuConfig().resizeSmall) {
3880
+ @if (imageBubbleMenuConfig().resizeSmall && editor().isEditable) {
3667
3881
  <ate-button
3668
3882
  icon="crop_square"
3669
3883
  iconSize="small"
3670
3884
  [title]="t().resizeSmall"
3671
3885
  (buttonClick)="onCommand('resizeSmall', $event)"></ate-button>
3672
3886
  }
3673
- @if (imageBubbleMenuConfig().resizeMedium) {
3887
+ @if (imageBubbleMenuConfig().resizeMedium && editor().isEditable) {
3674
3888
  <ate-button
3675
3889
  icon="crop_square"
3676
3890
  iconSize="medium"
3677
3891
  [title]="t().resizeMedium"
3678
3892
  (buttonClick)="onCommand('resizeMedium', $event)"></ate-button>
3679
3893
  }
3680
- @if (imageBubbleMenuConfig().resizeLarge) {
3894
+ @if (imageBubbleMenuConfig().resizeLarge && editor().isEditable) {
3681
3895
  <ate-button
3682
3896
  icon="crop_square"
3683
3897
  iconSize="large"
3684
3898
  [title]="t().resizeLarge"
3685
3899
  (buttonClick)="onCommand('resizeLarge', $event)"></ate-button>
3686
3900
  }
3687
- @if (imageBubbleMenuConfig().resizeOriginal) {
3901
+ @if (imageBubbleMenuConfig().resizeOriginal && editor().isEditable) {
3688
3902
  <ate-button
3689
3903
  icon="photo_size_select_actual"
3690
3904
  [title]="t().resizeOriginal"
3691
3905
  (buttonClick)="onCommand('resizeOriginal', $event)"></ate-button>
3692
3906
  }
3693
- @if (imageBubbleMenuConfig().separator && imageBubbleMenuConfig().deleteImage) {
3907
+ @if (imageBubbleMenuConfig().separator && hasAlignmentButtons() && editor().isEditable) {
3908
+ <ate-separator />
3909
+ }
3910
+ @if (imageBubbleMenuConfig().alignLeft && editor().isEditable) {
3911
+ <ate-button
3912
+ icon="format_align_left"
3913
+ [title]="t().alignLeft"
3914
+ [active]="editor().isActive({ textAlign: 'left' })"
3915
+ (buttonClick)="onCommand('alignLeft', $event)"></ate-button>
3916
+ }
3917
+ @if (imageBubbleMenuConfig().alignCenter && editor().isEditable) {
3918
+ <ate-button
3919
+ icon="format_align_center"
3920
+ [title]="t().alignCenter"
3921
+ [active]="editor().isActive({ textAlign: 'center' })"
3922
+ (buttonClick)="onCommand('alignCenter', $event)"></ate-button>
3923
+ }
3924
+ @if (imageBubbleMenuConfig().alignRight && editor().isEditable) {
3925
+ <ate-button
3926
+ icon="format_align_right"
3927
+ [title]="t().alignRight"
3928
+ [active]="editor().isActive({ textAlign: 'right' })"
3929
+ (buttonClick)="onCommand('alignRight', $event)"></ate-button>
3930
+ }
3931
+
3932
+ @if (
3933
+ imageBubbleMenuConfig().separator &&
3934
+ imageBubbleMenuConfig().deleteImage &&
3935
+ editor().isEditable
3936
+ ) {
3694
3937
  <ate-separator />
3695
3938
  }
3696
- @if (imageBubbleMenuConfig().deleteImage) {
3939
+ @if (imageBubbleMenuConfig().deleteImage && editor().isEditable) {
3697
3940
  <ate-button
3698
3941
  icon="delete"
3699
3942
  [title]="t().deleteImage"
@@ -3701,7 +3944,7 @@ class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3701
3944
  (buttonClick)="onCommand('deleteImage', $event)"></ate-button>
3702
3945
  }
3703
3946
  </div>
3704
- `, isInline: true, dependencies: [{ kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "component", type: AteSeparatorComponent, selector: "ate-separator", inputs: ["orientation", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3947
+ `, isInline: true, dependencies: [{ kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "component", type: AteSeparatorComponent, selector: "ate-separator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3705
3948
  }
3706
3949
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteImageBubbleMenuComponent, decorators: [{
3707
3950
  type: Component,
@@ -3712,46 +3955,81 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3712
3955
  imports: [AteButtonComponent, AteSeparatorComponent],
3713
3956
  template: `
3714
3957
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
3715
- @if (imageBubbleMenuConfig().changeImage) {
3958
+ @if (imageBubbleMenuConfig().changeImage && editor().isEditable) {
3716
3959
  <ate-button
3717
3960
  icon="drive_file_rename_outline"
3718
3961
  [title]="t().changeImage"
3719
3962
  (buttonClick)="onCommand('changeImage', $event)"></ate-button>
3720
3963
  }
3721
- @if (imageBubbleMenuConfig().separator && hasResizeButtons()) {
3964
+ @if (imageBubbleMenuConfig().downloadImage) {
3965
+ <ate-button
3966
+ icon="download"
3967
+ [title]="t().downloadImage"
3968
+ (buttonClick)="onCommand('downloadImage', $event)"></ate-button>
3969
+ }
3970
+ @if (imageBubbleMenuConfig().separator && hasResizeButtons() && editor().isEditable) {
3722
3971
  <ate-separator />
3723
3972
  }
3724
- @if (imageBubbleMenuConfig().resizeSmall) {
3973
+ @if (imageBubbleMenuConfig().resizeSmall && editor().isEditable) {
3725
3974
  <ate-button
3726
3975
  icon="crop_square"
3727
3976
  iconSize="small"
3728
3977
  [title]="t().resizeSmall"
3729
3978
  (buttonClick)="onCommand('resizeSmall', $event)"></ate-button>
3730
3979
  }
3731
- @if (imageBubbleMenuConfig().resizeMedium) {
3980
+ @if (imageBubbleMenuConfig().resizeMedium && editor().isEditable) {
3732
3981
  <ate-button
3733
3982
  icon="crop_square"
3734
3983
  iconSize="medium"
3735
3984
  [title]="t().resizeMedium"
3736
3985
  (buttonClick)="onCommand('resizeMedium', $event)"></ate-button>
3737
3986
  }
3738
- @if (imageBubbleMenuConfig().resizeLarge) {
3987
+ @if (imageBubbleMenuConfig().resizeLarge && editor().isEditable) {
3739
3988
  <ate-button
3740
3989
  icon="crop_square"
3741
3990
  iconSize="large"
3742
3991
  [title]="t().resizeLarge"
3743
3992
  (buttonClick)="onCommand('resizeLarge', $event)"></ate-button>
3744
3993
  }
3745
- @if (imageBubbleMenuConfig().resizeOriginal) {
3994
+ @if (imageBubbleMenuConfig().resizeOriginal && editor().isEditable) {
3746
3995
  <ate-button
3747
3996
  icon="photo_size_select_actual"
3748
3997
  [title]="t().resizeOriginal"
3749
3998
  (buttonClick)="onCommand('resizeOriginal', $event)"></ate-button>
3750
3999
  }
3751
- @if (imageBubbleMenuConfig().separator && imageBubbleMenuConfig().deleteImage) {
4000
+ @if (imageBubbleMenuConfig().separator && hasAlignmentButtons() && editor().isEditable) {
4001
+ <ate-separator />
4002
+ }
4003
+ @if (imageBubbleMenuConfig().alignLeft && editor().isEditable) {
4004
+ <ate-button
4005
+ icon="format_align_left"
4006
+ [title]="t().alignLeft"
4007
+ [active]="editor().isActive({ textAlign: 'left' })"
4008
+ (buttonClick)="onCommand('alignLeft', $event)"></ate-button>
4009
+ }
4010
+ @if (imageBubbleMenuConfig().alignCenter && editor().isEditable) {
4011
+ <ate-button
4012
+ icon="format_align_center"
4013
+ [title]="t().alignCenter"
4014
+ [active]="editor().isActive({ textAlign: 'center' })"
4015
+ (buttonClick)="onCommand('alignCenter', $event)"></ate-button>
4016
+ }
4017
+ @if (imageBubbleMenuConfig().alignRight && editor().isEditable) {
4018
+ <ate-button
4019
+ icon="format_align_right"
4020
+ [title]="t().alignRight"
4021
+ [active]="editor().isActive({ textAlign: 'right' })"
4022
+ (buttonClick)="onCommand('alignRight', $event)"></ate-button>
4023
+ }
4024
+
4025
+ @if (
4026
+ imageBubbleMenuConfig().separator &&
4027
+ imageBubbleMenuConfig().deleteImage &&
4028
+ editor().isEditable
4029
+ ) {
3752
4030
  <ate-separator />
3753
4031
  }
3754
- @if (imageBubbleMenuConfig().deleteImage) {
4032
+ @if (imageBubbleMenuConfig().deleteImage && editor().isEditable) {
3755
4033
  <ate-button
3756
4034
  icon="delete"
3757
4035
  [title]="t().deleteImage"
@@ -3768,18 +4046,15 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3768
4046
  super(...arguments);
3769
4047
  // Alias for template
3770
4048
  this.t = this.i18nService.table;
3771
- this.config = input({
3772
- addRowBefore: true,
3773
- addRowAfter: true,
3774
- deleteRow: true,
3775
- addColumnBefore: true,
3776
- addColumnAfter: true,
3777
- deleteColumn: true,
3778
- deleteTable: true,
3779
- toggleHeaderRow: true,
3780
- toggleHeaderColumn: true,
3781
- separator: true,
3782
- }, ...(ngDevMode ? [{ debugName: "config" }] : []));
4049
+ this.config = input(ATE_DEFAULT_TABLE_MENU_CONFIG, ...(ngDevMode ? [{ debugName: "config" }] : []));
4050
+ this.tableBubbleMenuConfig = computed(() => {
4051
+ const c = this.config();
4052
+ const result = {};
4053
+ ATE_TABLE_BUBBLE_MENU_KEYS.forEach(key => {
4054
+ result[key] = c[key] ?? true;
4055
+ });
4056
+ return result;
4057
+ }, ...(ngDevMode ? [{ debugName: "tableBubbleMenuConfig" }] : []));
3783
4058
  }
3784
4059
  shouldShow() {
3785
4060
  const { selection, nodes, isEditable, isFocused } = this.state();
@@ -3841,21 +4116,21 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3841
4116
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AteTableBubbleMenuComponent, isStandalone: true, selector: "ate-table-bubble-menu", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
3842
4117
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
3843
4118
  <!-- Row actions -->
3844
- @if (config().addRowBefore !== false) {
4119
+ @if (tableBubbleMenuConfig().addRowBefore !== false) {
3845
4120
  <ate-button
3846
4121
  icon="add_row_above"
3847
4122
  [title]="t().addRowBefore"
3848
4123
  [disabled]="!state().can.addRowBefore"
3849
4124
  (buttonClick)="onCommand('addRowBefore', $event)"></ate-button>
3850
4125
  }
3851
- @if (config().addRowAfter !== false) {
4126
+ @if (tableBubbleMenuConfig().addRowAfter !== false) {
3852
4127
  <ate-button
3853
4128
  icon="add_row_below"
3854
4129
  [title]="t().addRowAfter"
3855
4130
  [disabled]="!state().can.addRowAfter"
3856
4131
  (buttonClick)="onCommand('addRowAfter', $event)"></ate-button>
3857
4132
  }
3858
- @if (config().deleteRow !== false) {
4133
+ @if (tableBubbleMenuConfig().deleteRow !== false) {
3859
4134
  <ate-button
3860
4135
  icon="delete"
3861
4136
  [title]="t().deleteRow"
@@ -3863,26 +4138,26 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3863
4138
  [disabled]="!state().can.deleteRow"
3864
4139
  (buttonClick)="onCommand('deleteRow', $event)"></ate-button>
3865
4140
  }
3866
- @if (config().separator !== false) {
4141
+ @if (tableBubbleMenuConfig().separator !== false) {
3867
4142
  <ate-separator />
3868
4143
  }
3869
4144
 
3870
4145
  <!-- Column actions -->
3871
- @if (config().addColumnBefore !== false) {
4146
+ @if (tableBubbleMenuConfig().addColumnBefore !== false) {
3872
4147
  <ate-button
3873
4148
  icon="add_column_left"
3874
4149
  [title]="t().addColumnBefore"
3875
4150
  [disabled]="!state().can.addColumnBefore"
3876
4151
  (buttonClick)="onCommand('addColumnBefore', $event)"></ate-button>
3877
4152
  }
3878
- @if (config().addColumnAfter !== false) {
4153
+ @if (tableBubbleMenuConfig().addColumnAfter !== false) {
3879
4154
  <ate-button
3880
4155
  icon="add_column_right"
3881
4156
  [title]="t().addColumnAfter"
3882
4157
  [disabled]="!state().can.addColumnAfter"
3883
4158
  (buttonClick)="onCommand('addColumnAfter', $event)"></ate-button>
3884
4159
  }
3885
- @if (config().deleteColumn !== false) {
4160
+ @if (tableBubbleMenuConfig().deleteColumn !== false) {
3886
4161
  <ate-button
3887
4162
  icon="delete"
3888
4163
  [title]="t().deleteColumn"
@@ -3890,12 +4165,12 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3890
4165
  [disabled]="!state().can.deleteColumn"
3891
4166
  (buttonClick)="onCommand('deleteColumn', $event)"></ate-button>
3892
4167
  }
3893
- @if (config().separator !== false) {
4168
+ @if (tableBubbleMenuConfig().separator !== false) {
3894
4169
  <ate-separator />
3895
4170
  }
3896
4171
 
3897
4172
  <!-- Cell actions -->
3898
- @if (config().toggleHeaderRow !== false) {
4173
+ @if (tableBubbleMenuConfig().toggleHeaderRow !== false) {
3899
4174
  <ate-button
3900
4175
  icon="toolbar"
3901
4176
  [title]="t().toggleHeaderRow"
@@ -3903,7 +4178,7 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3903
4178
  [disabled]="!state().can.toggleHeaderRow"
3904
4179
  (buttonClick)="onCommand('toggleHeaderRow', $event)"></ate-button>
3905
4180
  }
3906
- @if (config().toggleHeaderColumn !== false) {
4181
+ @if (tableBubbleMenuConfig().toggleHeaderColumn !== false) {
3907
4182
  <ate-button
3908
4183
  icon="dock_to_right"
3909
4184
  [title]="t().toggleHeaderColumn"
@@ -3911,12 +4186,14 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3911
4186
  [disabled]="!state().can.toggleHeaderColumn"
3912
4187
  (buttonClick)="onCommand('toggleHeaderColumn', $event)"></ate-button>
3913
4188
  }
3914
- @if (config().separator !== false && config().deleteTable !== false) {
4189
+ @if (
4190
+ tableBubbleMenuConfig().separator !== false && tableBubbleMenuConfig().deleteTable !== false
4191
+ ) {
3915
4192
  <ate-separator />
3916
4193
  }
3917
4194
 
3918
4195
  <!-- Table actions -->
3919
- @if (config().deleteTable !== false) {
4196
+ @if (tableBubbleMenuConfig().deleteTable !== false) {
3920
4197
  <ate-button
3921
4198
  icon="delete_forever"
3922
4199
  [title]="t().deleteTable"
@@ -3925,7 +4202,7 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3925
4202
  (buttonClick)="onCommand('deleteTable', $event)"></ate-button>
3926
4203
  }
3927
4204
  </div>
3928
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "component", type: AteSeparatorComponent, selector: "ate-separator", inputs: ["orientation", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4205
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "component", type: AteSeparatorComponent, selector: "ate-separator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3929
4206
  }
3930
4207
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteTableBubbleMenuComponent, decorators: [{
3931
4208
  type: Component,
@@ -3937,21 +4214,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3937
4214
  template: `
3938
4215
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
3939
4216
  <!-- Row actions -->
3940
- @if (config().addRowBefore !== false) {
4217
+ @if (tableBubbleMenuConfig().addRowBefore !== false) {
3941
4218
  <ate-button
3942
4219
  icon="add_row_above"
3943
4220
  [title]="t().addRowBefore"
3944
4221
  [disabled]="!state().can.addRowBefore"
3945
4222
  (buttonClick)="onCommand('addRowBefore', $event)"></ate-button>
3946
4223
  }
3947
- @if (config().addRowAfter !== false) {
4224
+ @if (tableBubbleMenuConfig().addRowAfter !== false) {
3948
4225
  <ate-button
3949
4226
  icon="add_row_below"
3950
4227
  [title]="t().addRowAfter"
3951
4228
  [disabled]="!state().can.addRowAfter"
3952
4229
  (buttonClick)="onCommand('addRowAfter', $event)"></ate-button>
3953
4230
  }
3954
- @if (config().deleteRow !== false) {
4231
+ @if (tableBubbleMenuConfig().deleteRow !== false) {
3955
4232
  <ate-button
3956
4233
  icon="delete"
3957
4234
  [title]="t().deleteRow"
@@ -3959,26 +4236,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3959
4236
  [disabled]="!state().can.deleteRow"
3960
4237
  (buttonClick)="onCommand('deleteRow', $event)"></ate-button>
3961
4238
  }
3962
- @if (config().separator !== false) {
4239
+ @if (tableBubbleMenuConfig().separator !== false) {
3963
4240
  <ate-separator />
3964
4241
  }
3965
4242
 
3966
4243
  <!-- Column actions -->
3967
- @if (config().addColumnBefore !== false) {
4244
+ @if (tableBubbleMenuConfig().addColumnBefore !== false) {
3968
4245
  <ate-button
3969
4246
  icon="add_column_left"
3970
4247
  [title]="t().addColumnBefore"
3971
4248
  [disabled]="!state().can.addColumnBefore"
3972
4249
  (buttonClick)="onCommand('addColumnBefore', $event)"></ate-button>
3973
4250
  }
3974
- @if (config().addColumnAfter !== false) {
4251
+ @if (tableBubbleMenuConfig().addColumnAfter !== false) {
3975
4252
  <ate-button
3976
4253
  icon="add_column_right"
3977
4254
  [title]="t().addColumnAfter"
3978
4255
  [disabled]="!state().can.addColumnAfter"
3979
4256
  (buttonClick)="onCommand('addColumnAfter', $event)"></ate-button>
3980
4257
  }
3981
- @if (config().deleteColumn !== false) {
4258
+ @if (tableBubbleMenuConfig().deleteColumn !== false) {
3982
4259
  <ate-button
3983
4260
  icon="delete"
3984
4261
  [title]="t().deleteColumn"
@@ -3986,12 +4263,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3986
4263
  [disabled]="!state().can.deleteColumn"
3987
4264
  (buttonClick)="onCommand('deleteColumn', $event)"></ate-button>
3988
4265
  }
3989
- @if (config().separator !== false) {
4266
+ @if (tableBubbleMenuConfig().separator !== false) {
3990
4267
  <ate-separator />
3991
4268
  }
3992
4269
 
3993
4270
  <!-- Cell actions -->
3994
- @if (config().toggleHeaderRow !== false) {
4271
+ @if (tableBubbleMenuConfig().toggleHeaderRow !== false) {
3995
4272
  <ate-button
3996
4273
  icon="toolbar"
3997
4274
  [title]="t().toggleHeaderRow"
@@ -3999,7 +4276,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3999
4276
  [disabled]="!state().can.toggleHeaderRow"
4000
4277
  (buttonClick)="onCommand('toggleHeaderRow', $event)"></ate-button>
4001
4278
  }
4002
- @if (config().toggleHeaderColumn !== false) {
4279
+ @if (tableBubbleMenuConfig().toggleHeaderColumn !== false) {
4003
4280
  <ate-button
4004
4281
  icon="dock_to_right"
4005
4282
  [title]="t().toggleHeaderColumn"
@@ -4007,12 +4284,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
4007
4284
  [disabled]="!state().can.toggleHeaderColumn"
4008
4285
  (buttonClick)="onCommand('toggleHeaderColumn', $event)"></ate-button>
4009
4286
  }
4010
- @if (config().separator !== false && config().deleteTable !== false) {
4287
+ @if (
4288
+ tableBubbleMenuConfig().separator !== false && tableBubbleMenuConfig().deleteTable !== false
4289
+ ) {
4011
4290
  <ate-separator />
4012
4291
  }
4013
4292
 
4014
4293
  <!-- Table actions -->
4015
- @if (config().deleteTable !== false) {
4294
+ @if (tableBubbleMenuConfig().deleteTable !== false) {
4016
4295
  <ate-button
4017
4296
  icon="delete_forever"
4018
4297
  [title]="t().deleteTable"
@@ -4029,7 +4308,11 @@ class AteCellBubbleMenuComponent extends AteBaseBubbleMenu {
4029
4308
  constructor() {
4030
4309
  super(...arguments);
4031
4310
  // Inputs
4032
- this.config = input({}, ...(ngDevMode ? [{ debugName: "config" }] : []));
4311
+ this.config = input(ATE_DEFAULT_CELL_MENU_CONFIG, ...(ngDevMode ? [{ debugName: "config" }] : []));
4312
+ this.cellBubbleMenuConfig = computed(() => ({
4313
+ mergeCells: this.config().mergeCells ?? true,
4314
+ splitCell: this.config().splitCell ?? true,
4315
+ }), ...(ngDevMode ? [{ debugName: "cellBubbleMenuConfig" }] : []));
4033
4316
  // Signals
4034
4317
  this.i18n = () => this.i18nService;
4035
4318
  }
@@ -4095,14 +4378,14 @@ class AteCellBubbleMenuComponent extends AteBaseBubbleMenu {
4095
4378
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AteCellBubbleMenuComponent, isStandalone: true, selector: "ate-cell-bubble-menu", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
4096
4379
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
4097
4380
  <!-- Cell specific actions -->
4098
- @if (config().mergeCells !== false && !state().selection.isSingleCell) {
4381
+ @if (cellBubbleMenuConfig().mergeCells !== false && !state().selection.isSingleCell) {
4099
4382
  <ate-button
4100
4383
  icon="cell_merge"
4101
4384
  [title]="i18n().table().mergeCells"
4102
4385
  [disabled]="!state().can.mergeCells"
4103
4386
  (buttonClick)="onCommand('mergeCells', $event)"></ate-button>
4104
4387
  }
4105
- @if (config().splitCell !== false && state().selection.isSingleCell) {
4388
+ @if (cellBubbleMenuConfig().splitCell !== false && state().selection.isSingleCell) {
4106
4389
  <ate-button
4107
4390
  icon="split_scene"
4108
4391
  [title]="i18n().table().splitCell"
@@ -4122,14 +4405,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
4122
4405
  template: `
4123
4406
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
4124
4407
  <!-- Cell specific actions -->
4125
- @if (config().mergeCells !== false && !state().selection.isSingleCell) {
4408
+ @if (cellBubbleMenuConfig().mergeCells !== false && !state().selection.isSingleCell) {
4126
4409
  <ate-button
4127
4410
  icon="cell_merge"
4128
4411
  [title]="i18n().table().mergeCells"
4129
4412
  [disabled]="!state().can.mergeCells"
4130
4413
  (buttonClick)="onCommand('mergeCells', $event)"></ate-button>
4131
4414
  }
4132
- @if (config().splitCell !== false && state().selection.isSingleCell) {
4415
+ @if (cellBubbleMenuConfig().splitCell !== false && state().selection.isSingleCell) {
4133
4416
  <ate-button
4134
4417
  icon="split_scene"
4135
4418
  [title]="i18n().table().splitCell"
@@ -4456,7 +4739,7 @@ class AteLinkBubbleMenuComponent extends AteBaseSubBubbleMenu {
4456
4739
  </div>
4457
4740
  </div>
4458
4741
  </div>
4459
- `, isInline: true, styles: [".link-input-row{display:flex;align-items:center;gap:6px}.url-input-container{flex:1;display:flex;align-items:center;background:var(--ate-surface-secondary, #f8fafc);border:1px solid var(--ate-border, #e2e8f0);border-radius:8px;padding:0 10px;height:32px;transition:all .15s ease}.url-input-container:focus-within{border-color:var(--ate-primary, #3b82f6);background:var(--ate-surface, #ffffff);box-shadow:0 0 0 2px var(--ate-primary-light, rgba(59, 130, 246, .1))}.icon-link{font-size:16px;color:var(--ate-text-muted, #94a3b8);margin-right:6px}.url-field{background:transparent;border:none;outline:none;color:var(--ate-text, #1e293b);font-size:13px;width:100%;font-family:inherit}.action-buttons{display:flex;align-items:center;gap:2px}\n"], dependencies: [{ kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "component", type: AteSeparatorComponent, selector: "ate-separator", inputs: ["orientation", "size"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4742
+ `, isInline: true, styles: [".link-input-row{display:flex;align-items:center;gap:6px}.url-input-container{flex:1;display:flex;align-items:center;background:var(--ate-surface-secondary, #f8fafc);border:1px solid var(--ate-border, #e2e8f0);border-radius:8px;padding:0 10px;height:32px;transition:all .15s ease}.url-input-container:focus-within{border-color:var(--ate-primary, #3b82f6);background:var(--ate-surface, #ffffff);box-shadow:0 0 0 2px var(--ate-primary-light, rgba(59, 130, 246, .1))}.icon-link{font-size:16px;color:var(--ate-text-muted, #94a3b8);margin-right:6px}.url-field{background:transparent;border:none;outline:none;color:var(--ate-text, #1e293b);font-size:13px;width:100%;font-family:inherit}.action-buttons{display:flex;align-items:center;gap:2px}\n"], dependencies: [{ kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "component", type: AteSeparatorComponent, selector: "ate-separator" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4460
4743
  }
4461
4744
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteLinkBubbleMenuComponent, decorators: [{
4462
4745
  type: Component,
@@ -4783,7 +5066,7 @@ class AteColorBubbleMenuComponent extends AteBaseSubBubbleMenu {
4783
5066
  </div>
4784
5067
  </div>
4785
5068
  </div>
4786
- `, isInline: true, styles: [".color-picker-container{display:flex;flex-direction:column;gap:8px}.dropdown-row{display:flex;align-items:center;width:100%}.dropdown-row.presets{justify-content:center}.dropdown-row.controls{gap:8px;justify-content:space-between;padding-top:4px;border-top:1px solid var(--ate-border, #e2e8f0)}.color-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:4px;width:100%}:host ::ng-deep .color-swatch-btn .ate-button{width:100%;aspect-ratio:1;height:auto;border-radius:4px;border:1px solid rgba(0,0,0,.1);padding:0}:host ::ng-deep .color-swatch-btn .ate-button.is-active{border-color:var(--ate-primary, #3b82f6);box-shadow:0 0 0 2px #3b82f64d}:host ::ng-deep .btn-native-picker-trigger .ate-button{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.2)}.divider-v{width:1px;height:24px;background:var(--ate-border, #e2e8f0)}.hex-input-wrapper{flex:1;display:flex;align-items:center;background:var(--ate-surface-secondary, #f8fafc);border:1px solid var(--ate-border, #e2e8f0);border-radius:8px;padding:0 10px;height:32px;transition:border-color .15s ease}.hex-input-wrapper:focus-within{border-color:var(--ate-primary, #3b82f6);background:var(--ate-menu-bg, #ffffff)}.hex-hash{color:var(--ate-text-muted, #94a3b8);font-family:monospace;font-size:.875rem}.hex-input{background:transparent;border:none;outline:none;color:var(--ate-text, #1e293b);font-family:monospace;font-size:.875rem;width:100%;padding-left:4px}.native-trigger-wrapper{position:relative;width:32px;height:32px}.hidden-native-input{position:absolute;inset:0;opacity:0;width:100%;height:100%;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "component", type: AteSeparatorComponent, selector: "ate-separator", inputs: ["orientation", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5069
+ `, isInline: true, styles: [".color-picker-container{display:flex;flex-direction:column;gap:8px}.dropdown-row{display:flex;align-items:center;width:100%}.dropdown-row.presets{justify-content:center}.dropdown-row.controls{gap:8px;justify-content:space-between;padding-top:4px;border-top:1px solid var(--ate-border, #e2e8f0)}.color-grid{display:grid;grid-template-columns:repeat(12,1fr);gap:4px;width:100%}:host ::ng-deep .color-swatch-btn .ate-button{width:100%;aspect-ratio:1;height:auto;border-radius:4px;border:1px solid rgba(0,0,0,.1);padding:0}:host ::ng-deep .color-swatch-btn .ate-button.is-active{border-color:var(--ate-primary, #3b82f6);box-shadow:0 0 0 2px #3b82f64d}:host ::ng-deep .btn-native-picker-trigger .ate-button{color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.2)}.divider-v{width:1px;height:24px;background:var(--ate-border, #e2e8f0)}.hex-input-wrapper{flex:1;display:flex;align-items:center;background:var(--ate-surface-secondary, #f8fafc);border:1px solid var(--ate-border, #e2e8f0);border-radius:8px;padding:0 10px;height:32px;transition:border-color .15s ease}.hex-input-wrapper:focus-within{border-color:var(--ate-primary, #3b82f6);background:var(--ate-menu-bg, #ffffff)}.hex-hash{color:var(--ate-text-muted, #94a3b8);font-family:monospace;font-size:.875rem}.hex-input{background:transparent;border:none;outline:none;color:var(--ate-text, #1e293b);font-family:monospace;font-size:.875rem;width:100%;padding-left:4px}.native-trigger-wrapper{position:relative;width:32px;height:32px}.hidden-native-input{position:absolute;inset:0;opacity:0;width:100%;height:100%;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "component", type: AteSeparatorComponent, selector: "ate-separator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4787
5070
  }
4788
5071
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteColorBubbleMenuComponent, decorators: [{
4789
5072
  type: Component,
@@ -6109,124 +6392,6 @@ const AteLinkClickBehavior = Extension.create({
6109
6392
  },
6110
6393
  });
6111
6394
 
6112
- // Default toolbar configuration
6113
- const ATE_DEFAULT_TOOLBAR_CONFIG = {
6114
- bold: true,
6115
- italic: true,
6116
- underline: true,
6117
- strike: true,
6118
- code: true,
6119
- codeBlock: true,
6120
- superscript: false, // Disabled by default (opt-in)
6121
- subscript: false, // Disabled by default (opt-in)
6122
- highlight: false, // Disabled by default (opt-in)
6123
- highlightPicker: true,
6124
- heading1: true,
6125
- heading2: true,
6126
- heading3: true,
6127
- bulletList: true,
6128
- orderedList: true,
6129
- blockquote: true,
6130
- alignLeft: false, // Disabled by default (opt-in)
6131
- alignCenter: false, // Disabled by default (opt-in)
6132
- alignRight: false, // Disabled by default (opt-in)
6133
- alignJustify: false, // Disabled by default (opt-in)
6134
- link: true,
6135
- image: true,
6136
- horizontalRule: false, // Disabled by default (opt-in)
6137
- table: true,
6138
- undo: true,
6139
- redo: true,
6140
- clear: false, // Disabled by default (opt-in)
6141
- textColor: true,
6142
- separator: true,
6143
- };
6144
- // Default bubble menu configuration
6145
- const ATE_DEFAULT_BUBBLE_MENU_CONFIG = {
6146
- bold: true,
6147
- italic: true,
6148
- underline: true,
6149
- strike: true,
6150
- code: true,
6151
- superscript: false,
6152
- subscript: false,
6153
- highlight: false,
6154
- highlightPicker: true,
6155
- textColor: true,
6156
- link: true,
6157
- separator: true,
6158
- };
6159
- // Default image bubble menu configuration
6160
- const ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG = {
6161
- changeImage: true,
6162
- resizeSmall: true,
6163
- resizeMedium: true,
6164
- resizeLarge: true,
6165
- resizeOriginal: true,
6166
- deleteImage: true,
6167
- separator: true,
6168
- };
6169
- // Default table bubble menu configuration
6170
- const ATE_DEFAULT_TABLE_MENU_CONFIG = {
6171
- addRowBefore: true,
6172
- addRowAfter: true,
6173
- deleteRow: true,
6174
- addColumnBefore: true,
6175
- addColumnAfter: true,
6176
- deleteColumn: true,
6177
- toggleHeaderRow: true,
6178
- toggleHeaderColumn: true,
6179
- deleteTable: true,
6180
- separator: true,
6181
- };
6182
- // Default cell bubble menu configuration
6183
- const ATE_DEFAULT_CELL_MENU_CONFIG = {
6184
- mergeCells: true,
6185
- splitCell: true,
6186
- };
6187
- /**
6188
- * Ultimate default configuration for the Angular Tiptap Editor.
6189
- * This serves as the 'Level 4' fallback in the configuration hierarchy:
6190
- * 1. Component Inputs (Le Roi)
6191
- * 2. Component [config] (Le Prince)
6192
- * 3. Global provideAteEditor() (Le Duc)
6193
- * 4. ATE_DEFAULT_CONFIG (Le Peuple)
6194
- */
6195
- const ATE_DEFAULT_CONFIG = {
6196
- theme: "auto",
6197
- mode: "classic",
6198
- height: "auto",
6199
- minHeight: "200px",
6200
- maxHeight: "none",
6201
- fillContainer: false,
6202
- autofocus: false,
6203
- editable: true,
6204
- disabled: false,
6205
- spellcheck: true,
6206
- enableOfficePaste: true,
6207
- showToolbar: true,
6208
- showFooter: true,
6209
- showCharacterCount: true,
6210
- showWordCount: true,
6211
- showEditToggle: false,
6212
- showBubbleMenu: true,
6213
- showImageBubbleMenu: true,
6214
- showTableMenu: true,
6215
- showCellMenu: true,
6216
- enableSlashCommands: true,
6217
- floatingToolbar: false,
6218
- toolbar: ATE_DEFAULT_TOOLBAR_CONFIG,
6219
- bubbleMenu: ATE_DEFAULT_BUBBLE_MENU_CONFIG,
6220
- imageBubbleMenu: ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG,
6221
- tableBubbleMenu: ATE_DEFAULT_TABLE_MENU_CONFIG,
6222
- cellBubbleMenu: ATE_DEFAULT_CELL_MENU_CONFIG,
6223
- slashCommands: {},
6224
- tiptapExtensions: [],
6225
- tiptapOptions: {},
6226
- stateCalculators: [],
6227
- angularNodes: [],
6228
- };
6229
-
6230
6395
  // Slash commands configuration is handled dynamically via slashCommandsConfigComputed
6231
6396
  /**
6232
6397
  * The main rich-text editor component for Angular.
@@ -6347,18 +6512,19 @@ class AngularTiptapEditorComponent {
6347
6512
  // Appearance & Fundamentals
6348
6513
  this.finalSeamless = computed(() => {
6349
6514
  const inputVal = this.seamless();
6350
- if (inputVal !== undefined)
6515
+ if (inputVal !== undefined) {
6351
6516
  return inputVal;
6517
+ }
6352
6518
  const fromConfig = this.effectiveConfig().mode;
6353
6519
  return fromConfig === "seamless";
6354
6520
  }, ...(ngDevMode ? [{ debugName: "finalSeamless" }] : []));
6355
- this.finalEditable = computed(() => this.editable() ?? this.effectiveConfig().editable, ...(ngDevMode ? [{ debugName: "finalEditable" }] : []));
6521
+ this.finalEditable = computed(() => this.editable() ?? this.effectiveConfig().editable ?? true, ...(ngDevMode ? [{ debugName: "finalEditable" }] : []));
6356
6522
  this.finalPlaceholder = computed(() => this.placeholder() ??
6357
6523
  this.effectiveConfig().placeholder ??
6358
6524
  this.currentTranslations().editor.placeholder, ...(ngDevMode ? [{ debugName: "finalPlaceholder" }] : []));
6359
6525
  this.finalFillContainer = computed(() => this.fillContainer() ?? this.effectiveConfig().fillContainer, ...(ngDevMode ? [{ debugName: "finalFillContainer" }] : []));
6360
- this.finalShowFooter = computed(() => this.showFooter() ?? this.effectiveConfig().showFooter, ...(ngDevMode ? [{ debugName: "finalShowFooter" }] : []));
6361
- this.finalShowEditToggle = computed(() => this.showEditToggle() ?? this.effectiveConfig().showEditToggle, ...(ngDevMode ? [{ debugName: "finalShowEditToggle" }] : []));
6526
+ this.finalShowFooter = computed(() => this.showFooter() ?? this.effectiveConfig().showFooter ?? true, ...(ngDevMode ? [{ debugName: "finalShowFooter" }] : []));
6527
+ this.finalShowEditToggle = computed(() => this.showEditToggle() ?? this.effectiveConfig().showEditToggle ?? false, ...(ngDevMode ? [{ debugName: "finalShowEditToggle" }] : []));
6362
6528
  this.finalHeight = computed(() => {
6363
6529
  const h = this.height() ?? this.effectiveConfig().height;
6364
6530
  return typeof h === "number" ? `${h}px` : h;
@@ -6371,10 +6537,10 @@ class AngularTiptapEditorComponent {
6371
6537
  const mh = this.maxHeight() ?? this.effectiveConfig().maxHeight;
6372
6538
  return typeof mh === "number" ? `${mh}px` : mh;
6373
6539
  }, ...(ngDevMode ? [{ debugName: "finalMaxHeight" }] : []));
6374
- this.finalSpellcheck = computed(() => this.spellcheck() ?? this.effectiveConfig().spellcheck, ...(ngDevMode ? [{ debugName: "finalSpellcheck" }] : []));
6375
- this.finalEnableOfficePaste = computed(() => this.enableOfficePaste() ?? this.effectiveConfig().enableOfficePaste, ...(ngDevMode ? [{ debugName: "finalEnableOfficePaste" }] : []));
6540
+ this.finalSpellcheck = computed(() => this.spellcheck() ?? this.effectiveConfig().spellcheck ?? true, ...(ngDevMode ? [{ debugName: "finalSpellcheck" }] : []));
6541
+ this.finalEnableOfficePaste = computed(() => this.enableOfficePaste() ?? this.effectiveConfig().enableOfficePaste ?? true, ...(ngDevMode ? [{ debugName: "finalEnableOfficePaste" }] : []));
6376
6542
  // Features
6377
- this.finalShowToolbar = computed(() => this.showToolbar() ?? this.effectiveConfig().showToolbar, ...(ngDevMode ? [{ debugName: "finalShowToolbar" }] : []));
6543
+ this.finalShowToolbar = computed(() => this.showToolbar() ?? this.effectiveConfig().showToolbar ?? true, ...(ngDevMode ? [{ debugName: "finalShowToolbar" }] : []));
6378
6544
  this.finalToolbarConfig = computed(() => {
6379
6545
  const fromInput = this.toolbar();
6380
6546
  const fromConfig = this.effectiveConfig().toolbar;
@@ -6387,8 +6553,8 @@ class AngularTiptapEditorComponent {
6387
6553
  }
6388
6554
  return base;
6389
6555
  }, ...(ngDevMode ? [{ debugName: "finalToolbarConfig" }] : []));
6390
- this.finalFloatingToolbar = computed(() => this.floatingToolbar() ?? this.effectiveConfig().floatingToolbar, ...(ngDevMode ? [{ debugName: "finalFloatingToolbar" }] : []));
6391
- this.finalShowBubbleMenu = computed(() => this.showBubbleMenu() ?? this.effectiveConfig().showBubbleMenu, ...(ngDevMode ? [{ debugName: "finalShowBubbleMenu" }] : []));
6556
+ this.finalFloatingToolbar = computed(() => this.floatingToolbar() ?? this.effectiveConfig().floatingToolbar ?? false, ...(ngDevMode ? [{ debugName: "finalFloatingToolbar" }] : []));
6557
+ this.finalShowBubbleMenu = computed(() => this.showBubbleMenu() ?? this.effectiveConfig().showBubbleMenu ?? true, ...(ngDevMode ? [{ debugName: "finalShowBubbleMenu" }] : []));
6392
6558
  this.finalBubbleMenuConfig = computed(() => {
6393
6559
  const fromInput = this.bubbleMenu();
6394
6560
  const fromConfig = this.effectiveConfig().bubbleMenu;
@@ -6401,7 +6567,7 @@ class AngularTiptapEditorComponent {
6401
6567
  }
6402
6568
  return base;
6403
6569
  }, ...(ngDevMode ? [{ debugName: "finalBubbleMenuConfig" }] : []));
6404
- this.finalShowImageBubbleMenu = computed(() => this.showImageBubbleMenu() ?? this.effectiveConfig().showImageBubbleMenu, ...(ngDevMode ? [{ debugName: "finalShowImageBubbleMenu" }] : []));
6570
+ this.finalShowImageBubbleMenu = computed(() => this.showImageBubbleMenu() ?? this.effectiveConfig().showImageBubbleMenu ?? true, ...(ngDevMode ? [{ debugName: "finalShowImageBubbleMenu" }] : []));
6405
6571
  this.finalImageBubbleMenuConfig = computed(() => {
6406
6572
  const fromInput = this.imageBubbleMenu();
6407
6573
  const fromConfig = this.effectiveConfig().imageBubbleMenu;
@@ -6414,7 +6580,7 @@ class AngularTiptapEditorComponent {
6414
6580
  }
6415
6581
  return base;
6416
6582
  }, ...(ngDevMode ? [{ debugName: "finalImageBubbleMenuConfig" }] : []));
6417
- this.finalShowTableBubbleMenu = computed(() => this.showTableBubbleMenu() ?? this.effectiveConfig().showTableMenu, ...(ngDevMode ? [{ debugName: "finalShowTableBubbleMenu" }] : []));
6583
+ this.finalShowTableBubbleMenu = computed(() => this.showTableBubbleMenu() ?? this.effectiveConfig().showTableMenu ?? true, ...(ngDevMode ? [{ debugName: "finalShowTableBubbleMenu" }] : []));
6418
6584
  this.finalTableBubbleMenuConfig = computed(() => {
6419
6585
  const fromInput = this.tableBubbleMenu();
6420
6586
  const fromConfig = this.effectiveConfig().tableBubbleMenu;
@@ -6427,7 +6593,7 @@ class AngularTiptapEditorComponent {
6427
6593
  }
6428
6594
  return base;
6429
6595
  }, ...(ngDevMode ? [{ debugName: "finalTableBubbleMenuConfig" }] : []));
6430
- this.finalShowCellBubbleMenu = computed(() => this.showCellBubbleMenu() ?? this.effectiveConfig().showCellMenu, ...(ngDevMode ? [{ debugName: "finalShowCellBubbleMenu" }] : []));
6596
+ this.finalShowCellBubbleMenu = computed(() => this.showCellBubbleMenu() ?? this.effectiveConfig().showCellMenu ?? true, ...(ngDevMode ? [{ debugName: "finalShowCellBubbleMenu" }] : []));
6431
6597
  this.finalCellBubbleMenuConfig = computed(() => {
6432
6598
  const fromInput = this.cellBubbleMenu();
6433
6599
  const fromConfig = this.effectiveConfig().cellBubbleMenu;
@@ -6440,7 +6606,7 @@ class AngularTiptapEditorComponent {
6440
6606
  }
6441
6607
  return base;
6442
6608
  }, ...(ngDevMode ? [{ debugName: "finalCellBubbleMenuConfig" }] : []));
6443
- this.finalEnableSlashCommands = computed(() => this.enableSlashCommands() ?? this.effectiveConfig().enableSlashCommands, ...(ngDevMode ? [{ debugName: "finalEnableSlashCommands" }] : []));
6609
+ this.finalEnableSlashCommands = computed(() => this.enableSlashCommands() ?? this.effectiveConfig().enableSlashCommands ?? true, ...(ngDevMode ? [{ debugName: "finalEnableSlashCommands" }] : []));
6444
6610
  this.finalSlashCommandsConfig = computed(() => {
6445
6611
  const fromInputComponent = this.customSlashCommands();
6446
6612
  const fromConfigComponent = this.effectiveConfig().customSlashCommands;
@@ -6460,8 +6626,8 @@ class AngularTiptapEditorComponent {
6460
6626
  // Behavior
6461
6627
  this.finalAutofocus = computed(() => this.autofocus() ?? this.effectiveConfig().autofocus, ...(ngDevMode ? [{ debugName: "finalAutofocus" }] : []));
6462
6628
  this.finalMaxCharacters = computed(() => this.maxCharacters() ?? this.effectiveConfig().maxCharacters, ...(ngDevMode ? [{ debugName: "finalMaxCharacters" }] : []));
6463
- this.finalShowCharacterCount = computed(() => this.showCharacterCount() ?? this.effectiveConfig().showCharacterCount, ...(ngDevMode ? [{ debugName: "finalShowCharacterCount" }] : []));
6464
- this.finalShowWordCount = computed(() => this.showWordCount() ?? this.effectiveConfig().showWordCount, ...(ngDevMode ? [{ debugName: "finalShowWordCount" }] : []));
6629
+ this.finalShowCharacterCount = computed(() => this.showCharacterCount() ?? this.effectiveConfig().showCharacterCount ?? true, ...(ngDevMode ? [{ debugName: "finalShowCharacterCount" }] : []));
6630
+ this.finalShowWordCount = computed(() => this.showWordCount() ?? this.effectiveConfig().showWordCount ?? true, ...(ngDevMode ? [{ debugName: "finalShowWordCount" }] : []));
6465
6631
  this.finalLocale = computed(() => this.locale() ?? this.effectiveConfig().locale, ...(ngDevMode ? [{ debugName: "finalLocale" }] : []));
6466
6632
  // Extensions & Options
6467
6633
  this.finalTiptapExtensions = computed(() => this.tiptapExtensions() ?? this.effectiveConfig().tiptapExtensions ?? [], ...(ngDevMode ? [{ debugName: "finalTiptapExtensions" }] : []));
@@ -6472,22 +6638,15 @@ class AngularTiptapEditorComponent {
6472
6638
  this.finalImageUploadConfig = computed(() => {
6473
6639
  const fromInput = this.imageUpload();
6474
6640
  const fromConfig = this.effectiveConfig().imageUpload;
6641
+ const base = ATE_DEFAULT_IMAGE_UPLOAD_CONFIG;
6475
6642
  const merged = {
6476
- maxSize: 5, // Default 5MB
6477
- maxWidth: 1920,
6478
- maxHeight: 1080,
6479
- allowedTypes: ["image/jpeg", "image/png", "image/gif", "image/webp"],
6480
- enableDragDrop: true,
6481
- showPreview: true,
6482
- multiple: false,
6483
- compressImages: true,
6484
- quality: 0.8,
6643
+ ...base,
6485
6644
  ...fromConfig,
6486
6645
  ...fromInput,
6487
6646
  };
6488
6647
  return {
6489
6648
  ...merged,
6490
- maxSize: merged.maxSize * 1024 * 1024, // Convert MB to bytes for internal service
6649
+ maxSize: (merged.maxSize ?? 5) * 1024 * 1024, // Convert MB to bytes for internal service
6491
6650
  };
6492
6651
  }, ...(ngDevMode ? [{ debugName: "finalImageUploadConfig" }] : []));
6493
6652
  this.finalImageUploadHandler = computed(() => this.imageUploadHandler() ?? this.effectiveConfig().imageUpload?.handler, ...(ngDevMode ? [{ debugName: "finalImageUploadHandler" }] : []));
@@ -6619,7 +6778,14 @@ class AngularTiptapEditorComponent {
6619
6778
  }
6620
6779
  initEditor() {
6621
6780
  const extensions = [
6622
- StarterKit,
6781
+ StarterKit.configure({
6782
+ link: {
6783
+ openOnClick: false,
6784
+ HTMLAttributes: {
6785
+ class: "ate-link",
6786
+ },
6787
+ },
6788
+ }),
6623
6789
  TextStyle,
6624
6790
  Color.configure({
6625
6791
  types: ["textStyle"],
@@ -6627,17 +6793,10 @@ class AngularTiptapEditorComponent {
6627
6793
  Placeholder.configure({
6628
6794
  placeholder: this.finalPlaceholder(),
6629
6795
  }),
6630
- Underline,
6631
6796
  Superscript,
6632
6797
  Subscript,
6633
6798
  TextAlign.configure({
6634
- types: ["heading", "paragraph"],
6635
- }),
6636
- Link.configure({
6637
- openOnClick: false,
6638
- HTMLAttributes: {
6639
- class: "ate-link",
6640
- },
6799
+ types: ["heading", "paragraph", "resizableImage"],
6641
6800
  }),
6642
6801
  AteLinkClickBehavior,
6643
6802
  Highlight.configure({
@@ -6871,7 +7030,17 @@ class AngularTiptapEditorComponent {
6871
7030
  }
6872
7031
  onEditorClick(event) {
6873
7032
  const editor = this.editor();
6874
- if (!editor || !this.finalEditable()) {
7033
+ if (!editor) {
7034
+ return;
7035
+ }
7036
+ // In read-only mode, handle clearing of node selection
7037
+ if (!this.finalEditable()) {
7038
+ const target = event.target;
7039
+ const editorElement = this.editorElement()?.nativeElement;
7040
+ if (target === editorElement || target.classList.contains("ate-content")) {
7041
+ // Clear selection to hide bubble menus
7042
+ editor.commands.setTextSelection(0);
7043
+ }
6875
7044
  return;
6876
7045
  }
6877
7046
  // Verify if interaction is on the container element and not on the content
@@ -6931,7 +7100,7 @@ class AngularTiptapEditorComponent {
6931
7100
  }
6932
7101
 
6933
7102
  <!-- Image Bubble Menu -->
6934
- @if (finalEditable() && finalShowImageBubbleMenu() && editor()) {
7103
+ @if (finalShowImageBubbleMenu() && editor()) {
6935
7104
  <ate-image-bubble-menu
6936
7105
  [editor]="editor()!"
6937
7106
  [config]="finalImageBubbleMenuConfig()"
@@ -7006,7 +7175,7 @@ class AngularTiptapEditorComponent {
7006
7175
  </div>
7007
7176
  }
7008
7177
  </div>
7009
- `, 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);--ate-menu-border-radius: var(--ate-border-radius);--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-code-color);--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: 16px;--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%}.ate-editor{border:var(--ate-border-width) solid var(--ate-border-color);border-radius:var(--ate-border-radius);background:var(--ate-background);overflow:visible;transition:border-color .2s ease;position:relative}:host(.floating-toolbar) .ate-editor{overflow:visible}:host(.fill-container) .ate-editor{display:flex;flex-direction:column;height:100%}:host(.fill-container) .ate-content-wrapper{flex:1;min-height:0}:host(.fill-container) .ate-content{flex:1;min-height:0;overflow-y:auto}.ate-editor:focus-within{border-color:var(--ate-focus-color)}.ate-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) .ate-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) .ate-content{cursor:default;-webkit-user-select:text;user-select:text}:host(.is-readonly) .ate-content ::ng-deep .ate-link{cursor:pointer;pointer-events:auto}.ate-content::-webkit-scrollbar{width:var(--ate-scrollbar-width)}.ate-content-wrapper{position:relative;display:flex;flex-direction:column;min-height:0}.ate-content-wrapper .ate-content{flex:1}.ate-content::-webkit-scrollbar-track{background:var(--ate-scrollbar-track)}.ate-content::-webkit-scrollbar-thumb{background:var(--ate-scrollbar-thumb);border:3px solid transparent;background-clip:content-box;border-radius:10px}.ate-content::-webkit-scrollbar-thumb:hover{background:var(--ate-scrollbar-thumb-hover);background-clip:content-box}.ate-content.drag-over{background:var(--ate-drag-background);border:2px dashed var(--ate-drag-border-color)}.character-count{padding:6px 8px;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:var(--ate-image-border-radius);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:var(--ate-image-border-radius);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: AteToolbarComponent, selector: "ate-toolbar", inputs: ["editor", "config", "imageUpload", "floating"] }, { kind: "component", type: AteBubbleMenuComponent, selector: "ate-bubble-menu", inputs: ["config"] }, { kind: "component", type: AteImageBubbleMenuComponent, selector: "ate-image-bubble-menu", inputs: ["config", "imageUpload"] }, { kind: "component", type: AteTableBubbleMenuComponent, selector: "ate-table-bubble-menu", inputs: ["config"] }, { kind: "component", type: AteCellBubbleMenuComponent, selector: "ate-cell-bubble-menu", inputs: ["config"] }, { kind: "component", type: AteSlashCommandsComponent, selector: "ate-slash-commands", inputs: ["editor", "config"] }, { kind: "component", type: AteLinkBubbleMenuComponent, selector: "ate-link-bubble-menu" }, { kind: "component", type: AteColorBubbleMenuComponent, selector: "ate-color-bubble-menu" }, { kind: "component", type: AteEditToggleComponent, selector: "ate-edit-toggle", inputs: ["editable", "translations"], outputs: ["editToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7178
+ `, isInline: true, styles: [":host{--ate-primary: #2563eb;--ate-primary-hover: #153ca9;--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);--ate-menu-border-radius: var(--ate-border-radius);--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: 4px;--ate-menu-gap: 2px;--ate-toolbar-padding: var(--ate-menu-padding);--ate-toolbar-gap: var(--ate-menu-gap);--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-code-color);--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: 16px;--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%}.ate-editor{border:var(--ate-border-width) solid var(--ate-border-color);border-radius:var(--ate-border-radius);background:var(--ate-background);overflow:visible;transition:border-color .2s ease;position:relative}:host(.floating-toolbar) .ate-editor{overflow:visible}:host(.fill-container) .ate-editor{display:flex;flex-direction:column;height:100%}:host(.fill-container) .ate-content-wrapper{flex:1;min-height:0}:host(.fill-container) .ate-content{flex:1;min-height:0;overflow-y:auto}.ate-editor:focus-within{border-color:var(--ate-focus-color)}.ate-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) .ate-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) .ate-content{cursor:default;-webkit-user-select:text;user-select:text}:host(.is-readonly) .ate-content ::ng-deep .ate-link{cursor:pointer;pointer-events:auto}.ate-content::-webkit-scrollbar{width:var(--ate-scrollbar-width)}.ate-content-wrapper{position:relative;display:flex;flex-direction:column;min-height:0}.ate-content-wrapper .ate-content{flex:1}.ate-content::-webkit-scrollbar-track{background:var(--ate-scrollbar-track)}.ate-content::-webkit-scrollbar-thumb{background:var(--ate-scrollbar-thumb);border:3px solid transparent;background-clip:content-box;border-radius:10px}.ate-content::-webkit-scrollbar-thumb:hover{background:var(--ate-scrollbar-thumb-hover);background-clip:content-box}.ate-content.drag-over{background:var(--ate-drag-background);border:2px dashed var(--ate-drag-border-color)}.character-count{padding:6px 8px;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] img{cursor:pointer}:host ::ng-deep .ProseMirror[contenteditable=false] a{cursor:pointer}: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,:host ::ng-deep .resizable-image-container.selected img{border-color:var(--ate-image-selected-color);transition:all .2s ease}:host ::ng-deep .ProseMirror [data-text-align=center],:host ::ng-deep .ProseMirror [data-align=center]{text-align:center}:host ::ng-deep .ProseMirror [data-text-align=right],:host ::ng-deep .ProseMirror [data-align=right]{text-align:right}:host ::ng-deep .ProseMirror [data-text-align=left],:host ::ng-deep .ProseMirror [data-align=left]{text-align:left}:host ::ng-deep .resizable-image-wrapper{display:block;width:100%;margin:.5em 0}:host ::ng-deep .resizable-image-container{position:relative;display:inline-block;max-width:100%}:host ::ng-deep .resize-controls{position:absolute;inset:0;pointer-events:none;z-index:1000;opacity:0;transition:opacity .2s ease}:host:not(.is-readonly):not(.is-disabled) ::ng-deep .resizable-image-container:hover .resize-controls,:host:not(.is-readonly):not(.is-disabled) ::ng-deep body.resizing .resize-controls{opacity:1}:host ::ng-deep .resize-handle{position:absolute;width:.35rem;height:2rem;background:var(--ate-primary);border:2px solid var(--ate-surface);border-radius:var(--ate-border-radius);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-w:hover,:host ::ng-deep .resize-handle-e:hover{background:var(--ate-primary-hover)}:host ::ng-deep .resize-handle-w:active,:host ::ng-deep .resize-handle-e:active{transform:translateY(-50%) scale(.9);background:var(--ate-primary-hover)}:host ::ng-deep .resize-handle-w{top:50%;left:.35rem;transform:translateY(-50%);cursor:w-resize}:host ::ng-deep .resize-handle-e{top:50%;right:.35rem;transform:translateY(-50%);cursor:e-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 .resizable-image-container{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 .resizable-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: AteToolbarComponent, selector: "ate-toolbar", inputs: ["editor", "config", "imageUpload", "floating"] }, { kind: "component", type: AteBubbleMenuComponent, selector: "ate-bubble-menu", inputs: ["config"] }, { kind: "component", type: AteImageBubbleMenuComponent, selector: "ate-image-bubble-menu", inputs: ["config", "imageUpload"] }, { kind: "component", type: AteTableBubbleMenuComponent, selector: "ate-table-bubble-menu", inputs: ["config"] }, { kind: "component", type: AteCellBubbleMenuComponent, selector: "ate-cell-bubble-menu", inputs: ["config"] }, { kind: "component", type: AteSlashCommandsComponent, selector: "ate-slash-commands", inputs: ["editor", "config"] }, { kind: "component", type: AteLinkBubbleMenuComponent, selector: "ate-link-bubble-menu" }, { kind: "component", type: AteColorBubbleMenuComponent, selector: "ate-color-bubble-menu" }, { kind: "component", type: AteEditToggleComponent, selector: "ate-edit-toggle", inputs: ["editable", "translations"], outputs: ["editToggle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7010
7179
  }
7011
7180
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AngularTiptapEditorComponent, decorators: [{
7012
7181
  type: Component,
@@ -7075,7 +7244,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
7075
7244
  }
7076
7245
 
7077
7246
  <!-- Image Bubble Menu -->
7078
- @if (finalEditable() && finalShowImageBubbleMenu() && editor()) {
7247
+ @if (finalShowImageBubbleMenu() && editor()) {
7079
7248
  <ate-image-bubble-menu
7080
7249
  [editor]="editor()!"
7081
7250
  [config]="finalImageBubbleMenuConfig()"
@@ -7150,7 +7319,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
7150
7319
  </div>
7151
7320
  }
7152
7321
  </div>
7153
- `, 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);--ate-menu-border-radius: var(--ate-border-radius);--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-code-color);--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: 16px;--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%}.ate-editor{border:var(--ate-border-width) solid var(--ate-border-color);border-radius:var(--ate-border-radius);background:var(--ate-background);overflow:visible;transition:border-color .2s ease;position:relative}:host(.floating-toolbar) .ate-editor{overflow:visible}:host(.fill-container) .ate-editor{display:flex;flex-direction:column;height:100%}:host(.fill-container) .ate-content-wrapper{flex:1;min-height:0}:host(.fill-container) .ate-content{flex:1;min-height:0;overflow-y:auto}.ate-editor:focus-within{border-color:var(--ate-focus-color)}.ate-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) .ate-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) .ate-content{cursor:default;-webkit-user-select:text;user-select:text}:host(.is-readonly) .ate-content ::ng-deep .ate-link{cursor:pointer;pointer-events:auto}.ate-content::-webkit-scrollbar{width:var(--ate-scrollbar-width)}.ate-content-wrapper{position:relative;display:flex;flex-direction:column;min-height:0}.ate-content-wrapper .ate-content{flex:1}.ate-content::-webkit-scrollbar-track{background:var(--ate-scrollbar-track)}.ate-content::-webkit-scrollbar-thumb{background:var(--ate-scrollbar-thumb);border:3px solid transparent;background-clip:content-box;border-radius:10px}.ate-content::-webkit-scrollbar-thumb:hover{background:var(--ate-scrollbar-thumb-hover);background-clip:content-box}.ate-content.drag-over{background:var(--ate-drag-background);border:2px dashed var(--ate-drag-border-color)}.character-count{padding:6px 8px;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:var(--ate-image-border-radius);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:var(--ate-image-border-radius);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"] }]
7322
+ `, styles: [":host{--ate-primary: #2563eb;--ate-primary-hover: #153ca9;--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);--ate-menu-border-radius: var(--ate-border-radius);--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: 4px;--ate-menu-gap: 2px;--ate-toolbar-padding: var(--ate-menu-padding);--ate-toolbar-gap: var(--ate-menu-gap);--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-code-color);--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: 16px;--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%}.ate-editor{border:var(--ate-border-width) solid var(--ate-border-color);border-radius:var(--ate-border-radius);background:var(--ate-background);overflow:visible;transition:border-color .2s ease;position:relative}:host(.floating-toolbar) .ate-editor{overflow:visible}:host(.fill-container) .ate-editor{display:flex;flex-direction:column;height:100%}:host(.fill-container) .ate-content-wrapper{flex:1;min-height:0}:host(.fill-container) .ate-content{flex:1;min-height:0;overflow-y:auto}.ate-editor:focus-within{border-color:var(--ate-focus-color)}.ate-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) .ate-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) .ate-content{cursor:default;-webkit-user-select:text;user-select:text}:host(.is-readonly) .ate-content ::ng-deep .ate-link{cursor:pointer;pointer-events:auto}.ate-content::-webkit-scrollbar{width:var(--ate-scrollbar-width)}.ate-content-wrapper{position:relative;display:flex;flex-direction:column;min-height:0}.ate-content-wrapper .ate-content{flex:1}.ate-content::-webkit-scrollbar-track{background:var(--ate-scrollbar-track)}.ate-content::-webkit-scrollbar-thumb{background:var(--ate-scrollbar-thumb);border:3px solid transparent;background-clip:content-box;border-radius:10px}.ate-content::-webkit-scrollbar-thumb:hover{background:var(--ate-scrollbar-thumb-hover);background-clip:content-box}.ate-content.drag-over{background:var(--ate-drag-background);border:2px dashed var(--ate-drag-border-color)}.character-count{padding:6px 8px;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] img{cursor:pointer}:host ::ng-deep .ProseMirror[contenteditable=false] a{cursor:pointer}: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,:host ::ng-deep .resizable-image-container.selected img{border-color:var(--ate-image-selected-color);transition:all .2s ease}:host ::ng-deep .ProseMirror [data-text-align=center],:host ::ng-deep .ProseMirror [data-align=center]{text-align:center}:host ::ng-deep .ProseMirror [data-text-align=right],:host ::ng-deep .ProseMirror [data-align=right]{text-align:right}:host ::ng-deep .ProseMirror [data-text-align=left],:host ::ng-deep .ProseMirror [data-align=left]{text-align:left}:host ::ng-deep .resizable-image-wrapper{display:block;width:100%;margin:.5em 0}:host ::ng-deep .resizable-image-container{position:relative;display:inline-block;max-width:100%}:host ::ng-deep .resize-controls{position:absolute;inset:0;pointer-events:none;z-index:1000;opacity:0;transition:opacity .2s ease}:host:not(.is-readonly):not(.is-disabled) ::ng-deep .resizable-image-container:hover .resize-controls,:host:not(.is-readonly):not(.is-disabled) ::ng-deep body.resizing .resize-controls{opacity:1}:host ::ng-deep .resize-handle{position:absolute;width:.35rem;height:2rem;background:var(--ate-primary);border:2px solid var(--ate-surface);border-radius:var(--ate-border-radius);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-w:hover,:host ::ng-deep .resize-handle-e:hover{background:var(--ate-primary-hover)}:host ::ng-deep .resize-handle-w:active,:host ::ng-deep .resize-handle-e:active{transform:translateY(-50%) scale(.9);background:var(--ate-primary-hover)}:host ::ng-deep .resize-handle-w{top:50%;left:.35rem;transform:translateY(-50%);cursor:w-resize}:host ::ng-deep .resize-handle-e{top:50%;right:.35rem;transform:translateY(-50%);cursor:e-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 .resizable-image-container{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 .resizable-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"] }]
7154
7323
  }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], minHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "minHeight", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], maxHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxHeight", required: false }] }], fillContainer: [{ type: i0.Input, args: [{ isSignal: true, alias: "fillContainer", required: false }] }], showToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToolbar", required: false }] }], showFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFooter", required: false }] }], showCharacterCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCharacterCount", required: false }] }], showWordCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "showWordCount", required: false }] }], maxCharacters: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxCharacters", required: false }] }], enableOfficePaste: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableOfficePaste", required: false }] }], enableSlashCommands: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableSlashCommands", required: false }] }], slashCommands: [{ type: i0.Input, args: [{ isSignal: true, alias: "slashCommands", required: false }] }], customSlashCommands: [{ type: i0.Input, args: [{ isSignal: true, alias: "customSlashCommands", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], seamless: [{ type: i0.Input, args: [{ isSignal: true, alias: "seamless", required: false }] }], floatingToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "floatingToolbar", required: false }] }], showEditToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showEditToggle", required: false }] }], spellcheck: [{ type: i0.Input, args: [{ isSignal: true, alias: "spellcheck", required: false }] }], tiptapExtensions: [{ type: i0.Input, args: [{ isSignal: true, alias: "tiptapExtensions", required: false }] }], tiptapOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "tiptapOptions", required: false }] }], showBubbleMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "showBubbleMenu", required: false }] }], bubbleMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "bubbleMenu", required: false }] }], showImageBubbleMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "showImageBubbleMenu", required: false }] }], imageBubbleMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageBubbleMenu", required: false }] }], toolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbar", required: false }] }], showTableBubbleMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTableBubbleMenu", required: false }] }], tableBubbleMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "tableBubbleMenu", required: false }] }], showCellBubbleMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCellBubbleMenu", required: false }] }], cellBubbleMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "cellBubbleMenu", required: false }] }], stateCalculators: [{ type: i0.Input, args: [{ isSignal: true, alias: "stateCalculators", required: false }] }], imageUpload: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageUpload", required: false }] }], imageUploadHandler: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageUploadHandler", required: false }] }], contentChange: [{ type: i0.Output, args: ["contentChange"] }], editorCreated: [{ type: i0.Output, args: ["editorCreated"] }], editorUpdate: [{ type: i0.Output, args: ["editorUpdate"] }], editorFocus: [{ type: i0.Output, args: ["editorFocus"] }], editorBlur: [{ type: i0.Output, args: ["editorBlur"] }], editableChange: [{ type: i0.Output, args: ["editableChange"] }], editorElement: [{ type: i0.ViewChild, args: ["editorElement", { isSignal: true }] }] } });
7155
7324
 
7156
7325
  /**
@@ -7219,55 +7388,6 @@ const ATE_TOOLBAR_KEYS = [
7219
7388
  "separator",
7220
7389
  ];
7221
7390
 
7222
- /**
7223
- * Clés des options du menu bulle de texte
7224
- */
7225
- const ATE_BUBBLE_MENU_KEYS = [
7226
- "bold",
7227
- "italic",
7228
- "underline",
7229
- "strike",
7230
- "code",
7231
- "superscript",
7232
- "subscript",
7233
- "highlight",
7234
- "highlightPicker",
7235
- "textColor",
7236
- "link",
7237
- "separator",
7238
- ];
7239
- /**
7240
- * Clés des options du menu bulle d'image
7241
- */
7242
- const ATE_IMAGE_BUBBLE_MENU_KEYS = [
7243
- "changeImage",
7244
- "resizeSmall",
7245
- "resizeMedium",
7246
- "resizeLarge",
7247
- "resizeOriginal",
7248
- "deleteImage",
7249
- "separator",
7250
- ];
7251
- /**
7252
- * Clés des options du menu de table
7253
- */
7254
- const ATE_TABLE_BUBBLE_MENU_KEYS = [
7255
- "addRowBefore",
7256
- "addRowAfter",
7257
- "deleteRow",
7258
- "addColumnBefore",
7259
- "addColumnAfter",
7260
- "deleteColumn",
7261
- "deleteTable",
7262
- "toggleHeaderRow",
7263
- "toggleHeaderColumn",
7264
- "separator",
7265
- ];
7266
- /**
7267
- * Clés des options du menu de cellule
7268
- */
7269
- const ATE_CELL_BUBBLE_MENU_KEYS = ["mergeCells", "splitCell"];
7270
-
7271
7391
  /*
7272
7392
  * Public API Surface of tiptap-editor
7273
7393
  */
@@ -7277,5 +7397,5 @@ const ATE_CELL_BUBBLE_MENU_KEYS = ["mergeCells", "splitCell"];
7277
7397
  * Generated bundle index. Do not edit.
7278
7398
  */
7279
7399
 
7280
- export { ATE_BUBBLE_MENU_KEYS, ATE_CELL_BUBBLE_MENU_KEYS, ATE_DEFAULT_BUBBLE_MENU_CONFIG, ATE_DEFAULT_CELL_MENU_CONFIG, ATE_DEFAULT_CONFIG, ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ATE_DEFAULT_SLASH_COMMANDS_CONFIG, ATE_DEFAULT_TABLE_MENU_CONFIG, ATE_DEFAULT_TOOLBAR_CONFIG, ATE_GLOBAL_CONFIG, ATE_IMAGE_BUBBLE_MENU_KEYS, ATE_INITIAL_EDITOR_STATE, ATE_SLASH_COMMAND_KEYS, ATE_TABLE_BUBBLE_MENU_KEYS, ATE_TOOLBAR_KEYS, AngularTiptapEditorComponent, AteAngularNodeView, AteColorPickerService, AteDiscoveryCalculator, AteEditorCommandsService, AteI18nService, AteImageCalculator, AteImageService, AteLinkService, AteMarksCalculator, AteNodeViewRenderer, AteNoopValueAccessorDirective, AteSelectionCalculator, AteStructureCalculator, AteTableCalculator, createAngularComponentExtension, createDefaultSlashCommands, filterSlashCommands, provideAteEditor, registerAngularComponent };
7400
+ export { ATE_BUBBLE_MENU_KEYS, ATE_CELL_BUBBLE_MENU_KEYS, ATE_DEFAULT_BUBBLE_MENU_CONFIG, ATE_DEFAULT_CELL_MENU_CONFIG, ATE_DEFAULT_CONFIG, ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ATE_DEFAULT_IMAGE_UPLOAD_CONFIG, ATE_DEFAULT_SLASH_COMMANDS_CONFIG, ATE_DEFAULT_TABLE_MENU_CONFIG, ATE_DEFAULT_TOOLBAR_CONFIG, ATE_GLOBAL_CONFIG, ATE_IMAGE_BUBBLE_MENU_KEYS, ATE_INITIAL_EDITOR_STATE, ATE_SLASH_COMMAND_KEYS, ATE_TABLE_BUBBLE_MENU_KEYS, ATE_TOOLBAR_KEYS, AngularTiptapEditorComponent, AteAngularNodeView, AteColorPickerService, AteDiscoveryCalculator, AteEditorCommandsService, AteI18nService, AteImageCalculator, AteImageService, AteLinkService, AteMarksCalculator, AteNodeViewRenderer, AteNoopValueAccessorDirective, AteSelectionCalculator, AteStructureCalculator, AteTableCalculator, createAngularComponentExtension, createDefaultSlashCommands, filterSlashCommands, provideAteEditor, registerAngularComponent };
7281
7401
  //# sourceMappingURL=flogeez-angular-tiptap-editor.mjs.map