@flogeez/angular-tiptap-editor 3.5.2 → 3.5.4

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.
@@ -13,6 +13,7 @@ import { Color } from '@tiptap/extension-color';
13
13
  import OfficePaste from '@intevation/tiptap-extension-office-paste';
14
14
  import { Plugin, PluginKey, TextSelection, NodeSelection } from '@tiptap/pm/state';
15
15
  import { DecorationSet, Decoration } from '@tiptap/pm/view';
16
+ import { Fragment, Slice } from '@tiptap/pm/model';
16
17
  import { Table, TableRow, TableHeader, TableCell } from '@tiptap/extension-table';
17
18
  import { Subscription, isObservable, firstValueFrom, concat, defer, of, tap } from 'rxjs';
18
19
  import tippy, { sticky } from 'tippy.js';
@@ -681,6 +682,207 @@ const AteUploadProgress = Extension.create({
681
682
  },
682
683
  });
683
684
 
685
+ const IMAGE_NODE_NAMES = new Set(["resizableImage", "image"]);
686
+ const REMOTE_SRC = /^(https?:)?\/\//i;
687
+ const INLINE_SRC = /^data:(image\/[\w.+-]+);base64,(.*)$/is;
688
+ const PASTED_IMAGE_BASENAME = "pasted-image";
689
+ /**
690
+ * Classifies the `src` of an image found in pasted HTML.
691
+ * `unreachable` sources (e.g. `attachment:`, `file:`, `cid:`, foreign `blob:`) cannot be fetched by the page.
692
+ */
693
+ function classifyPastedImageSrc(src, origin = typeof location !== "undefined" ? location.origin : "") {
694
+ if (!src) {
695
+ return "unreachable";
696
+ }
697
+ if (REMOTE_SRC.test(src) || (src.startsWith("/") && !src.startsWith("//"))) {
698
+ return "remote";
699
+ }
700
+ if (origin && src.startsWith(`blob:${origin}/`)) {
701
+ return "remote";
702
+ }
703
+ return INLINE_SRC.test(src) ? "inline" : "unreachable";
704
+ }
705
+ /** Decodes a base64 image data URI into a `File`, or returns `null` when it is malformed */
706
+ function dataUriToFile(src) {
707
+ const match = INLINE_SRC.exec(src);
708
+ if (!match) {
709
+ return null;
710
+ }
711
+ const mimeType = match[1].toLowerCase();
712
+ try {
713
+ const binary = atob(match[2].replace(/\s/g, ""));
714
+ const bytes = Uint8Array.from(binary, char => char.codePointAt(0) ?? 0);
715
+ const extension = mimeType.split("/")[1].split("+")[0];
716
+ return new File([bytes], `${PASTED_IMAGE_BASENAME}.${extension}`, { type: mimeType });
717
+ }
718
+ catch {
719
+ return null;
720
+ }
721
+ }
722
+ function isImageNode(node) {
723
+ return IMAGE_NODE_NAMES.has(node.type.name);
724
+ }
725
+ /** Removes unreachable images from a pasted slice and lists the base64 sources it keeps */
726
+ function sanitizePastedImages(slice) {
727
+ const inlineSources = new Set();
728
+ const droppedSources = [];
729
+ const sanitize = (fragment) => {
730
+ const kept = [];
731
+ fragment.forEach(child => {
732
+ if (isImageNode(child)) {
733
+ const src = child.attrs["src"];
734
+ const source = classifyPastedImageSrc(src);
735
+ if (source === "unreachable") {
736
+ droppedSources.push(src ?? "");
737
+ return;
738
+ }
739
+ if (source === "inline" && src) {
740
+ inlineSources.add(src);
741
+ }
742
+ kept.push(child);
743
+ return;
744
+ }
745
+ kept.push(child.isLeaf ? child : child.copy(sanitize(child.content)));
746
+ });
747
+ return Fragment.fromArray(kept);
748
+ };
749
+ const content = sanitize(slice.content);
750
+ if (!droppedSources.length) {
751
+ return { slice, inlineSources: [...inlineSources], droppedSources };
752
+ }
753
+ const openStart = content.firstChild === slice.content.firstChild ? slice.openStart : 0;
754
+ const openEnd = content.lastChild === slice.content.lastChild ? slice.openEnd : 0;
755
+ return {
756
+ slice: new Slice(content, openStart, openEnd),
757
+ inlineSources: [...inlineSources],
758
+ droppedSources,
759
+ };
760
+ }
761
+ function replaceImageSrc(editor, previousSrc, nextSrc) {
762
+ if (editor.isDestroyed) {
763
+ return;
764
+ }
765
+ const { state } = editor;
766
+ const matches = [];
767
+ state.doc.descendants((node, pos) => {
768
+ if (isImageNode(node) && node.attrs["src"] === previousSrc) {
769
+ matches.push({ pos, node });
770
+ }
771
+ });
772
+ if (!matches.length) {
773
+ return;
774
+ }
775
+ const tr = state.tr;
776
+ for (const { pos, node } of [...matches].reverse()) {
777
+ if (nextSrc) {
778
+ tr.setNodeMarkup(pos, undefined, { ...node.attrs, src: nextSrc });
779
+ }
780
+ else {
781
+ tr.delete(pos, pos + node.nodeSize);
782
+ }
783
+ }
784
+ editor.view.dispatch(tr);
785
+ }
786
+ /**
787
+ * Cleans images coming from pasted HTML (e.g. Notion, Google Docs, Office):
788
+ * - drops images whose source the page cannot load, instead of inserting broken images;
789
+ * - sends base64 images through the upload handler (when one is configured) and swaps in the hosted URL.
790
+ *
791
+ * File-based clipboard images keep going through the regular paste upload flow.
792
+ */
793
+ const AtePastedImage = Extension.create({
794
+ name: "atePastedImage",
795
+ addOptions() {
796
+ return {
797
+ shouldRehost: () => false,
798
+ rehost: () => Promise.reject(new Error("No upload handler configured")),
799
+ onRejected: () => undefined,
800
+ };
801
+ },
802
+ addProseMirrorPlugins() {
803
+ const editor = this.editor;
804
+ const options = this.options;
805
+ const rehost = (src) => {
806
+ const file = dataUriToFile(src);
807
+ if (!file) {
808
+ replaceImageSrc(editor, src, null);
809
+ options.onRejected({ reason: "unreachable", src });
810
+ return;
811
+ }
812
+ options
813
+ .rehost(file)
814
+ .then(url => replaceImageSrc(editor, src, url))
815
+ .catch(() => {
816
+ replaceImageSrc(editor, src, null);
817
+ options.onRejected({ reason: "upload-failed", src });
818
+ });
819
+ };
820
+ return [
821
+ new Plugin({
822
+ key: new PluginKey("atePastedImage"),
823
+ props: {
824
+ transformPasted: slice => {
825
+ const { slice: sanitized, inlineSources, droppedSources } = sanitizePastedImages(slice);
826
+ droppedSources.forEach(src => options.onRejected({ reason: "unreachable", src }));
827
+ if (inlineSources.length && options.shouldRehost()) {
828
+ queueMicrotask(() => inlineSources.forEach(rehost));
829
+ }
830
+ return sanitized;
831
+ },
832
+ },
833
+ }),
834
+ ];
835
+ },
836
+ });
837
+
838
+ /** Matches the bare `Mod+K` chord (`Cmd+K` on macOS, `Ctrl+K` elsewhere) */
839
+ function isLinkShortcut(event) {
840
+ return ((event.metaKey || event.ctrlKey) &&
841
+ !event.shiftKey &&
842
+ !event.altKey &&
843
+ event.key.toLowerCase() === "k");
844
+ }
845
+ /**
846
+ * `Mod+K` opens the link editor when text is selected or the cursor is on a link.
847
+ * With an empty selection outside a link the event is left alone, so host-level `Mod+K`
848
+ * shortcuts (search, command palettes) keep working.
849
+ */
850
+ const AteLinkShortcut = Extension.create({
851
+ name: "ateLinkShortcut",
852
+ addOptions() {
853
+ return {
854
+ canOpen: () => true,
855
+ open: () => undefined,
856
+ };
857
+ },
858
+ addProseMirrorPlugins() {
859
+ const editor = this.editor;
860
+ const options = this.options;
861
+ return [
862
+ new Plugin({
863
+ key: new PluginKey("ateLinkShortcut"),
864
+ props: {
865
+ handleKeyDown: (view, event) => {
866
+ if (!isLinkShortcut(event) || !view.editable) {
867
+ return false;
868
+ }
869
+ if (view.state.selection.empty && !editor.isActive("link")) {
870
+ return false;
871
+ }
872
+ if (!options.canOpen()) {
873
+ return false;
874
+ }
875
+ event.preventDefault();
876
+ event.stopPropagation();
877
+ options.open(editor);
878
+ return true;
879
+ },
880
+ },
881
+ }),
882
+ ];
883
+ },
884
+ });
885
+
684
886
  const AteTableExtension = Extension.create({
685
887
  name: "tableExtension",
686
888
  addExtensions() {
@@ -3341,43 +3543,15 @@ class AteImageService {
3341
3543
  this.uploadProgress.set(10);
3342
3544
  this.uploadMessage.set(this.t().validating);
3343
3545
  this.forceEditorUpdate();
3344
- const validation = this.validateImage(file, {
3345
- maxSize: options?.maxSize,
3346
- allowedTypes: options?.allowedTypes,
3347
- });
3348
- if (!validation.valid) {
3349
- throw new Error(validation.error);
3350
- }
3351
- this.uploadProgress.set(30);
3352
- this.uploadMessage.set(this.t().compressing);
3353
- this.forceEditorUpdate();
3354
- const result = await this.compressImage(file, options?.quality || 0.8, options?.maxWidth || 1920, options?.maxHeight || 1200);
3355
- this.uploadProgress.set(70);
3356
- // Handle custom upload if handler is provided
3357
- if (this.uploadHandler) {
3358
- this.uploadMessage.set(this.t().uploadingToServer);
3359
- this.forceEditorUpdate();
3360
- try {
3361
- const handlerResponse = this.uploadHandler({
3362
- file,
3363
- width: result.width || 0,
3364
- height: result.height || 0,
3365
- type: result.type,
3366
- base64: result.src,
3367
- });
3368
- const handlerResult = isObservable(handlerResponse)
3369
- ? await firstValueFrom(handlerResponse)
3370
- : await handlerResponse;
3371
- result.src = handlerResult.src;
3372
- if (handlerResult.alt) {
3373
- result.name = handlerResult.alt;
3374
- }
3546
+ const result = await this.processImage(file, options, (progress, message) => {
3547
+ if (progress !== undefined) {
3548
+ this.uploadProgress.set(progress);
3375
3549
  }
3376
- catch (handlerError) {
3377
- console.error(this.t().uploadError, handlerError);
3378
- throw handlerError;
3550
+ if (message !== undefined) {
3551
+ this.uploadMessage.set(message);
3552
+ this.forceEditorUpdate();
3379
3553
  }
3380
- }
3554
+ });
3381
3555
  this.uploadProgress.set(90);
3382
3556
  this.uploadMessage.set(actionMessage);
3383
3557
  this.forceEditorUpdate();
@@ -3394,6 +3568,61 @@ class AteImageService {
3394
3568
  throw error;
3395
3569
  }
3396
3570
  }
3571
+ /** Validate, compress and (when configured) send an image to the upload handler */
3572
+ async processImage(file, options, onStep) {
3573
+ const validation = this.validateImage(file, {
3574
+ maxSize: options?.maxSize,
3575
+ allowedTypes: options?.allowedTypes,
3576
+ });
3577
+ if (!validation.valid) {
3578
+ throw new Error(validation.error);
3579
+ }
3580
+ onStep?.(30, this.t().compressing);
3581
+ const result = await this.compressImage(file, options?.quality || 0.8, options?.maxWidth || 1920, options?.maxHeight || 1200);
3582
+ onStep?.(70);
3583
+ // Handle custom upload if handler is provided
3584
+ if (this.uploadHandler) {
3585
+ onStep?.(undefined, this.t().uploadingToServer);
3586
+ try {
3587
+ const handlerResponse = this.uploadHandler({
3588
+ file,
3589
+ width: result.width || 0,
3590
+ height: result.height || 0,
3591
+ type: result.type,
3592
+ base64: result.src,
3593
+ });
3594
+ const handlerResult = isObservable(handlerResponse)
3595
+ ? await firstValueFrom(handlerResponse)
3596
+ : await handlerResponse;
3597
+ result.src = handlerResult.src;
3598
+ if (handlerResult.alt) {
3599
+ result.name = handlerResult.alt;
3600
+ }
3601
+ }
3602
+ catch (handlerError) {
3603
+ console.error(this.t().uploadError, handlerError);
3604
+ throw handlerError;
3605
+ }
3606
+ }
3607
+ return result;
3608
+ }
3609
+ /**
3610
+ * Run an image that is already in the document (e.g. base64 from pasted HTML)
3611
+ * through validation, compression and the upload handler, and resolve to its new `src`.
3612
+ */
3613
+ async rehostImage(file, options) {
3614
+ try {
3615
+ const result = await this.processImage(file, options);
3616
+ if (this.onImageUploadedCallback) {
3617
+ this.onImageUploadedCallback(result);
3618
+ }
3619
+ return result.src;
3620
+ }
3621
+ catch (error) {
3622
+ console.error(this.t().uploadError, error);
3623
+ throw error;
3624
+ }
3625
+ }
3397
3626
  resetUploadState() {
3398
3627
  this.isUploading.set(false);
3399
3628
  this.uploadProgress.set(0);
@@ -4635,6 +4864,12 @@ class AteEditorCommandsService {
4635
4864
  handleImagePaste(editor, event, options) {
4636
4865
  return this.imageService.handlePaste(editor, event, options);
4637
4866
  }
4867
+ rehostImage(file, options) {
4868
+ return this.imageService.rehostImage(file, options);
4869
+ }
4870
+ get hasUploadHandler() {
4871
+ return this.imageService.uploadHandler !== null;
4872
+ }
4638
4873
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteEditorCommandsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4639
4874
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteEditorCommandsService }); }
4640
4875
  }
@@ -6751,6 +6986,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
6751
6986
  type: Directive
6752
6987
  }], ctorParameters: () => [] });
