@flogeez/angular-tiptap-editor 2.2.2 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,22 @@ All notable changes to `@flogeez/angular-tiptap-editor` will be documented in th
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), with the exception that the major version is specifically aligned with the major version of [Tiptap](https://tiptap.dev).
7
7
 
8
+ ## [2.3.0] - 2026-01-28
9
+
10
+ ### Added
11
+
12
+ - **Advanced Angular Component Engine**: A powerful, unified engine to embed any Angular component directly into the editor as a custom TipTap node.
13
+ - **Universal Integration**: Seamlessly register both standard library components and TipTap-aware interactive components.
14
+ - **Modern Reactive Support**: Full out-of-the-box compatibility with Angular 18+ Signal-based `input()` and `output()`.
15
+ - **Editable Content Zones**: Turn any part of your Angular component into a nested, editable rich-text area.
16
+ - **Robustness**: Build-in protection against naming collisions and reserved TipTap nodes.
17
+
18
+ ## [2.2.3] - 2026-01-27
19
+
20
+ ### Added
21
+
22
+ - **Link Navigation**: Added support for opening links via `Ctrl + Click` (Windows/Linux) or `Cmd + Click` (macOS), allowing users to follow links directly from the editor even in edit mode.
23
+
8
24
  ## [2.2.2] - 2026-01-26
9
25
 
10
26
  ### Refactored
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, output, ChangeDetectionStrategy, Component, signal, computed, Injectable, inject, viewChild, effect, Directive, DestroyRef, untracked } from '@angular/core';
2
+ import { input, output, ChangeDetectionStrategy, Component, signal, computed, Injectable, inject, viewChild, effect, Directive, DestroyRef, untracked, ApplicationRef, EnvironmentInjector, createComponent } from '@angular/core';
3
3
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
4
  import { Node as Node$1, nodeInputRule, mergeAttributes, Extension, getAttributes, Editor } from '@tiptap/core';
5
5
  import StarterKit from '@tiptap/starter-kit';
@@ -20,7 +20,7 @@ import Table from '@tiptap/extension-table';
20
20
  import TableRow from '@tiptap/extension-table-row';
21
21
  import TableCell from '@tiptap/extension-table-cell';
22
22
  import TableHeader from '@tiptap/extension-table-header';
23
- import { isObservable, firstValueFrom, concat, defer, of, tap } from 'rxjs';
23
+ import { isObservable, firstValueFrom, concat, defer, of, tap, Subscription } from 'rxjs';
24
24
  import { CommonModule } from '@angular/common';
25
25
  import tippy, { sticky } from 'tippy.js';
26
26
  import * as i1 from '@angular/forms';
