@flogeez/angular-tiptap-editor 3.0.1 → 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.
@@ -119,6 +119,13 @@ const AteResizableImage = Node$1.create({
119
119
  },
120
120
  addNodeView() {
121
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
+ }
122
129
  const container = document.createElement("div");
123
130
  container.className = "resizable-image-container";
124
131
  container.style.position = "relative";
@@ -128,20 +135,32 @@ const AteResizableImage = Node$1.create({
128
135
  img.alt = node.attrs["alt"] || "";
129
136
  img.title = node.attrs["title"] || "";
130
137
  img.className = "ate-image";
138
+ img.style.display = "inline-block"; // Ensure it respects container text-align
131
139
  if (node.attrs["width"]) {
132
140
  img.width = node.attrs["width"];
133
141
  }
134
142
  if (node.attrs["height"]) {
135
143
  img.height = node.attrs["height"];
136
144
  }
137
- img.parentNode?.insertBefore(container, img);
145
+ wrapper.appendChild(container);
138
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
+ });
139
159
  // Add modern resize controls
140
160
  const resizeControls = document.createElement("div");
141
161
  resizeControls.className = "resize-controls";
142
- resizeControls.style.display = "none";
143
- // Create 8 handles for full resizing capability
144
- 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"];
145
164
  handles.forEach(direction => {
146
165
  const handle = document.createElement("div");
147
166
  handle.className = `resize-handle resize-handle-${direction}`;
@@ -153,7 +172,6 @@ const AteResizableImage = Node$1.create({
153
172
  // Variables for resizing
154
173
  let isResizing = false;
155
174
  let startX = 0;
156
- let startY = 0;
157
175
  let startWidth = 0;
158
176
  let startHeight = 0;
159
177
  let aspectRatio = 1;
@@ -167,7 +185,6 @@ const AteResizableImage = Node$1.create({
167
185
  e.stopPropagation();
168
186
  isResizing = true;
169
187
  startX = e.clientX;
170
- startY = e.clientY;
171
188
  // Use current image dimensions instead of initial ones
172
189
  startWidth =
173
190
  parseInt(img.getAttribute("width") || "0") || node.attrs["width"] || img.naturalWidth;
@@ -180,7 +197,6 @@ const AteResizableImage = Node$1.create({
180
197
  return;
181
198
  }
182
199
  const deltaX = e.clientX - startX;
183
- const deltaY = e.clientY - startY;
184
200
  let newWidth = startWidth;
185
201
  let newHeight = startHeight;
186
202
  // Resize according to direction
@@ -193,30 +209,6 @@ const AteResizableImage = Node$1.create({
193
209
  newWidth = startWidth - deltaX;
194
210
  newHeight = newWidth / aspectRatio;
195
211
  break;
196
- case "s":
197
- newHeight = startHeight + deltaY;
198
- newWidth = newHeight * aspectRatio;
199
- break;
200
- case "n":
201
- newHeight = startHeight - deltaY;
202
- newWidth = newHeight * aspectRatio;
203
- break;
204
- case "se":
205
- newWidth = startWidth + deltaX;
206
- newHeight = startHeight + deltaY;
207
- break;
208
- case "sw":
209
- newWidth = startWidth - deltaX;
210
- newHeight = startHeight + deltaY;
211
- break;
212
- case "ne":
213
- newWidth = startWidth + deltaX;
214
- newHeight = startHeight - deltaY;
215
- break;
216
- case "nw":
217
- newWidth = startWidth - deltaX;
218
- newHeight = startHeight - deltaY;
219
- break;
220
212
  }
221
213
  // Limits
222
214
  newWidth = Math.max(50, Math.min(2000, newWidth));
@@ -257,17 +249,17 @@ const AteResizableImage = Node$1.create({
257
249
  });
258
250
  // Proper selection management via ProseMirror lifecycle
259
251
  const selectNode = () => {
260
- resizeControls.style.display = "block";
252
+ wrapper.classList.add("selected");
261
253
  container.classList.add("selected");
262
254
  img.classList.add("selected");
263
255
  };
264
256
  const deselectNode = () => {
265
- resizeControls.style.display = "none";
257
+ wrapper.classList.remove("selected");
266
258
  container.classList.remove("selected");
267
259
  img.classList.remove("selected");
268
260
  };
269
261
  return {
270
- dom: container,
262
+ dom: wrapper,
271
263
  selectNode,
272
264
  deselectNode,
273
265
  update: updatedNode => {
@@ -283,8 +275,21 @@ const AteResizableImage = Node$1.create({
283
275
  if (updatedNode.attrs["height"]) {
284
276
  img.height = updatedNode.attrs["height"];
285
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
+ }
286
286
  return true;
287
287
  },
288
+ stopEvent: (event) => {
289
+ const target = event.target;
290
+ return !!target.closest(".resize-controls");
291
+ },
292
+ ignoreMutation: () => true,
288
293
  };
289
294
  };
290
295
  },
@@ -767,33 +772,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
767
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"] }] } });
768
773
 
769
774
  class AteSeparatorComponent {
770
- constructor() {
771
- this.orientation = input("vertical", ...(ngDevMode ? [{ debugName: "orientation" }] : []));
772
- this.size = input("medium", ...(ngDevMode ? [{ debugName: "size" }] : []));
773
- }
774
775
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteSeparatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
775
- 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: `
776
- <div
777
- class="ate-separator"
778
- [class.vertical]="orientation() === 'vertical'"
779
- [class.horizontal]="orientation() === 'horizontal'"
780
- [class.small]="size() === 'small'"
781
- [class.medium]="size() === 'medium'"
782
- [class.large]="size() === 'large'"></div>
783
- `, 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 }); }
784
777
  }
785
778
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteSeparatorComponent, decorators: [{
786
779
  type: Component,
787
- args: [{ selector: "ate-separator", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
788
- <div
789
- class="ate-separator"
790
- [class.vertical]="orientation() === 'vertical'"
791
- [class.horizontal]="orientation() === 'horizontal'"
792
- [class.small]="size() === 'small'"
793
- [class.medium]="size() === 'medium'"
794
- [class.large]="size() === 'large'"></div>
795
- `, 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"] }]
796
- }], 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
+ }] });
797
782
 
798
783
  const ENGLISH_TRANSLATIONS = {
799
784
  toolbar: {
@@ -925,11 +910,15 @@ const ENGLISH_TRANSLATIONS = {
925
910
  invalidFileType: "Invalid file type",
926
911
  dragDropText: "Drag and drop images here",
927
912
  changeImage: "Change Image",
913
+ downloadImage: "Download Image",
928
914
  deleteImage: "Delete Image",
929
915
  resizeSmall: "Small",
930
916
  resizeMedium: "Medium",
931
917
  resizeLarge: "Large",
932
918
  resizeOriginal: "Original",
919
+ alignLeft: "Align Left",
920
+ alignCenter: "Align Center",
921
+ alignRight: "Align Right",
933
922
  resizing: "Resizing...",
934
923
  compressing: "Compressing...",
935
924
  compressionError: "Error during compression",
@@ -1092,11 +1081,15 @@ const FRENCH_TRANSLATIONS = {
1092
1081
  invalidFileType: "Type de fichier invalide",
1093
1082
  dragDropText: "Glissez et déposez des images ici",
1094
1083
  changeImage: "Changer l'image",
1084
+ downloadImage: "Télécharger l'image",
1095
1085
  deleteImage: "Supprimer l'image",
1096
1086
  resizeSmall: "Petit",
1097
1087
  resizeMedium: "Moyen",
1098
1088
  resizeLarge: "Grand",
1099
1089
  resizeOriginal: "Original",
1090
+ alignLeft: "Aligner à gauche",
1091
+ alignCenter: "Aligner au centre",
1092
+ alignRight: "Aligner à droite",
1100
1093
  resizing: "Redimensionnement...",
1101
1094
  compressing: "Compression...",
1102
1095
  compressionError: "Erreur lors de la compression",
@@ -1328,6 +1321,46 @@ class AteImageService {
1328
1321
  this.clearSelection();
1329
1322
  }
1330
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
+ }
1331
1364
  updateSelectedImage(attributes) {
1332
1365
  const current = this.selectedImage();
1333
1366
  if (current) {
@@ -2404,6 +2437,9 @@ class AteEditorCommandsService {
2404
2437
  throw error;
2405
2438
  }
2406
2439
  }
2440
+ downloadImage(editor) {
2441
+ this.imageService.downloadImage(editor);
2442
+ }
2407
2443
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteEditorCommandsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2408
2444
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteEditorCommandsService }); }
2409
2445
  }
@@ -2794,7 +2830,7 @@ class AteToolbarComponent {
2794
2830
  }
2795
2831
  }
2796
2832
  </div>
2797
- `, 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 }); }
2798
2834
  }
2799
2835
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteToolbarComponent, decorators: [{
2800
2836
  type: Component,
@@ -3047,9 +3083,141 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3047
3083
  }
3048
3084
  }
3049
3085
  </div>
3050
- `, 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"] }]
3051
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 }] }] } });
3052
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
+
3053
3221
  /**
3054
3222
  * Base abstract class for all Bubble Menus (Text, Image, Table, Cell).
3055
3223
  * Handles common logic for Tippy.js initialization, positioning, and visibility.
@@ -3259,31 +3427,9 @@ class AteBubbleMenuComponent extends AteBaseBubbleMenu {
3259
3427
  this.onMouseDown = () => {
3260
3428
  this.hideTippy();
3261
3429
  };
3262
- this.config = input({
3263
- bold: true,
3264
- italic: true,
3265
- underline: true,
3266
- strike: true,
3267
- code: true,
3268
- superscript: false,
3269
- subscript: false,
3270
- highlight: true,
3271
- textColor: false,
3272
- link: true,
3273
- separator: true,
3274
- }, ...(ngDevMode ? [{ debugName: "config" }] : []));
3430
+ this.config = input(ATE_DEFAULT_BUBBLE_MENU_CONFIG, ...(ngDevMode ? [{ debugName: "config" }] : []));
3275
3431
  this.bubbleMenuConfig = computed(() => ({
3276
- bold: true,
3277
- italic: true,
3278
- underline: true,
3279
- strike: true,
3280
- code: true,
3281
- superscript: false,
3282
- subscript: false,
3283
- highlight: true,
3284
- textColor: false,
3285
- link: true,
3286
- separator: true,
3432
+ ...ATE_DEFAULT_BUBBLE_MENU_CONFIG,
3287
3433
  ...this.config(),
3288
3434
  }), ...(ngDevMode ? [{ debugName: "bubbleMenuConfig" }] : []));
3289
3435
  }
@@ -3541,41 +3687,93 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3541
3687
  }]
3542
3688
  }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }] } });
3543
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
+
3544
3743
  class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3545
3744
  constructor() {
3546
3745
  super(...arguments);
3547
3746
  this.t = this.i18nService.imageUpload;
3548
3747
  this.imageService = inject(AteImageService);
3549
- this.config = input({
3550
- changeImage: true,
3551
- resizeSmall: true,
3552
- resizeMedium: true,
3553
- resizeLarge: true,
3554
- resizeOriginal: true,
3555
- deleteImage: true,
3556
- separator: true,
3557
- }, ...(ngDevMode ? [{ debugName: "config" }] : []));
3748
+ this.config = input(ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ...(ngDevMode ? [{ debugName: "config" }] : []));
3558
3749
  this.imageUpload = input({}, ...(ngDevMode ? [{ debugName: "imageUpload" }] : []));
3559
- this.imageBubbleMenuConfig = computed(() => ({
3560
- changeImage: this.config().changeImage ?? true,
3561
- resizeSmall: this.config().resizeSmall ?? true,
3562
- resizeMedium: this.config().resizeMedium ?? true,
3563
- resizeLarge: this.config().resizeLarge ?? true,
3564
- resizeOriginal: this.config().resizeOriginal ?? true,
3565
- deleteImage: this.config().deleteImage ?? true,
3566
- separator: this.config().separator ?? true,
3567
- }), ...(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" }] : []));
3568
3761
  this.hasResizeButtons = computed(() => {
3569
3762
  const c = this.imageBubbleMenuConfig();
3570
3763
  return c.resizeSmall || c.resizeMedium || c.resizeLarge || c.resizeOriginal;
3571
3764
  }, ...(ngDevMode ? [{ debugName: "hasResizeButtons" }] : []));
3572
3765
  }
3573
3766
  shouldShow() {
3574
- const { nodes, isEditable, isFocused } = this.state();
3767
+ const { nodes, isEditable, isFocused, selection } = this.state();
3575
3768
  if (this.editorCommands.linkEditMode() || this.editorCommands.colorEditMode()) {
3576
3769
  return false;
3577
3770
  }
3578
- 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;
3579
3777
  }
3580
3778
  getSelectionRect() {
3581
3779
  const ed = this.editor();
@@ -3613,6 +3811,9 @@ class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3613
3811
  case "changeImage":
3614
3812
  this.changeImage();
3615
3813
  break;
3814
+ case "downloadImage":
3815
+ this.editorCommands.downloadImage(editor);
3816
+ break;
3616
3817
  case "resizeSmall":
3617
3818
  this.imageService.resizeImageToSmall(editor);
3618
3819
  break;
@@ -3628,6 +3829,15 @@ class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3628
3829
  case "deleteImage":
3629
3830
  this.deleteImage();
3630
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;
3631
3841
  }
3632
3842
  }
3633
3843
  async changeImage() {
@@ -3652,46 +3862,81 @@ class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3652
3862
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteImageBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3653
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: `
3654
3864
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
3655
- @if (imageBubbleMenuConfig().changeImage) {
3865
+ @if (imageBubbleMenuConfig().changeImage && editor().isEditable) {
3656
3866
  <ate-button
3657
3867
  icon="drive_file_rename_outline"
3658
3868
  [title]="t().changeImage"
3659
3869
  (buttonClick)="onCommand('changeImage', $event)"></ate-button>
3660
3870
  }
3661
- @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) {
3662
3878
  <ate-separator />
3663
3879
  }
3664
- @if (imageBubbleMenuConfig().resizeSmall) {
3880
+ @if (imageBubbleMenuConfig().resizeSmall && editor().isEditable) {
3665
3881
  <ate-button
3666
3882
  icon="crop_square"
3667
3883
  iconSize="small"
3668
3884
  [title]="t().resizeSmall"
3669
3885
  (buttonClick)="onCommand('resizeSmall', $event)"></ate-button>
3670
3886
  }
3671
- @if (imageBubbleMenuConfig().resizeMedium) {
3887
+ @if (imageBubbleMenuConfig().resizeMedium && editor().isEditable) {
3672
3888
  <ate-button
3673
3889
  icon="crop_square"
3674
3890
  iconSize="medium"
3675
3891
  [title]="t().resizeMedium"
3676
3892
  (buttonClick)="onCommand('resizeMedium', $event)"></ate-button>
3677
3893
  }
3678
- @if (imageBubbleMenuConfig().resizeLarge) {
3894
+ @if (imageBubbleMenuConfig().resizeLarge && editor().isEditable) {
3679
3895
  <ate-button
3680
3896
  icon="crop_square"
3681
3897
  iconSize="large"
3682
3898
  [title]="t().resizeLarge"
3683
3899
  (buttonClick)="onCommand('resizeLarge', $event)"></ate-button>
3684
3900
  }
3685
- @if (imageBubbleMenuConfig().resizeOriginal) {
3901
+ @if (imageBubbleMenuConfig().resizeOriginal && editor().isEditable) {
3686
3902
  <ate-button
3687
3903
  icon="photo_size_select_actual"
3688
3904
  [title]="t().resizeOriginal"
3689
3905
  (buttonClick)="onCommand('resizeOriginal', $event)"></ate-button>
3690
3906
  }
3691
- @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
+ ) {
3692
3937
  <ate-separator />
3693
3938
  }
3694
- @if (imageBubbleMenuConfig().deleteImage) {
3939
+ @if (imageBubbleMenuConfig().deleteImage && editor().isEditable) {
3695
3940
  <ate-button
3696
3941
  icon="delete"
3697
3942
  [title]="t().deleteImage"
@@ -3699,7 +3944,7 @@ class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3699
3944
  (buttonClick)="onCommand('deleteImage', $event)"></ate-button>
3700
3945
  }
3701
3946
  </div>
3702
- `, 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 }); }
3703
3948
  }
3704
3949
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteImageBubbleMenuComponent, decorators: [{
3705
3950
  type: Component,
@@ -3710,46 +3955,81 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3710
3955
  imports: [AteButtonComponent, AteSeparatorComponent],
3711
3956
  template: `
3712
3957
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
3713
- @if (imageBubbleMenuConfig().changeImage) {
3958
+ @if (imageBubbleMenuConfig().changeImage && editor().isEditable) {
3714
3959
  <ate-button
3715
3960
  icon="drive_file_rename_outline"
3716
3961
  [title]="t().changeImage"
3717
3962
  (buttonClick)="onCommand('changeImage', $event)"></ate-button>
3718
3963
  }
3719
- @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) {
3720
3971
  <ate-separator />
3721
3972
  }
3722
- @if (imageBubbleMenuConfig().resizeSmall) {
3973
+ @if (imageBubbleMenuConfig().resizeSmall && editor().isEditable) {
3723
3974
  <ate-button
3724
3975
  icon="crop_square"
3725
3976
  iconSize="small"
3726
3977
  [title]="t().resizeSmall"
3727
3978
  (buttonClick)="onCommand('resizeSmall', $event)"></ate-button>
3728
3979
  }
3729
- @if (imageBubbleMenuConfig().resizeMedium) {
3980
+ @if (imageBubbleMenuConfig().resizeMedium && editor().isEditable) {
3730
3981
  <ate-button
3731
3982
  icon="crop_square"
3732
3983
  iconSize="medium"
3733
3984
  [title]="t().resizeMedium"
3734
3985
  (buttonClick)="onCommand('resizeMedium', $event)"></ate-button>
3735
3986
  }
3736
- @if (imageBubbleMenuConfig().resizeLarge) {
3987
+ @if (imageBubbleMenuConfig().resizeLarge && editor().isEditable) {
3737
3988
  <ate-button
3738
3989
  icon="crop_square"
3739
3990
  iconSize="large"
3740
3991
  [title]="t().resizeLarge"
3741
3992
  (buttonClick)="onCommand('resizeLarge', $event)"></ate-button>
3742
3993
  }
3743
- @if (imageBubbleMenuConfig().resizeOriginal) {
3994
+ @if (imageBubbleMenuConfig().resizeOriginal && editor().isEditable) {
3744
3995
  <ate-button
3745
3996
  icon="photo_size_select_actual"
3746
3997
  [title]="t().resizeOriginal"
3747
3998
  (buttonClick)="onCommand('resizeOriginal', $event)"></ate-button>
3748
3999
  }
3749
- @if (imageBubbleMenuConfig().separator && imageBubbleMenuConfig().deleteImage) {
4000
+ @if (imageBubbleMenuConfig().separator && hasAlignmentButtons() && editor().isEditable) {
3750
4001
  <ate-separator />
3751
4002
  }
3752
- @if (imageBubbleMenuConfig().deleteImage) {
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
+ ) {
4030
+ <ate-separator />
4031
+ }
4032
+ @if (imageBubbleMenuConfig().deleteImage && editor().isEditable) {
3753
4033
  <ate-button
3754
4034
  icon="delete"
3755
4035
  [title]="t().deleteImage"
@@ -3766,18 +4046,15 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3766
4046
  super(...arguments);
3767
4047
  // Alias for template
3768
4048
  this.t = this.i18nService.table;
3769
- this.config = input({
3770
- addRowBefore: true,
3771
- addRowAfter: true,
3772
- deleteRow: true,
3773
- addColumnBefore: true,
3774
- addColumnAfter: true,
3775
- deleteColumn: true,
3776
- deleteTable: true,
3777
- toggleHeaderRow: true,
3778
- toggleHeaderColumn: true,
3779
- separator: true,
3780
- }, ...(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" }] : []));
3781
4058
  }
3782
4059
  shouldShow() {
3783
4060
  const { selection, nodes, isEditable, isFocused } = this.state();
@@ -3839,21 +4116,21 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3839
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: `
3840
4117
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
3841
4118
  <!-- Row actions -->
3842
- @if (config().addRowBefore !== false) {
4119
+ @if (tableBubbleMenuConfig().addRowBefore !== false) {
3843
4120
  <ate-button
3844
4121
  icon="add_row_above"
3845
4122
  [title]="t().addRowBefore"
3846
4123
  [disabled]="!state().can.addRowBefore"
3847
4124
  (buttonClick)="onCommand('addRowBefore', $event)"></ate-button>
3848
4125
  }
3849
- @if (config().addRowAfter !== false) {
4126
+ @if (tableBubbleMenuConfig().addRowAfter !== false) {
3850
4127
  <ate-button
3851
4128
  icon="add_row_below"
3852
4129
  [title]="t().addRowAfter"
3853
4130
  [disabled]="!state().can.addRowAfter"
3854
4131
  (buttonClick)="onCommand('addRowAfter', $event)"></ate-button>
3855
4132
  }
3856
- @if (config().deleteRow !== false) {
4133
+ @if (tableBubbleMenuConfig().deleteRow !== false) {
3857
4134
  <ate-button
3858
4135
  icon="delete"
3859
4136
  [title]="t().deleteRow"
@@ -3861,26 +4138,26 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3861
4138
  [disabled]="!state().can.deleteRow"
3862
4139
  (buttonClick)="onCommand('deleteRow', $event)"></ate-button>
3863
4140
  }
3864
- @if (config().separator !== false) {
4141
+ @if (tableBubbleMenuConfig().separator !== false) {
3865
4142
  <ate-separator />
3866
4143
  }
3867
4144
 
3868
4145
  <!-- Column actions -->
3869
- @if (config().addColumnBefore !== false) {
4146
+ @if (tableBubbleMenuConfig().addColumnBefore !== false) {
3870
4147
  <ate-button
3871
4148
  icon="add_column_left"
3872
4149
  [title]="t().addColumnBefore"
3873
4150
  [disabled]="!state().can.addColumnBefore"
3874
4151
  (buttonClick)="onCommand('addColumnBefore', $event)"></ate-button>
3875
4152
  }
3876
- @if (config().addColumnAfter !== false) {
4153
+ @if (tableBubbleMenuConfig().addColumnAfter !== false) {
3877
4154
  <ate-button
3878
4155
  icon="add_column_right"
3879
4156
  [title]="t().addColumnAfter"
3880
4157
  [disabled]="!state().can.addColumnAfter"
3881
4158
  (buttonClick)="onCommand('addColumnAfter', $event)"></ate-button>
3882
4159
  }
3883
- @if (config().deleteColumn !== false) {
4160
+ @if (tableBubbleMenuConfig().deleteColumn !== false) {
3884
4161
  <ate-button
3885
4162
  icon="delete"
3886
4163
  [title]="t().deleteColumn"
@@ -3888,12 +4165,12 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3888
4165
  [disabled]="!state().can.deleteColumn"
3889
4166
  (buttonClick)="onCommand('deleteColumn', $event)"></ate-button>
3890
4167
  }
3891
- @if (config().separator !== false) {
4168
+ @if (tableBubbleMenuConfig().separator !== false) {
3892
4169
  <ate-separator />
3893
4170
  }
3894
4171
 
3895
4172
  <!-- Cell actions -->
3896
- @if (config().toggleHeaderRow !== false) {
4173
+ @if (tableBubbleMenuConfig().toggleHeaderRow !== false) {
3897
4174
  <ate-button
3898
4175
  icon="toolbar"
3899
4176
  [title]="t().toggleHeaderRow"
@@ -3901,7 +4178,7 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3901
4178
  [disabled]="!state().can.toggleHeaderRow"
3902
4179
  (buttonClick)="onCommand('toggleHeaderRow', $event)"></ate-button>
3903
4180
  }
3904
- @if (config().toggleHeaderColumn !== false) {
4181
+ @if (tableBubbleMenuConfig().toggleHeaderColumn !== false) {
3905
4182
  <ate-button
3906
4183
  icon="dock_to_right"
3907
4184
  [title]="t().toggleHeaderColumn"
@@ -3909,12 +4186,14 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3909
4186
  [disabled]="!state().can.toggleHeaderColumn"
3910
4187
  (buttonClick)="onCommand('toggleHeaderColumn', $event)"></ate-button>
3911
4188
  }
3912
- @if (config().separator !== false && config().deleteTable !== false) {
4189
+ @if (
4190
+ tableBubbleMenuConfig().separator !== false && tableBubbleMenuConfig().deleteTable !== false
4191
+ ) {
3913
4192
  <ate-separator />
3914
4193
  }
3915
4194
 
3916
4195
  <!-- Table actions -->
3917
- @if (config().deleteTable !== false) {
4196
+ @if (tableBubbleMenuConfig().deleteTable !== false) {
3918
4197
  <ate-button
3919
4198
  icon="delete_forever"
3920
4199
  [title]="t().deleteTable"
@@ -3923,7 +4202,7 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3923
4202
  (buttonClick)="onCommand('deleteTable', $event)"></ate-button>
3924
4203
  }
3925
4204
  </div>
3926
- `, 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 }); }
3927
4206
  }
3928
4207
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteTableBubbleMenuComponent, decorators: [{
3929
4208
  type: Component,
@@ -3935,21 +4214,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3935
4214
  template: `
3936
4215
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
3937
4216
  <!-- Row actions -->
3938
- @if (config().addRowBefore !== false) {
4217
+ @if (tableBubbleMenuConfig().addRowBefore !== false) {
3939
4218
  <ate-button
3940
4219
  icon="add_row_above"
3941
4220
  [title]="t().addRowBefore"
3942
4221
  [disabled]="!state().can.addRowBefore"
3943
4222
  (buttonClick)="onCommand('addRowBefore', $event)"></ate-button>
3944
4223
  }
3945
- @if (config().addRowAfter !== false) {
4224
+ @if (tableBubbleMenuConfig().addRowAfter !== false) {
3946
4225
  <ate-button
3947
4226
  icon="add_row_below"
3948
4227
  [title]="t().addRowAfter"
3949
4228
  [disabled]="!state().can.addRowAfter"
3950
4229
  (buttonClick)="onCommand('addRowAfter', $event)"></ate-button>
3951
4230
  }
3952
- @if (config().deleteRow !== false) {
4231
+ @if (tableBubbleMenuConfig().deleteRow !== false) {
3953
4232
  <ate-button
3954
4233
  icon="delete"
3955
4234
  [title]="t().deleteRow"
@@ -3957,26 +4236,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3957
4236
  [disabled]="!state().can.deleteRow"
3958
4237
  (buttonClick)="onCommand('deleteRow', $event)"></ate-button>
3959
4238
  }
3960
- @if (config().separator !== false) {
4239
+ @if (tableBubbleMenuConfig().separator !== false) {
3961
4240
  <ate-separator />
3962
4241
  }
3963
4242
 
3964
4243
  <!-- Column actions -->
3965
- @if (config().addColumnBefore !== false) {
4244
+ @if (tableBubbleMenuConfig().addColumnBefore !== false) {
3966
4245
  <ate-button
3967
4246
  icon="add_column_left"
3968
4247
  [title]="t().addColumnBefore"
3969
4248
  [disabled]="!state().can.addColumnBefore"
3970
4249
  (buttonClick)="onCommand('addColumnBefore', $event)"></ate-button>
3971
4250
  }
3972
- @if (config().addColumnAfter !== false) {
4251
+ @if (tableBubbleMenuConfig().addColumnAfter !== false) {
3973
4252
  <ate-button
3974
4253
  icon="add_column_right"
3975
4254
  [title]="t().addColumnAfter"
3976
4255
  [disabled]="!state().can.addColumnAfter"
3977
4256
  (buttonClick)="onCommand('addColumnAfter', $event)"></ate-button>
3978
4257
  }
3979
- @if (config().deleteColumn !== false) {
4258
+ @if (tableBubbleMenuConfig().deleteColumn !== false) {
3980
4259
  <ate-button
3981
4260
  icon="delete"
3982
4261
  [title]="t().deleteColumn"
@@ -3984,12 +4263,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3984
4263
  [disabled]="!state().can.deleteColumn"
3985
4264
  (buttonClick)="onCommand('deleteColumn', $event)"></ate-button>
3986
4265
  }
3987
- @if (config().separator !== false) {
4266
+ @if (tableBubbleMenuConfig().separator !== false) {
3988
4267
  <ate-separator />
3989
4268
  }
3990
4269
 
3991
4270
  <!-- Cell actions -->
3992
- @if (config().toggleHeaderRow !== false) {
4271
+ @if (tableBubbleMenuConfig().toggleHeaderRow !== false) {
3993
4272
  <ate-button
3994
4273
  icon="toolbar"
3995
4274
  [title]="t().toggleHeaderRow"
@@ -3997,7 +4276,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3997
4276
  [disabled]="!state().can.toggleHeaderRow"
3998
4277
  (buttonClick)="onCommand('toggleHeaderRow', $event)"></ate-button>
3999
4278
  }
4000
- @if (config().toggleHeaderColumn !== false) {
4279
+ @if (tableBubbleMenuConfig().toggleHeaderColumn !== false) {
4001
4280
  <ate-button
4002
4281
  icon="dock_to_right"
4003
4282
  [title]="t().toggleHeaderColumn"
@@ -4005,12 +4284,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
4005
4284
  [disabled]="!state().can.toggleHeaderColumn"
4006
4285
  (buttonClick)="onCommand('toggleHeaderColumn', $event)"></ate-button>
4007
4286
  }
4008
- @if (config().separator !== false && config().deleteTable !== false) {
4287
+ @if (
4288
+ tableBubbleMenuConfig().separator !== false && tableBubbleMenuConfig().deleteTable !== false
4289
+ ) {
4009
4290
  <ate-separator />
4010
4291
  }
4011
4292
 
4012
4293
  <!-- Table actions -->
4013
- @if (config().deleteTable !== false) {
4294
+ @if (tableBubbleMenuConfig().deleteTable !== false) {
4014
4295
  <ate-button
4015
4296
  icon="delete_forever"
4016
4297
  [title]="t().deleteTable"
@@ -4027,7 +4308,11 @@ class AteCellBubbleMenuComponent extends AteBaseBubbleMenu {
4027
4308
  constructor() {
4028
4309
  super(...arguments);
4029
4310
  // Inputs
4030
- 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" }] : []));
4031
4316
  // Signals
4032
4317
  this.i18n = () => this.i18nService;
4033
4318
  }
@@ -4093,14 +4378,14 @@ class AteCellBubbleMenuComponent extends AteBaseBubbleMenu {
4093
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: `
4094
4379
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
4095
4380
  <!-- Cell specific actions -->
4096
- @if (config().mergeCells !== false && !state().selection.isSingleCell) {
4381
+ @if (cellBubbleMenuConfig().mergeCells !== false && !state().selection.isSingleCell) {
4097
4382
  <ate-button
4098
4383
  icon="cell_merge"
4099
4384
  [title]="i18n().table().mergeCells"
4100
4385
  [disabled]="!state().can.mergeCells"
4101
4386
  (buttonClick)="onCommand('mergeCells', $event)"></ate-button>
4102
4387
  }
4103
- @if (config().splitCell !== false && state().selection.isSingleCell) {
4388
+ @if (cellBubbleMenuConfig().splitCell !== false && state().selection.isSingleCell) {
4104
4389
  <ate-button
4105
4390
  icon="split_scene"
4106
4391
  [title]="i18n().table().splitCell"
@@ -4120,14 +4405,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
4120
4405
  template: `
4121
4406
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
4122
4407
  <!-- Cell specific actions -->
4123
- @if (config().mergeCells !== false && !state().selection.isSingleCell) {
4408
+ @if (cellBubbleMenuConfig().mergeCells !== false && !state().selection.isSingleCell) {
4124
4409
  <ate-button
4125
4410
  icon="cell_merge"
4126
4411
  [title]="i18n().table().mergeCells"
4127
4412
  [disabled]="!state().can.mergeCells"
4128
4413
  (buttonClick)="onCommand('mergeCells', $event)"></ate-button>
4129
4414
  }
4130
- @if (config().splitCell !== false && state().selection.isSingleCell) {
4415
+ @if (cellBubbleMenuConfig().splitCell !== false && state().selection.isSingleCell) {
4131
4416
  <ate-button
4132
4417
  icon="split_scene"
4133
4418
  [title]="i18n().table().splitCell"
@@ -4454,7 +4739,7 @@ class AteLinkBubbleMenuComponent extends AteBaseSubBubbleMenu {
4454
4739
  </div>
4455
4740
  </div>
4456
4741
  </div>
4457
- `, 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 }); }
4458
4743
  }
4459
4744
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteLinkBubbleMenuComponent, decorators: [{
4460
4745
  type: Component,
@@ -4781,7 +5066,7 @@ class AteColorBubbleMenuComponent extends AteBaseSubBubbleMenu {
4781
5066
  </div>
4782
5067
  </div>
4783
5068
  </div>
4784
- `, 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 }); }
4785
5070
  }
4786
5071
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteColorBubbleMenuComponent, decorators: [{
4787
5072
  type: Component,
@@ -6107,124 +6392,6 @@ const AteLinkClickBehavior = Extension.create({
6107
6392
  },
6108
6393
  });
6109
6394
 
6110
- // Default toolbar configuration
6111
- const ATE_DEFAULT_TOOLBAR_CONFIG = {
6112
- bold: true,
6113
- italic: true,
6114
- underline: true,
6115
- strike: true,
6116
- code: true,
6117
- codeBlock: true,
6118
- superscript: false, // Disabled by default (opt-in)
6119
- subscript: false, // Disabled by default (opt-in)
6120
- highlight: false, // Disabled by default (opt-in)
6121
- highlightPicker: true,
6122
- heading1: true,
6123
- heading2: true,
6124
- heading3: true,
6125
- bulletList: true,
6126
- orderedList: true,
6127
- blockquote: true,
6128
- alignLeft: false, // Disabled by default (opt-in)
6129
- alignCenter: false, // Disabled by default (opt-in)
6130
- alignRight: false, // Disabled by default (opt-in)
6131
- alignJustify: false, // Disabled by default (opt-in)
6132
- link: true,
6133
- image: true,
6134
- horizontalRule: false, // Disabled by default (opt-in)
6135
- table: true,
6136
- undo: true,
6137
- redo: true,
6138
- clear: false, // Disabled by default (opt-in)
6139
- textColor: true,
6140
- separator: true,
6141
- };
6142
- // Default bubble menu configuration
6143
- const ATE_DEFAULT_BUBBLE_MENU_CONFIG = {
6144
- bold: true,
6145
- italic: true,
6146
- underline: true,
6147
- strike: true,
6148
- code: true,
6149
- superscript: false,
6150
- subscript: false,
6151
- highlight: false,
6152
- highlightPicker: true,
6153
- textColor: true,
6154
- link: true,
6155
- separator: true,
6156
- };
6157
- // Default image bubble menu configuration
6158
- const ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG = {
6159
- changeImage: true,
6160
- resizeSmall: true,
6161
- resizeMedium: true,
6162
- resizeLarge: true,
6163
- resizeOriginal: true,
6164
- deleteImage: true,
6165
- separator: true,
6166
- };
6167
- // Default table bubble menu configuration
6168
- const ATE_DEFAULT_TABLE_MENU_CONFIG = {
6169
- addRowBefore: true,
6170
- addRowAfter: true,
6171
- deleteRow: true,
6172
- addColumnBefore: true,
6173
- addColumnAfter: true,
6174
- deleteColumn: true,
6175
- toggleHeaderRow: true,
6176
- toggleHeaderColumn: true,
6177
- deleteTable: true,
6178
- separator: true,
6179
- };
6180
- // Default cell bubble menu configuration
6181
- const ATE_DEFAULT_CELL_MENU_CONFIG = {
6182
- mergeCells: true,
6183
- splitCell: true,
6184
- };
6185
- /**
6186
- * Ultimate default configuration for the Angular Tiptap Editor.
6187
- * This serves as the 'Level 4' fallback in the configuration hierarchy:
6188
- * 1. Component Inputs (Le Roi)
6189
- * 2. Component [config] (Le Prince)
6190
- * 3. Global provideAteEditor() (Le Duc)
6191
- * 4. ATE_DEFAULT_CONFIG (Le Peuple)
6192
- */
6193
- const ATE_DEFAULT_CONFIG = {
6194
- theme: "auto",
6195
- mode: "classic",
6196
- height: "auto",
6197
- minHeight: "200px",
6198
- maxHeight: "none",
6199
- fillContainer: false,
6200
- autofocus: false,
6201
- editable: true,
6202
- disabled: false,
6203
- spellcheck: true,
6204
- enableOfficePaste: true,
6205
- showToolbar: true,
6206
- showFooter: true,
6207
- showCharacterCount: true,
6208
- showWordCount: true,
6209
- showEditToggle: false,
6210
- showBubbleMenu: true,
6211
- showImageBubbleMenu: true,
6212
- showTableMenu: true,
6213
- showCellMenu: true,
6214
- enableSlashCommands: true,
6215
- floatingToolbar: false,
6216
- toolbar: ATE_DEFAULT_TOOLBAR_CONFIG,
6217
- bubbleMenu: ATE_DEFAULT_BUBBLE_MENU_CONFIG,
6218
- imageBubbleMenu: ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG,
6219
- tableBubbleMenu: ATE_DEFAULT_TABLE_MENU_CONFIG,
6220
- cellBubbleMenu: ATE_DEFAULT_CELL_MENU_CONFIG,
6221
- slashCommands: {},
6222
- tiptapExtensions: [],
6223
- tiptapOptions: {},
6224
- stateCalculators: [],
6225
- angularNodes: [],
6226
- };
6227
-
6228
6395
  // Slash commands configuration is handled dynamically via slashCommandsConfigComputed
6229
6396
  /**
6230
6397
  * The main rich-text editor component for Angular.
@@ -6471,22 +6638,15 @@ class AngularTiptapEditorComponent {
6471
6638
  this.finalImageUploadConfig = computed(() => {
6472
6639
  const fromInput = this.imageUpload();
6473
6640
  const fromConfig = this.effectiveConfig().imageUpload;
6641
+ const base = ATE_DEFAULT_IMAGE_UPLOAD_CONFIG;
6474
6642
  const merged = {
6475
- maxSize: 5, // Default 5MB
6476
- maxWidth: 1920,
6477
- maxHeight: 1080,
6478
- allowedTypes: ["image/jpeg", "image/png", "image/gif", "image/webp"],
6479
- enableDragDrop: true,
6480
- showPreview: true,
6481
- multiple: false,
6482
- compressImages: true,
6483
- quality: 0.8,
6643
+ ...base,
6484
6644
  ...fromConfig,
6485
6645
  ...fromInput,
6486
6646
  };
6487
6647
  return {
6488
6648
  ...merged,
6489
- 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
6490
6650
  };
6491
6651
  }, ...(ngDevMode ? [{ debugName: "finalImageUploadConfig" }] : []));
6492
6652
  this.finalImageUploadHandler = computed(() => this.imageUploadHandler() ?? this.effectiveConfig().imageUpload?.handler, ...(ngDevMode ? [{ debugName: "finalImageUploadHandler" }] : []));
@@ -6636,7 +6796,7 @@ class AngularTiptapEditorComponent {
6636
6796
  Superscript,
6637
6797
  Subscript,
6638
6798
  TextAlign.configure({
6639
- types: ["heading", "paragraph"],
6799
+ types: ["heading", "paragraph", "resizableImage"],
6640
6800
  }),
6641
6801
  AteLinkClickBehavior,
6642
6802
  Highlight.configure({
@@ -6870,7 +7030,17 @@ class AngularTiptapEditorComponent {
6870
7030
  }
6871
7031
  onEditorClick(event) {
6872
7032
  const editor = this.editor();
6873
- 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
+ }
6874
7044
  return;
6875
7045
  }
6876
7046
  // Verify if interaction is on the container element and not on the content
@@ -6930,7 +7100,7 @@ class AngularTiptapEditorComponent {
6930
7100
  }
6931
7101
 
6932
7102
  <!-- Image Bubble Menu -->
6933
- @if (finalEditable() && finalShowImageBubbleMenu() && editor()) {
7103
+ @if (finalShowImageBubbleMenu() && editor()) {
6934
7104
  <ate-image-bubble-menu
6935
7105
  [editor]="editor()!"
6936
7106
  [config]="finalImageBubbleMenuConfig()"
@@ -7005,7 +7175,7 @@ class AngularTiptapEditorComponent {
7005
7175
  </div>
7006
7176
  }
7007
7177
  </div>
7008
- `, 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 }); }
7009
7179
  }
7010
7180
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AngularTiptapEditorComponent, decorators: [{
7011
7181
  type: Component,
@@ -7074,7 +7244,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
7074
7244
  }
7075
7245
 
7076
7246
  <!-- Image Bubble Menu -->
7077
- @if (finalEditable() && finalShowImageBubbleMenu() && editor()) {
7247
+ @if (finalShowImageBubbleMenu() && editor()) {
7078
7248
  <ate-image-bubble-menu
7079
7249
  [editor]="editor()!"
7080
7250
  [config]="finalImageBubbleMenuConfig()"
@@ -7149,7 +7319,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
7149
7319
  </div>
7150
7320
  }
7151
7321
  </div>
7152
- `, 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"] }]
7153
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 }] }] } });
7154
7324
 
7155
7325
  /**
@@ -7218,55 +7388,6 @@ const ATE_TOOLBAR_KEYS = [
7218
7388
  "separator",
7219
7389
  ];
7220
7390
 
7221
- /**
7222
- * Clés des options du menu bulle de texte
7223
- */
7224
- const ATE_BUBBLE_MENU_KEYS = [
7225
- "bold",
7226
- "italic",
7227
- "underline",
7228
- "strike",
7229
- "code",
7230
- "superscript",
7231
- "subscript",
7232
- "highlight",
7233
- "highlightPicker",
7234
- "textColor",
7235
- "link",
7236
- "separator",
7237
- ];
7238
- /**
7239
- * Clés des options du menu bulle d'image
7240
- */
7241
- const ATE_IMAGE_BUBBLE_MENU_KEYS = [
7242
- "changeImage",
7243
- "resizeSmall",
7244
- "resizeMedium",
7245
- "resizeLarge",
7246
- "resizeOriginal",
7247
- "deleteImage",
7248
- "separator",
7249
- ];
7250
- /**
7251
- * Clés des options du menu de table
7252
- */
7253
- const ATE_TABLE_BUBBLE_MENU_KEYS = [
7254
- "addRowBefore",
7255
- "addRowAfter",
7256
- "deleteRow",
7257
- "addColumnBefore",
7258
- "addColumnAfter",
7259
- "deleteColumn",
7260
- "deleteTable",
7261
- "toggleHeaderRow",
7262
- "toggleHeaderColumn",
7263
- "separator",
7264
- ];
7265
- /**
7266
- * Clés des options du menu de cellule
7267
- */
7268
- const ATE_CELL_BUBBLE_MENU_KEYS = ["mergeCells", "splitCell"];
7269
-
7270
7391
  /*
7271
7392
  * Public API Surface of tiptap-editor
7272
7393
  */
@@ -7276,5 +7397,5 @@ const ATE_CELL_BUBBLE_MENU_KEYS = ["mergeCells", "splitCell"];
7276
7397
  * Generated bundle index. Do not edit.
7277
7398
  */
7278
7399
 
7279
- 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 };
7280
7401
  //# sourceMappingURL=flogeez-angular-tiptap-editor.mjs.map