6753
6988
 
6989
+ /** Frames to wait for the menu to become visible before giving up on focusing the URL field */
6990
+ const FOCUS_MAX_ATTEMPTS = 20;
6754
6991
  class AteLinkBubbleMenuComponent extends AteBaseSubBubbleMenu {
6755
6992
  constructor() {
6756
6993
  super();
@@ -6771,6 +7008,24 @@ class AteLinkBubbleMenuComponent extends AteBaseSubBubbleMenu {
6771
7008
  this.editUrl.set(currentLinkHref);
6772
7009
  }
6773
7010
  }, { allowSignalWrites: true });
7011
+ // Move focus to the URL field whenever link editing starts (toolbar, bubble menu or Mod+K)
7012
+ effect(() => {
7013
+ if (this.linkSvc.editMode()) {
7014
+ untracked(() => this.focusInputWhenVisible());
7015
+ }
7016
+ });
7017
+ }
7018
+ focusInputWhenVisible(attempt = 0) {
7019
+ requestAnimationFrame(() => {
7020
+ const input = this.linkInput()?.nativeElement;
7021
+ if (!input || !this.linkSvc.editMode()) {
7022
+ return;
7023
+ }
7024
+ input.focus();
7025
+ if (document.activeElement !== input && attempt < FOCUS_MAX_ATTEMPTS) {
7026
+ this.focusInputWhenVisible(attempt + 1);
7027
+ }
7028
+ });
6774
7029
  }