@@ -5646,13 +5646,14 @@ const AteLinkClickBehavior = Extension.create({
5646
5646
  new Plugin({
5647
5647
  key: new PluginKey("linkClickBehavior"),
5648
5648
  props: {
5649
- handleClick(view, _pos, _event) {
5649
+ handleClick(view, _pos, event) {
5650
5650
  // handleClick only runs in the browser, but we guard it for absolute SSR safety
5651
5651
  if (typeof window === "undefined") {
5652
5652
  return false;
5653
5653
  }
5654
- // If editor is editable, let TipTap/BubbleMenu handle it
5655
- if (view.editable) {
5654
+ const isModKey = event.ctrlKey || event.metaKey;
5655
+ // If editor is editable, only proceed if Ctrl/Cmd is pressed
5656
+ if (view.editable && !isModKey) {
5656
5657
  return false;
5657
5658
  }
5658
5659
  const attrs = getAttributes(view.state, "link");
@@ -6052,6 +6053,23 @@ class AngularTiptapEditorComponent {
6052
6053
  }
6053
6054
  }
6054
6055
  });
6056
+ // Effect to re-initialize editor when extensions or options change
6057
+ effect(() => {
6058
+ // Monitor extensions and options
6059
+ this.tiptapExtensions();
6060
+ this.tiptapOptions();
6061
+ untracked(() => {
6062
+ // Only if already initialized (post AfterViewInit)
6063
+ if (this.editorFullyInitialized()) {
6064
+ const currentEditor = this.editor();
6065
+ if (currentEditor) {
6066
+ currentEditor.destroy();
6067
+ this._editorFullyInitialized.set(false);
6068
+ this.initEditor();
6069
+ }
6070
+ }
6071
+ });
6072
+ });
6055
6073
  }
6056
6074
  ngAfterViewInit() {
6057
6075
  // La vue est déjà complètement initialisée dans ngAfterViewInit
@@ -6673,6 +6691,403 @@ const ATE_TABLE_BUBBLE_MENU_KEYS = [
6673
6691
  */
6674
6692
  const ATE_CELL_BUBBLE_MENU_KEYS = ["mergeCells", "splitCell"];
6675
6693
 
6694
+ /**
6695
+ * Base abstract class for Angular components used as TipTap NodeViews.
6696
+ *
6697
+ * Extend this class in your custom components to get access to the TipTap node properties.
6698
+ *
6699
+ * @example
6700
+ * ```typescript
6701
+ * @Component({
6702
+ * selector: 'app-counter',
6703
+ * template: `
6704
+ * <div>
6705
+ * <button (click)="increment()">Count: {{ node().attrs['count'] }}</button>
6706
+ * </div>
6707
+ * `
6708
+ * })
6709
+ * export class CounterComponent extends AteAngularNodeView {
6710
+ * increment() {
6711
+ * const count = this.node().attrs['count'] || 0;
6712
+ * this.updateAttributes({ count: count + 1 });
6713
+ * }
6714
+ * }
6715
+ * ```
6716
+ */
6717
+ class AteAngularNodeView {
6718
+ /**
6719
+ * Internal method to initialize the component with NodeView props.
6720
+ * This is called by the AngularNodeViewRenderer.
6721
+ *
6722
+ * @internal
6723
+ */
6724
+ _initNodeView(props) {
6725
+ // Create signals from the props
6726
+ const editorSignal = signal(props.editor, ...(ngDevMode ? [{ debugName: "editorSignal" }] : []));
6727
+ const nodeSignal = signal(props.node, ...(ngDevMode ? [{ debugName: "nodeSignal" }] : []));
6728
+ const decorationsSignal = signal(props.decorations, ...(ngDevMode ? [{ debugName: "decorationsSignal" }] : []));
6729
+ const selectedSignal = signal(props.selected, ...(ngDevMode ? [{ debugName: "selectedSignal" }] : []));
6730
+ const extensionSignal = signal(props.extension, ...(ngDevMode ? [{ debugName: "extensionSignal" }] : []));
6731
+ // Assign to the component
6732
+ this.editor = editorSignal.asReadonly();
6733
+ this.node = nodeSignal.asReadonly();
6734
+ this.decorations = decorationsSignal.asReadonly();
6735
+ this.selected = selectedSignal.asReadonly();
6736
+ this.extension = extensionSignal.asReadonly();
6737
+ this.getPos = props.getPos;
6738
+ this.updateAttributes = props.updateAttributes;
6739
+ this.deleteNode = props.deleteNode;
6740
+ // Store writable signals for updates
6741
+ this._writableSignals = {
6742
+ node: nodeSignal,
6743
+ decorations: decorationsSignal,
6744
+ selected: selectedSignal,
6745
+ };
6746
+ }
6747
+ /**
6748
+ * Internal method to update the component when the node changes.
6749
+ * This is called by the AngularNodeViewRenderer.
6750
+ *
6751
+ * @internal
6752
+ */
6753
+ _updateNodeView(node, decorations) {
6754
+ if (this._writableSignals) {
6755
+ this._writableSignals.node.set(node);
6756
+ this._writableSignals.decorations.set(decorations);
6757
+ }
6758
+ }
6759
+ /**
6760
+ * Internal method to update the selection state.
6761
+ * This is called by the AngularNodeViewRenderer.
6762
+ *
6763
+ * @internal
6764
+ */
6765
+ _selectNodeView() {
6766
+ if (this._writableSignals) {
6767
+ this._writableSignals.selected.set(true);
6768
+ }
6769
+ }
6770
+ /**
6771
+ * Internal method to update the deselection state.
6772
+ * This is called by the AngularNodeViewRenderer.
6773
+ *
6774
+ * @internal
6775
+ */
6776
+ _deselectNodeView() {
6777
+ if (this._writableSignals) {
6778
+ this._writableSignals.selected.set(false);
6779
+ }
6780
+ }
6781
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteAngularNodeView, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6782
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.16", type: AteAngularNodeView, isStandalone: true, ngImport: i0 }); }
6783
+ }
6784
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteAngularNodeView, decorators: [{
6785
+ type: Directive
6786
+ }] });
6787
+
6788
+ /**
6789
+ * Universal Renderer for Angular Components as TipTap NodeViews.
6790
+ *
6791
+ * Supports:
6792
+ * - TipTap-Aware components (extending AteAngularNodeView)
6793
+ * - Standard library components (automatic @Input() sync)
6794
+ * - Signal-based inputs and outputs (Angular 18+)
6795
+ * - Content projection (editableContent)
6796
+ * - Unified lifecycle and event management
6797
+ */
6798
+ function AteNodeViewRenderer(component, options) {
6799
+ return props => {
6800
+ const { node, view: _view, getPos, decorations, editor, extension } = props;
6801
+ const { injector, inputs = {}, wrapperTag = "div", wrapperClass, editableContent = false, contentSelector, onOutput, ignoreMutation = true, } = options;
6802
+ const dom = document.createElement(wrapperTag);
6803
+ if (wrapperClass) {
6804
+ dom.className = wrapperClass;
6805
+ }
6806
+ const applicationRef = injector.get(ApplicationRef);
6807
+ const environmentInjector = injector.get(EnvironmentInjector);
6808
+ // 1. Setup Content Projection (ng-content)
6809
+ let initialNodes = [];
6810
+ let contentDOM = null;
6811
+ if (editableContent && !contentSelector) {
6812
+ contentDOM = document.createElement("div");
6813
+ contentDOM.setAttribute("data-node-view-content", "");
6814
+ initialNodes = [[contentDOM]];
6815
+ }
6816
+ // 2. Create the Angular Component
6817
+ const componentRef = createComponent(component, {
6818
+ environmentInjector,
6819
+ elementInjector: injector,
6820
+ projectableNodes: initialNodes,
6821
+ });
6822
+ const instance = componentRef.instance;
6823
+ const subscriptions = [];
6824
+ // 3. Initialize TipTap-Aware instances
6825
+ if (instance instanceof AteAngularNodeView) {
6826
+ instance._initNodeView({
6827
+ editor,
6828
+ node,
6829
+ decorations,
6830
+ selected: false,
6831
+ extension,
6832
+ getPos,
6833
+ updateAttributes: attrs => editor.commands.updateAttributes(node.type.name, attrs),
6834
+ deleteNode: () => {
6835
+ const pos = getPos();
6836
+ if (pos !== undefined) {
6837
+ editor.commands.deleteRange({ from: pos, to: pos + node.nodeSize });
6838
+ }
6839
+ },
6840
+ });
6841
+ }
6842
+ // 4. Synchronize Inputs (Handles standard @Input and Signal-based inputs)
6843
+ const syncInputs = (nodeToSync) => {
6844
+ // Combine base inputs from options with dynamic node attributes
6845
+ const mergedInputs = { ...inputs, ...nodeToSync.attrs };
6846
+ Object.entries(mergedInputs).forEach(([key, value]) => {
6847
+ if (key !== "id" && value !== null && value !== undefined) {
6848
+ try {
6849
+ componentRef.setInput(key, value);
6850
+ }
6851
+ catch {
6852
+ // Silently ignore inputs that don't exist on the component
6853
+ }
6854
+ }
6855
+ });
6856
+ };
6857
+ syncInputs(node);
6858
+ // 5. Setup Outputs (Handles EventEmitter and OutputRef)
6859
+ if (onOutput) {
6860
+ Object.entries(instance).forEach(([key, potentialOutput]) => {
6861
+ if (potentialOutput &&
6862
+ typeof potentialOutput
6863
+ .subscribe === "function") {
6864
+ const sub = potentialOutput.subscribe((value) => {
6865
+ onOutput(key, value);
6866
+ });
6867
+ if (sub instanceof Subscription) {
6868
+ subscriptions.push(sub);
6869
+ }
6870
+ }
6871
+ });
6872
+ }
6873
+ // 6. Attach to DOM and ApplicationRef
6874
+ applicationRef.attachView(componentRef.hostView);
6875
+ const componentElement = componentRef.location.nativeElement;
6876
+ // Target specific element for content if selector provided
6877
+ if (editableContent && contentSelector) {
6878
+ contentDOM = componentElement.querySelector(contentSelector);
6879
+ }
6880
+ dom.appendChild(componentElement);
6881
+ // Initial detection to ensure the component is rendered
6882
+ componentRef.changeDetectorRef.detectChanges();
6883
+ // 7. Return the TipTap NodeView Interface
6884
+ return {
6885
+ dom,
6886
+ contentDOM,
6887
+ update: (updatedNode, updatedDecorations) => {
6888
+ if (updatedNode.type !== node.type) {
6889
+ return false;
6890
+ }
6891
+ // Update Aware component signals
6892
+ if (instance instanceof AteAngularNodeView) {
6893
+ instance._updateNodeView(updatedNode, updatedDecorations);
6894
+ }
6895
+ // Update inputs
6896
+ syncInputs(updatedNode);
6897
+ // Notify and Detect changes
6898
+ componentRef.changeDetectorRef.detectChanges();
6899
+ if (options.onUpdate) {
6900
+ options.onUpdate(updatedNode);
6901
+ }
6902
+ return true;
6903
+ },
6904
+ selectNode: () => {
6905
+ if (instance instanceof AteAngularNodeView) {
6906
+ instance._selectNodeView();
6907
+ }
6908
+ dom.classList.add("ProseMirror-selectednode");
6909
+ },
6910
+ deselectNode: () => {
6911
+ if (instance instanceof AteAngularNodeView) {
6912
+ instance._deselectNodeView();
6913
+ }
6914
+ dom.classList.remove("ProseMirror-selectednode");
6915
+ },
6916
+ destroy: () => {
6917
+ if (options.onDestroy) {
6918
+ options.onDestroy();
6919
+ }
6920
+ subscriptions.forEach(s => s.unsubscribe());
6921
+ applicationRef.detachView(componentRef.hostView);
6922
+ componentRef.destroy();
6923
+ },
6924
+ stopEvent: event => {
6925
+ const target = event.target;
6926
+ const isEditable = target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable;
6927
+ return isEditable;
6928
+ },
6929
+ ignoreMutation: mutation => {
6930
+ if (typeof ignoreMutation === "function") {
6931
+ return ignoreMutation(mutation);
6932
+ }
6933
+ return ignoreMutation;
6934
+ },
6935
+ };
6936
+ };
6937
+ }
6938
+
6939
+ const RESERVED_NAMES = [
6940
+ "doc",
6941
+ "paragraph",
6942
+ "text",
6943
+ "hardBreak",
6944
+ "bulletList",
6945
+ "orderedList",
6946
+ "listItem",
6947
+ "blockquote",
6948
+ "codeBlock",
6949
+ "heading",
6950
+ "horizontalRule",
6951
+ ];
6952
+ /**
6953
+ * Derives the TipTap node name and HTML tag from a component class.
6954
+ */
6955
+ function deriveMetadata(component, customName) {
6956
+ let nodeName = customName;
6957
+ if (!nodeName) {
6958
+ nodeName = component.name
6959
+ .replace(/Component$/, "")
6960
+ .replace(/Node$/, "")
6961
+ .replace(/^([A-Z])/, m => m.toLowerCase());
6962
+ console.warn(`[ATE] Auto-deriving node name '${nodeName}' for component ${component.name}. ` +
6963
+ `Provide an explicit 'name' in options to avoid potential naming collisions.`);
6964
+ }
6965
+ if (RESERVED_NAMES.includes(nodeName)) {
6966
+ throw new Error(`[ATE] The name '${nodeName}' is a reserved TipTap node name. ` +
6967
+ `Please provide a unique name for your custom component.`);
6968
+ }
6969
+ const tag = nodeName.toLowerCase().replace(/([A-Z])/g, "-$1");
6970
+ return { nodeName, tag };
6971
+ }
6972
+ /**
6973
+ * Creates TipTap attributes from component inputs (Standard Mode).
6974
+ */
6975
+ function createStandardAttributes(defaultInputs = {}) {
6976
+ const tiptapAttributes = {};
6977
+ Object.entries(defaultInputs).forEach(([key, defaultValue]) => {
6978
+ tiptapAttributes[key] = {
6979
+ default: defaultValue,
6980
+ parseHTML: (element) => {
6981
+ const attr = element.getAttribute(`data-${key}`);
6982
+ if (attr === null) {
6983
+ return defaultValue;
6984
+ }
6985
+ try {
6986
+ return JSON.parse(attr);
6987
+ }
6988
+ catch {
6989
+ return attr;
6990
+ }
6991
+ },
6992
+ renderHTML: (attrs) => {
6993
+ const value = attrs[key];
6994
+ if (value === undefined || value === null) {
6995
+ return {};
6996
+ }
6997
+ const serialized = typeof value === "object" ? JSON.stringify(value) : String(value);
6998
+ return { [`data-${key}`]: serialized };
6999
+ },
7000
+ };
7001
+ });
7002
+ return tiptapAttributes;
7003
+ }
7004
+ /**
7005
+ * Factory to transform an Angular component into a TipTap Node extension.
7006
+ * Supports both "TipTap-Aware" and "Standard" modes.
7007
+ *
7008
+ * @internal
7009
+ */
7010
+ function createAngularComponentExtension(injector, options) {
7011
+ const { component, name: customName, attributes, defaultInputs, contentSelector, contentMode = "block", editableContent = false, group = "block", draggable = true, ignoreMutation = true, onOutput, HTMLAttributes = {}, parseHTML: customParseHTML, renderHTML: customRenderHTML, } = options;
7012
+ const { nodeName, tag } = deriveMetadata(component, customName);
7013
+ const isTipTapAware = Object.prototype.isPrototypeOf.call(AteAngularNodeView, component);
7014
+ const atom = !editableContent;
7015
+ // 1. Prepare Attributes
7016
+ const tiptapAttributes = isTipTapAware
7017
+ ? attributes || {}
7018
+ : createStandardAttributes(defaultInputs);
7019
+ // 2. Create Node Extension
7020
+ return Node$1.create({
7021
+ name: nodeName,
7022
+ group,
7023
+ inline: group === "inline",
7024
+ atom,
7025
+ draggable,
7026
+ content: editableContent ? (contentMode === "inline" ? "inline*" : "block*") : undefined,
7027
+ addAttributes() {
7028
+ return tiptapAttributes;
7029
+ },
7030
+ parseHTML() {
7031
+ if (customParseHTML) {
7032
+ return customParseHTML.call(this);
7033
+ }
7034
+ return [{ tag }, { tag: `div[data-component="${nodeName}"]` }];
7035
+ },
7036
+ renderHTML({ node, HTMLAttributes: attrs }) {
7037
+ if (customRenderHTML) {
7038
+ return customRenderHTML.call(this, { node, HTMLAttributes: attrs });
7039
+ }
7040
+ return [tag, mergeAttributes(HTMLAttributes, attrs, { "data-component": nodeName })];
7041
+ },
7042
+ addNodeView() {
7043
+ return AteNodeViewRenderer(component, {
7044
+ injector,
7045
+ inputs: defaultInputs,
7046
+ wrapperTag: group === "inline" ? "span" : "div",
7047
+ wrapperClass: isTipTapAware
7048
+ ? `ate-node-${nodeName}`
7049
+ : `embedded-component embedded-${nodeName}`,
7050
+ atom,
7051
+ editableContent,
7052
+ contentSelector,
7053
+ contentMode,
7054
+ onOutput,
7055
+ ignoreMutation,
7056
+ });
7057
+ },
7058
+ });
7059
+ }
7060
+
7061
+ /**
7062
+ * Registers ANY Angular component as a TipTap node extension.
7063
+ *
7064
+ * This function is the single public entry point for adding custom components.
7065
+ * It supports two distinct modes:
7066
+ *
7067
+ * 1. **TipTap-Aware Mode** (the component extends `AteAngularNodeView`):
7068
+ * Grants direct access to the TipTap API (`editor`, `node`, `updateAttributes`, etc.) within the component.
7069
+ *
7070
+ * 2. **Standard Mode** (library or legacy components):
7071
+ * Allows using any existing Angular component. Its `@Input()` properties are automatically
7072
+ * synchronized with TipTap node attributes.
7073
+ *
7074
+ * @param injector - The Angular Injector (obtained via `inject(Injector)`)
7075
+ * @param options - Configuration options for the component extension
7076
+ * @returns A TipTap Node extension ready to be used
7077
+ *
7078
+ * @example
7079
+ * ```typescript
7080
+ * registerAngularComponent(injector, {
7081
+ * component: MyComponent,
7082
+ * name: 'myComponent',
7083
+ * defaultInputs: { color: 'blue' }
7084
+ * });
7085
+ * ```
7086
+ */
7087
+ function registerAngularComponent(injector, options) {
7088
+ return createAngularComponentExtension(injector, options);
7089
+ }
7090
+
6676
7091
  /*
6677
7092
  * Public API Surface of tiptap-editor
6678
7093
  */
@@ -6710,5 +7125,5 @@ const DEFAULT_CELL_MENU_CONFIG = ATE_DEFAULT_CELL_MENU_CONFIG;
6710
7125
  * Generated bundle index. Do not edit.
6711
7126
  */
6712
7127
 
6713
- export { ATE_BUBBLE_MENU_KEYS, ATE_CELL_BUBBLE_MENU_KEYS, ATE_DEFAULT_BUBBLE_MENU_CONFIG, ATE_DEFAULT_CELL_MENU_CONFIG, ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ATE_DEFAULT_SLASH_COMMANDS_CONFIG, ATE_DEFAULT_TABLE_MENU_CONFIG, ATE_DEFAULT_TOOLBAR_CONFIG, ATE_IMAGE_BUBBLE_MENU_KEYS, ATE_INITIAL_EDITOR_STATE, ATE_SLASH_COMMAND_KEYS, ATE_TABLE_BUBBLE_MENU_KEYS, ATE_TOOLBAR_KEYS, AngularTiptapEditorComponent, AteColorPickerService, AteDiscoveryCalculator, AteEditorCommandsService, AteI18nService, AteImageCalculator, AteImageService, AteLinkService, AteMarksCalculator, AteNoopValueAccessorDirective, AteSelectionCalculator, AteStructureCalculator, AteTableCalculator, AteColorPickerService as ColorPickerService, DEFAULT_BUBBLE_MENU_CONFIG, DEFAULT_CELL_MENU_CONFIG, DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, DEFAULT_SLASH_COMMANDS_CONFIG, DEFAULT_TABLE_MENU_CONFIG, DEFAULT_TOOLBAR_CONFIG, DiscoveryCalculator, AteEditorCommandsService as EditorCommandsService, INITIAL_EDITOR_STATE, ImageCalculator, AteImageService as ImageService, AteLinkService as LinkService, MarksCalculator, SLASH_COMMAND_KEYS, SelectionCalculator, StructureCalculator, TableCalculator, AteI18nService as TiptapI18nService, createDefaultSlashCommands, filterSlashCommands };
7128
+ export { ATE_BUBBLE_MENU_KEYS, ATE_CELL_BUBBLE_MENU_KEYS, ATE_DEFAULT_BUBBLE_MENU_CONFIG, ATE_DEFAULT_CELL_MENU_CONFIG, ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ATE_DEFAULT_SLASH_COMMANDS_CONFIG, ATE_DEFAULT_TABLE_MENU_CONFIG, ATE_DEFAULT_TOOLBAR_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, AteColorPickerService as ColorPickerService, DEFAULT_BUBBLE_MENU_CONFIG, DEFAULT_CELL_MENU_CONFIG, DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, DEFAULT_SLASH_COMMANDS_CONFIG, DEFAULT_TABLE_MENU_CONFIG, DEFAULT_TOOLBAR_CONFIG, DiscoveryCalculator, AteEditorCommandsService as EditorCommandsService, INITIAL_EDITOR_STATE, ImageCalculator, AteImageService as ImageService, AteLinkService as LinkService, MarksCalculator, SLASH_COMMAND_KEYS, SelectionCalculator, StructureCalculator, TableCalculator, AteI18nService as TiptapI18nService, createAngularComponentExtension, createDefaultSlashCommands, filterSlashCommands, registerAngularComponent };
6714
7129
  //# sourceMappingURL=flogeez-angular-tiptap-editor.mjs.map