6775
7030
  onStateChange() {
6776
7031
  this.linkSvc.editMode();
@@ -8723,6 +8978,8 @@ class AngularTiptapEditorComponent {
8723
8978
  this.editorBlur = output();
8724
8979
  this.editableChange = output();
8725
8980
  this.imageUploaded = output();
8981
+ /** Emitted when an image from pasted HTML is dropped (unreachable source or failed upload) */
8982
+ this.pastedImageRejected = output();
8726
8983
  // ViewChild with signal
8727
8984
  this.editorElement = viewChild.required("editorElement");
8728
8985
  // Private signals for internal state
@@ -9058,6 +9315,10 @@ class AngularTiptapEditorComponent {
9058
9315
  types: ["heading", "paragraph", "resizableImage"],
9059
9316
  }),
9060
9317
  AteLinkClickBehavior,
9318
+ AteLinkShortcut.configure({
9319
+ canOpen: () => this.editorCommandsService.editorState().can.toggleLink,
9320
+ open: editor => this.editorCommandsService.execute(editor, "toggleLink"),
9321
+ }),
9061
9322
  Highlight.configure({
9062
9323
  multicolor: true,
9063
9324
  HTMLAttributes: {
@@ -9071,6 +9332,11 @@ class AngularTiptapEditorComponent {
9071
9332
  class: "ate-image",
9072
9333
  },
9073
9334
  }),
9335
+ AtePastedImage.configure({
9336
+ shouldRehost: () => this.editorCommandsService.hasUploadHandler,
9337
+ rehost: file => this.editorCommandsService.rehostImage(file, this.getImageUploadOptions()),
9338
+ onRejected: rejection => this.pastedImageRejected.emit(rejection),
9339
+ }),
9074
9340
  AteUploadProgress.configure({
9075
9341
  isUploading: () => this.editorCommandsService.isUploading(),
9076
9342
  uploadProgress: () => this.editorCommandsService.uploadProgress(),
@@ -9353,7 +9619,7 @@ class AngularTiptapEditorComponent {
9353
9619
  }
9354
9620
  }
9355
9621
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AngularTiptapEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
9356
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AngularTiptapEditorComponent, isStandalone: true, selector: "angular-tiptap-editor", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, fillContainer: { classPropertyName: "fillContainer", publicName: "fillContainer", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showFooter: { classPropertyName: "showFooter", publicName: "showFooter", isSignal: true, isRequired: false, transformFunction: null }, showCharacterCount: { classPropertyName: "showCharacterCount", publicName: "showCharacterCount", isSignal: true, isRequired: false, transformFunction: null }, showWordCount: { classPropertyName: "showWordCount", publicName: "showWordCount", isSignal: true, isRequired: false, transformFunction: null }, maxCharacters: { classPropertyName: "maxCharacters", publicName: "maxCharacters", isSignal: true, isRequired: false, transformFunction: null }, enableOfficePaste: { classPropertyName: "enableOfficePaste", publicName: "enableOfficePaste", isSignal: true, isRequired: false, transformFunction: null }, enableSlashCommands: { classPropertyName: "enableSlashCommands", publicName: "enableSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, slashCommands: { classPropertyName: "slashCommands", publicName: "slashCommands", isSignal: true, isRequired: false, transformFunction: null }, customSlashCommands: { classPropertyName: "customSlashCommands", publicName: "customSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, blockControls: { classPropertyName: "blockControls", publicName: "blockControls", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, seamless: { classPropertyName: "seamless", publicName: "seamless", isSignal: true, isRequired: false, transformFunction: null }, floatingToolbar: { classPropertyName: "floatingToolbar", publicName: "floatingToolbar", isSignal: true, isRequired: false, transformFunction: null }, showEditToggle: { classPropertyName: "showEditToggle", publicName: "showEditToggle", isSignal: true, isRequired: false, transformFunction: null }, spellcheck: { classPropertyName: "spellcheck", publicName: "spellcheck", isSignal: true, isRequired: false, transformFunction: null }, tiptapExtensions: { classPropertyName: "tiptapExtensions", publicName: "tiptapExtensions", isSignal: true, isRequired: false, transformFunction: null }, tiptapOptions: { classPropertyName: "tiptapOptions", publicName: "tiptapOptions", isSignal: true, isRequired: false, transformFunction: null }, showBubbleMenu: { classPropertyName: "showBubbleMenu", publicName: "showBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, bubbleMenu: { classPropertyName: "bubbleMenu", publicName: "bubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showImageBubbleMenu: { classPropertyName: "showImageBubbleMenu", publicName: "showImageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, imageBubbleMenu: { classPropertyName: "imageBubbleMenu", publicName: "imageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, showTableBubbleMenu: { classPropertyName: "showTableBubbleMenu", publicName: "showTableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, tableBubbleMenu: { classPropertyName: "tableBubbleMenu", publicName: "tableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showCellBubbleMenu: { classPropertyName: "showCellBubbleMenu", publicName: "showCellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, cellBubbleMenu: { classPropertyName: "cellBubbleMenu", publicName: "cellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, stateCalculators: { classPropertyName: "stateCalculators", publicName: "stateCalculators", isSignal: true, isRequired: false, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null }, imageUploadHandler: { classPropertyName: "imageUploadHandler", publicName: "imageUploadHandler", isSignal: true, isRequired: false, transformFunction: null }, editorId: { classPropertyName: "editorId", publicName: "editorId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentChange: "contentChange", editorCreated: "editorCreated", editorUpdate: "editorUpdate", editorFocus: "editorFocus", editorBlur: "editorBlur", editableChange: "editableChange", imageUploaded: "imageUploaded" }, host: { properties: { "class.fill-container": "finalFillContainer()", "class.floating-toolbar": "finalFloatingToolbar()", "class.is-readonly": "!finalEditable() && !mergedDisabled()", "class.is-disabled": "mergedDisabled()", "style.--ate-border-width": "finalSeamless() || mergedDisabled() ? '0' : null", "style.--ate-background": "finalSeamless() ? 'transparent' : (mergedDisabled() ? 'var(--ate-surface-tertiary)' : null)", "style.--ate-toolbar-border-color": "finalSeamless() ? 'transparent' : null", "style.--ate-counter-background": "finalSeamless() ? 'transparent' : null", "style.--ate-counter-border-color": "finalSeamless() ? 'transparent' : null", "class.dark": "config().theme === 'dark'", "class.ate-blocks-inside": "finalBlockControls() === 'inside'", "class.ate-blocks-outside": "finalBlockControls() === 'outside'", "attr.data-theme": "config().theme" } }, providers: [
9622
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AngularTiptapEditorComponent, isStandalone: true, selector: "angular-tiptap-editor", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, minHeight: { classPropertyName: "minHeight", publicName: "minHeight", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, maxHeight: { classPropertyName: "maxHeight", publicName: "maxHeight", isSignal: true, isRequired: false, transformFunction: null }, fillContainer: { classPropertyName: "fillContainer", publicName: "fillContainer", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showFooter: { classPropertyName: "showFooter", publicName: "showFooter", isSignal: true, isRequired: false, transformFunction: null }, showCharacterCount: { classPropertyName: "showCharacterCount", publicName: "showCharacterCount", isSignal: true, isRequired: false, transformFunction: null }, showWordCount: { classPropertyName: "showWordCount", publicName: "showWordCount", isSignal: true, isRequired: false, transformFunction: null }, maxCharacters: { classPropertyName: "maxCharacters", publicName: "maxCharacters", isSignal: true, isRequired: false, transformFunction: null }, enableOfficePaste: { classPropertyName: "enableOfficePaste", publicName: "enableOfficePaste", isSignal: true, isRequired: false, transformFunction: null }, enableSlashCommands: { classPropertyName: "enableSlashCommands", publicName: "enableSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, slashCommands: { classPropertyName: "slashCommands", publicName: "slashCommands", isSignal: true, isRequired: false, transformFunction: null }, customSlashCommands: { classPropertyName: "customSlashCommands", publicName: "customSlashCommands", isSignal: true, isRequired: false, transformFunction: null }, blockControls: { classPropertyName: "blockControls", publicName: "blockControls", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, seamless: { classPropertyName: "seamless", publicName: "seamless", isSignal: true, isRequired: false, transformFunction: null }, floatingToolbar: { classPropertyName: "floatingToolbar", publicName: "floatingToolbar", isSignal: true, isRequired: false, transformFunction: null }, showEditToggle: { classPropertyName: "showEditToggle", publicName: "showEditToggle", isSignal: true, isRequired: false, transformFunction: null }, spellcheck: { classPropertyName: "spellcheck", publicName: "spellcheck", isSignal: true, isRequired: false, transformFunction: null }, tiptapExtensions: { classPropertyName: "tiptapExtensions", publicName: "tiptapExtensions", isSignal: true, isRequired: false, transformFunction: null }, tiptapOptions: { classPropertyName: "tiptapOptions", publicName: "tiptapOptions", isSignal: true, isRequired: false, transformFunction: null }, showBubbleMenu: { classPropertyName: "showBubbleMenu", publicName: "showBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, bubbleMenu: { classPropertyName: "bubbleMenu", publicName: "bubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showImageBubbleMenu: { classPropertyName: "showImageBubbleMenu", publicName: "showImageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, imageBubbleMenu: { classPropertyName: "imageBubbleMenu", publicName: "imageBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, toolbar: { classPropertyName: "toolbar", publicName: "toolbar", isSignal: true, isRequired: false, transformFunction: null }, showTableBubbleMenu: { classPropertyName: "showTableBubbleMenu", publicName: "showTableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, tableBubbleMenu: { classPropertyName: "tableBubbleMenu", publicName: "tableBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, showCellBubbleMenu: { classPropertyName: "showCellBubbleMenu", publicName: "showCellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, cellBubbleMenu: { classPropertyName: "cellBubbleMenu", publicName: "cellBubbleMenu", isSignal: true, isRequired: false, transformFunction: null }, stateCalculators: { classPropertyName: "stateCalculators", publicName: "stateCalculators", isSignal: true, isRequired: false, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null }, imageUploadHandler: { classPropertyName: "imageUploadHandler", publicName: "imageUploadHandler", isSignal: true, isRequired: false, transformFunction: null }, editorId: { classPropertyName: "editorId", publicName: "editorId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { contentChange: "contentChange", editorCreated: "editorCreated", editorUpdate: "editorUpdate", editorFocus: "editorFocus", editorBlur: "editorBlur", editableChange: "editableChange", imageUploaded: "imageUploaded", pastedImageRejected: "pastedImageRejected" }, host: { properties: { "class.fill-container": "finalFillContainer()", "class.floating-toolbar": "finalFloatingToolbar()", "class.is-readonly": "!finalEditable() && !mergedDisabled()", "class.is-disabled": "mergedDisabled()", "style.--ate-border-width": "finalSeamless() || mergedDisabled() ? '0' : null", "style.--ate-background": "finalSeamless() ? 'transparent' : (mergedDisabled() ? 'var(--ate-surface-tertiary)' : null)", "style.--ate-toolbar-border-color": "finalSeamless() ? 'transparent' : null", "style.--ate-counter-background": "finalSeamless() ? 'transparent' : null", "style.--ate-counter-border-color": "finalSeamless() ? 'transparent' : null", "class.dark": "config().theme === 'dark'", "class.ate-blocks-inside": "finalBlockControls() === 'inside'", "class.ate-blocks-outside": "finalBlockControls() === 'outside'", "attr.data-theme": "config().theme" } }, providers: [
9357
9623
  AteEditorCommandsService,
9358
9624
  AteImageService,
9359
9625
  AteColorPickerService,
@@ -9849,5 +10115,5 @@ const ATE_DEFAULT_TOC_CONFIG = {
9849
10115
  * Generated bundle index. Do not edit.
9850
10116
  */
9851
10117
 
9852
- 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_ICONS, ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ATE_DEFAULT_IMAGE_UPLOAD_CONFIG, ATE_DEFAULT_SLASH_COMMANDS_CONFIG, ATE_DEFAULT_TABLE_MENU_CONFIG, ATE_DEFAULT_TOC_CONFIG, ATE_DEFAULT_TOOLBAR_CONFIG, ATE_GLOBAL_CONFIG, ATE_ICONS, ATE_IMAGE_BUBBLE_MENU_KEYS, ATE_INITIAL_EDITOR_STATE, ATE_MATERIAL_SYMBOLS_VIEWBOX, ATE_SLASH_COMMAND_KEYS, ATE_STROKE_ICONS, ATE_TABLE_BUBBLE_MENU_KEYS, ATE_TOOLBAR_KEYS, AngularTiptapEditorComponent, AteAngularNodeView, AteColorPickerService, AteDiscoveryCalculator, AteEditorCommandsService, AteEditorRef, AteEditorRegistry, AteExportService, AteI18nService, AteIconComponent, AteIconRegistry, AteImageCalculator, AteImageService, AteLinkService, AteMarksCalculator, AteNodeViewRenderer, AteNoopValueAccessorDirective, AteSelectionCalculator, AteStructureCalculator, AteTableCalculator, AteTableOfContentsComponent, AteTocNodeComponent, AteTocNodeOptions, AteTooltipDirective, createAngularComponentExtension, createDefaultSlashCommands, filterSlashCommands, getAteTocNodeExtension, provideAteEditor, provideAteIcons, registerAngularComponent };
10118
+ 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_ICONS, ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ATE_DEFAULT_IMAGE_UPLOAD_CONFIG, ATE_DEFAULT_SLASH_COMMANDS_CONFIG, ATE_DEFAULT_TABLE_MENU_CONFIG, ATE_DEFAULT_TOC_CONFIG, ATE_DEFAULT_TOOLBAR_CONFIG, ATE_GLOBAL_CONFIG, ATE_ICONS, ATE_IMAGE_BUBBLE_MENU_KEYS, ATE_INITIAL_EDITOR_STATE, ATE_MATERIAL_SYMBOLS_VIEWBOX, ATE_SLASH_COMMAND_KEYS, ATE_STROKE_ICONS, ATE_TABLE_BUBBLE_MENU_KEYS, ATE_TOOLBAR_KEYS, AngularTiptapEditorComponent, AteAngularNodeView, AteColorPickerService, AteDiscoveryCalculator, AteEditorCommandsService, AteEditorRef, AteEditorRegistry, AteExportService, AteI18nService, AteIconComponent, AteIconRegistry, AteImageCalculator, AteImageService, AteLinkService, AteLinkShortcut, AteMarksCalculator, AteNodeViewRenderer, AteNoopValueAccessorDirective, AtePastedImage, AteSelectionCalculator, AteStructureCalculator, AteTableCalculator, AteTableOfContentsComponent, AteTocNodeComponent, AteTocNodeOptions, AteTooltipDirective, classifyPastedImageSrc, createAngularComponentExtension, createDefaultSlashCommands, dataUriToFile, filterSlashCommands, getAteTocNodeExtension, isLinkShortcut, provideAteEditor, provideAteIcons, registerAngularComponent, sanitizePastedImages };
9853
10119
  //# sourceMappingURL=flogeez-angular-tiptap-editor.mjs.map