@flogeez/angular-tiptap-editor 2.3.0 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +132 -93
  3. package/esm2022/flogeez-angular-tiptap-editor.mjs +5 -0
  4. package/esm2022/lib/ate-editor.provider.mjs +38 -0
  5. package/esm2022/lib/components/bubble-menus/base/ate-base-bubble-menu.mjs +207 -0
  6. package/esm2022/lib/components/bubble-menus/base/ate-base-sub-bubble-menu.mjs +133 -0
  7. package/esm2022/lib/components/bubble-menus/color/ate-color-bubble-menu.component.mjs +365 -0
  8. package/esm2022/lib/components/bubble-menus/image/ate-image-bubble-menu.component.mjs +226 -0
  9. package/esm2022/lib/components/bubble-menus/link/ate-link-bubble-menu.component.mjs +247 -0
  10. package/esm2022/lib/components/bubble-menus/table/ate-cell-bubble-menu.component.mjs +121 -0
  11. package/esm2022/lib/components/bubble-menus/table/ate-table-bubble-menu.component.mjs +266 -0
  12. package/esm2022/lib/components/bubble-menus/text/ate-bubble-menu.component.mjs +294 -0
  13. package/esm2022/lib/components/color-picker/ate-color-picker.component.mjs +122 -0
  14. package/esm2022/lib/components/edit-toggle/ate-edit-toggle.component.mjs +42 -0
  15. package/esm2022/lib/components/editor/angular-tiptap-editor.component.mjs +953 -0
  16. package/esm2022/lib/components/slash-commands/ate-slash-commands.component.mjs +329 -0
  17. package/esm2022/lib/components/toolbar/ate-toolbar.component.mjs +531 -0
  18. package/esm2022/lib/components/ui/ate-button.component.mjs +90 -0
  19. package/esm2022/lib/components/ui/ate-separator.component.mjs +31 -0
  20. package/esm2022/lib/config/ate-editor.config.mjs +76 -0
  21. package/esm2022/lib/config/ate-global-config.token.mjs +6 -0
  22. package/esm2022/lib/config/ate-slash-commands.config.mjs +130 -0
  23. package/esm2022/lib/directives/ate-noop-value-accessor.directive.mjs +40 -0
  24. package/esm2022/lib/extensions/ate-link-click-behavior.extension.mjs +32 -0
  25. package/esm2022/lib/extensions/ate-resizable-image.extension.mjs +270 -0
  26. package/esm2022/lib/extensions/ate-table.extension.mjs +29 -0
  27. package/esm2022/lib/extensions/ate-tiptap-state.extension.mjs +85 -0
  28. package/esm2022/lib/extensions/ate-upload-progress.extension.mjs +195 -0
  29. package/esm2022/lib/extensions/calculators/ate-discovery.calculator.mjs +62 -0
  30. package/esm2022/lib/extensions/calculators/ate-image.calculator.mjs +8 -0
  31. package/esm2022/lib/extensions/calculators/ate-marks.calculator.mjs +75 -0
  32. package/esm2022/lib/extensions/calculators/ate-selection.calculator.mjs +35 -0
  33. package/esm2022/lib/extensions/calculators/ate-structure.calculator.mjs +34 -0
  34. package/esm2022/lib/extensions/calculators/ate-table.calculator.mjs +38 -0
  35. package/esm2022/lib/models/ate-bubble-menu.model.mjs +49 -0
  36. package/esm2022/lib/models/ate-editor-config.model.mjs +2 -0
  37. package/esm2022/lib/models/ate-editor-state.model.mjs +90 -0
  38. package/esm2022/lib/models/ate-image.model.mjs +2 -0
  39. package/esm2022/lib/models/ate-toolbar.model.mjs +35 -0
  40. package/esm2022/lib/node-view/ate-angular-node-view.mjs +97 -0
  41. package/esm2022/lib/node-view/ate-injector.registry.mjs +16 -0
  42. package/esm2022/lib/node-view/ate-node-view.factory.mjs +125 -0
  43. package/esm2022/lib/node-view/ate-node-view.models.mjs +2 -0
  44. package/esm2022/lib/node-view/ate-node-view.renderer.mjs +154 -0
  45. package/esm2022/lib/node-view/ate-register-angular-component.mjs +49 -0
  46. package/esm2022/lib/services/ate-color-picker.service.mjs +193 -0
  47. package/esm2022/lib/services/ate-editor-commands.service.mjs +465 -0
  48. package/esm2022/lib/services/ate-i18n.service.mjs +410 -0
  49. package/esm2022/lib/services/ate-image.service.mjs +368 -0
  50. package/esm2022/lib/services/ate-link.service.mjs +97 -0
  51. package/esm2022/lib/utils/ate-color.utils.mjs +60 -0
  52. package/esm2022/public-api.mjs +93 -0
  53. package/fesm2022/flogeez-angular-tiptap-editor.mjs +1178 -1100
  54. package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
  55. package/index.d.ts +3 -1562
  56. package/lib/ate-editor.provider.d.ts +21 -0
  57. package/lib/components/bubble-menus/base/ate-base-bubble-menu.d.ts +71 -0
  58. package/lib/components/bubble-menus/base/ate-base-sub-bubble-menu.d.ts +60 -0
  59. package/lib/components/bubble-menus/color/ate-color-bubble-menu.component.d.ts +77 -0
  60. package/lib/components/bubble-menus/image/ate-image-bubble-menu.component.d.ts +52 -0
  61. package/lib/components/bubble-menus/link/ate-link-bubble-menu.component.d.ts +55 -0
  62. package/lib/components/bubble-menus/table/ate-cell-bubble-menu.component.d.ts +12 -0
  63. package/lib/components/bubble-menus/table/ate-table-bubble-menu.component.d.ts +24 -0
  64. package/lib/components/bubble-menus/text/ate-bubble-menu.component.d.ts +53 -0
  65. package/lib/components/color-picker/ate-color-picker.component.d.ts +54 -0
  66. package/lib/components/edit-toggle/ate-edit-toggle.component.d.ts +13 -0
  67. package/lib/components/editor/angular-tiptap-editor.component.d.ts +235 -0
  68. package/lib/components/slash-commands/ate-slash-commands.component.d.ts +43 -0
  69. package/lib/components/toolbar/ate-toolbar.component.d.ts +47 -0
  70. package/lib/components/ui/ate-button.component.d.ts +25 -0
  71. package/lib/components/ui/ate-separator.component.d.ts +7 -0
  72. package/lib/config/ate-editor.config.d.ts +7 -0
  73. package/lib/config/ate-global-config.token.d.ts +6 -0
  74. package/lib/config/ate-slash-commands.config.d.ts +41 -0
  75. package/lib/directives/ate-noop-value-accessor.directive.d.ts +13 -0
  76. package/lib/extensions/ate-link-click-behavior.extension.d.ts +2 -0
  77. package/lib/extensions/ate-resizable-image.extension.d.ts +27 -0
  78. package/lib/extensions/ate-table.extension.d.ts +2 -0
  79. package/lib/extensions/ate-tiptap-state.extension.d.ts +7 -0
  80. package/lib/extensions/ate-upload-progress.extension.d.ts +7 -0
  81. package/lib/extensions/calculators/ate-discovery.calculator.d.ts +7 -0
  82. package/lib/extensions/calculators/ate-image.calculator.d.ts +2 -0
  83. package/lib/extensions/calculators/ate-marks.calculator.d.ts +2 -0
  84. package/lib/extensions/calculators/ate-selection.calculator.d.ts +2 -0
  85. package/lib/extensions/calculators/ate-structure.calculator.d.ts +2 -0
  86. package/lib/extensions/calculators/ate-table.calculator.d.ts +2 -0
  87. package/lib/models/ate-bubble-menu.model.d.ts +33 -0
  88. package/lib/models/ate-editor-config.model.d.ts +100 -0
  89. package/lib/models/ate-editor-state.model.d.ts +109 -0
  90. package/lib/models/ate-image.model.d.ts +104 -0
  91. package/lib/models/ate-toolbar.model.d.ts +18 -0
  92. package/lib/node-view/ate-angular-node-view.d.ts +115 -0
  93. package/lib/node-view/ate-injector.registry.d.ts +3 -0
  94. package/lib/node-view/ate-node-view.factory.d.ts +10 -0
  95. package/lib/node-view/ate-node-view.models.d.ts +138 -0
  96. package/lib/node-view/ate-node-view.renderer.d.ts +23 -0
  97. package/lib/node-view/ate-register-angular-component.d.ts +35 -0
  98. package/lib/services/ate-color-picker.service.d.ts +65 -0
  99. package/lib/services/ate-editor-commands.service.d.ts +72 -0
  100. package/lib/services/ate-i18n.service.d.ts +394 -0
  101. package/lib/services/ate-image.service.d.ts +71 -0
  102. package/lib/services/ate-link.service.d.ts +42 -0
  103. package/lib/utils/ate-color.utils.d.ts +12 -0
  104. package/package.json +3 -1
  105. package/public-api.d.ts +112 -0
@@ -1,26 +1,26 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, output, ChangeDetectionStrategy, Component, signal, computed, Injectable, inject, viewChild, effect, Directive, DestroyRef, untracked, ApplicationRef, EnvironmentInjector, createComponent } from '@angular/core';
2
+ import { input, output, ChangeDetectionStrategy, Component, signal, computed, Injectable, inject, viewChild, effect, Directive, ApplicationRef, EnvironmentInjector, createComponent, InjectionToken, DestroyRef, Injector, untracked, makeEnvironmentProviders, APP_INITIALIZER } 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
- import StarterKit from '@tiptap/starter-kit';
6
- import Placeholder from '@tiptap/extension-placeholder';
7
- import CharacterCount from '@tiptap/extension-character-count';
8
- import Underline from '@tiptap/extension-underline';
9
- import Superscript from '@tiptap/extension-superscript';
10
- import Subscript from '@tiptap/extension-subscript';
11
- import TextAlign from '@tiptap/extension-text-align';
12
- import Link from '@tiptap/extension-link';
13
- import Highlight from '@tiptap/extension-highlight';
14
- import TextStyle from '@tiptap/extension-text-style';
15
- import Color from '@tiptap/extension-color';
5
+ import { StarterKit } from '@tiptap/starter-kit';
6
+ import { Placeholder } from '@tiptap/extension-placeholder';
7
+ import { CharacterCount } from '@tiptap/extension-character-count';
8
+ import { Underline } from '@tiptap/extension-underline';
9
+ import { Superscript } from '@tiptap/extension-superscript';
10
+ import { Subscript } from '@tiptap/extension-subscript';
11
+ import { TextAlign } from '@tiptap/extension-text-align';
12
+ import { Link } from '@tiptap/extension-link';
13
+ import { Highlight } from '@tiptap/extension-highlight';
14
+ import { TextStyle } from '@tiptap/extension-text-style';
15
+ import { Color } from '@tiptap/extension-color';
16
16
  import OfficePaste from '@intevation/tiptap-extension-office-paste';
17
17
  import { Plugin, PluginKey, TextSelection, NodeSelection } from '@tiptap/pm/state';
18
18
  import { DecorationSet, Decoration } from '@tiptap/pm/view';
19
- import Table from '@tiptap/extension-table';
20
- import TableRow from '@tiptap/extension-table-row';
21
- import TableCell from '@tiptap/extension-table-cell';
22
- import TableHeader from '@tiptap/extension-table-header';
23
- import { isObservable, firstValueFrom, concat, defer, of, tap, Subscription } from 'rxjs';
19
+ import { Table } from '@tiptap/extension-table';
20
+ import { TableRow } from '@tiptap/extension-table-row';
21
+ import { TableCell } from '@tiptap/extension-table-cell';
22
+ import { TableHeader } from '@tiptap/extension-table-header';
23
+ import { isObservable, firstValueFrom, Subscription, concat, defer, of, tap } 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';
@@ -687,23 +687,23 @@ const AteTiptapStateExtension = Extension.create({
687
687
  class AteButtonComponent {
688
688
  constructor() {
689
689
  // Inputs
690
- this.icon = input("", ...(ngDevMode ? [{ debugName: "icon" }] : []));
691
- this.title = input.required(...(ngDevMode ? [{ debugName: "title" }] : []));
692
- this.active = input(false, ...(ngDevMode ? [{ debugName: "active" }] : []));
693
- this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
694
- this.color = input(...(ngDevMode ? [undefined, { debugName: "color" }] : []));
695
- this.backgroundColor = input(...(ngDevMode ? [undefined, { debugName: "backgroundColor" }] : []));
696
- this.variant = input("default", ...(ngDevMode ? [{ debugName: "variant" }] : []));
697
- this.size = input("medium", ...(ngDevMode ? [{ debugName: "size" }] : []));
698
- this.iconSize = input("medium", ...(ngDevMode ? [{ debugName: "iconSize" }] : []));
690
+ this.icon = input("");
691
+ this.title = input.required();
692
+ this.active = input(false);
693
+ this.disabled = input(false);
694
+ this.color = input();
695
+ this.backgroundColor = input();
696
+ this.variant = input("default");
697
+ this.size = input("medium");
698
+ this.iconSize = input("medium");
699
699
  // Outputs
700
700
  this.buttonClick = output();
701
701
  }
702
702
  onMouseDown(event) {
703
703
  event.preventDefault();
704
704
  }
705
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
706
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AteButtonComponent, isStandalone: true, selector: "ate-button", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, backgroundColor: { classPropertyName: "backgroundColor", publicName: "backgroundColor", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, iconSize: { classPropertyName: "iconSize", publicName: "iconSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { buttonClick: "buttonClick" }, ngImport: i0, template: `
705
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
706
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AteButtonComponent, isStandalone: true, selector: "ate-button", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, backgroundColor: { classPropertyName: "backgroundColor", publicName: "backgroundColor", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, iconSize: { classPropertyName: "iconSize", publicName: "iconSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { buttonClick: "buttonClick" }, ngImport: i0, template: `
707
707
  <button
708
708
  class="ate-button"
709
709
  [class.is-active]="active()"
@@ -736,7 +736,7 @@ class AteButtonComponent {
736
736
  </button>
737
737
  `, isInline: true, styles: [".ate-button{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;background:transparent;border-radius:var(--ate-sub-border-radius, 8px);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);color:var(--ate-toolbar-button-color, var(--ate-text-secondary));position:relative;overflow:hidden}.ate-button:before{content:\"\";position:absolute;inset:0;background:var(--ate-primary);opacity:0;transition:opacity .2s ease;border-radius:var(--ate-sub-border-radius, 8px)}.ate-button:hover:not(.has-custom-color){color:var(--ate-toolbar-button-active-color, var(--ate-primary));background:var(--ate-toolbar-button-hover-background, transparent);transform:translateY(-1px)}.ate-button.has-custom-color:hover:not(.has-custom-bg){background:var(--ate-toolbar-button-hover-background, transparent);transform:translateY(-1px)}.ate-button.has-custom-bg:hover{transform:translateY(-1px);filter:brightness(.9)}.ate-button:hover:before{opacity:.1}.ate-button:active{transform:translateY(0)}.ate-button.is-active:not(.has-custom-color){color:var(--ate-toolbar-button-active-color, var(--ate-primary));background:var(--ate-toolbar-button-active-background, var(--ate-primary-light))}.ate-button.is-active.has-custom-color{background:var(--ate-toolbar-button-active-background, var(--ate-primary-light))}.ate-button:disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.ate-button .material-symbols-outlined{font-size:20px;position:relative;z-index:1}.ate-button .material-symbols-outlined.icon-small{font-size:16px}.ate-button .material-symbols-outlined.icon-medium{font-size:20px}.ate-button .material-symbols-outlined.icon-large{font-size:24px}.ate-button.text-button{width:auto;padding:0 12px;font-size:14px;font-weight:500;gap:8px}.ate-button.color-button{width:28px;height:28px;border-radius:50%;border:2px solid transparent;transition:all .2s ease}.ate-button.color-button:hover{border-color:var(--ate-border);transform:scale(1.1)}.ate-button.color-button.is-active{border-color:var(--ate-primary);box-shadow:0 0 0 2px var(--ate-primary-light)}.ate-button.danger{color:var(--ate-error-color, #ef4444)}.ate-button.danger:hover{color:var(--ate-error-color, #ef4444);background:var(--ate-error-bg, rgba(239, 68, 68, .1))}.ate-button.danger:before{background:var(--ate-error-color, #ef4444)}.ate-button.small{width:24px;height:24px}.ate-button.medium{width:32px;height:32px}.ate-button.large{width:40px;height:40px}@keyframes pulse{0%,to{box-shadow:0 0 0 0 var(--ate-primary-light-alpha)}50%{box-shadow:0 0 0 4px transparent}}.ate-button.is-active.pulse{animation:pulse 2s infinite}@media (max-width: 768px){.ate-button{width:32px;height:32px}.ate-button .material-symbols-outlined{font-size:18px}.ate-button.text-button{padding:0 8px;font-size:13px}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
738
738
  }
739
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteButtonComponent, decorators: [{
739
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteButtonComponent, decorators: [{
740
740
  type: Component,
741
741
  args: [{ selector: "ate-button", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
742
742
  <button
@@ -770,15 +770,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
770
770
  <ng-content></ng-content>
771
771
  </button>
772
772
  `, styles: [".ate-button{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;background:transparent;border-radius:var(--ate-sub-border-radius, 8px);cursor:pointer;transition:all .2s cubic-bezier(.4,0,.2,1);color:var(--ate-toolbar-button-color, var(--ate-text-secondary));position:relative;overflow:hidden}.ate-button:before{content:\"\";position:absolute;inset:0;background:var(--ate-primary);opacity:0;transition:opacity .2s ease;border-radius:var(--ate-sub-border-radius, 8px)}.ate-button:hover:not(.has-custom-color){color:var(--ate-toolbar-button-active-color, var(--ate-primary));background:var(--ate-toolbar-button-hover-background, transparent);transform:translateY(-1px)}.ate-button.has-custom-color:hover:not(.has-custom-bg){background:var(--ate-toolbar-button-hover-background, transparent);transform:translateY(-1px)}.ate-button.has-custom-bg:hover{transform:translateY(-1px);filter:brightness(.9)}.ate-button:hover:before{opacity:.1}.ate-button:active{transform:translateY(0)}.ate-button.is-active:not(.has-custom-color){color:var(--ate-toolbar-button-active-color, var(--ate-primary));background:var(--ate-toolbar-button-active-background, var(--ate-primary-light))}.ate-button.is-active.has-custom-color{background:var(--ate-toolbar-button-active-background, var(--ate-primary-light))}.ate-button:disabled{opacity:.4;cursor:not-allowed;pointer-events:none}.ate-button .material-symbols-outlined{font-size:20px;position:relative;z-index:1}.ate-button .material-symbols-outlined.icon-small{font-size:16px}.ate-button .material-symbols-outlined.icon-medium{font-size:20px}.ate-button .material-symbols-outlined.icon-large{font-size:24px}.ate-button.text-button{width:auto;padding:0 12px;font-size:14px;font-weight:500;gap:8px}.ate-button.color-button{width:28px;height:28px;border-radius:50%;border:2px solid transparent;transition:all .2s ease}.ate-button.color-button:hover{border-color:var(--ate-border);transform:scale(1.1)}.ate-button.color-button.is-active{border-color:var(--ate-primary);box-shadow:0 0 0 2px var(--ate-primary-light)}.ate-button.danger{color:var(--ate-error-color, #ef4444)}.ate-button.danger:hover{color:var(--ate-error-color, #ef4444);background:var(--ate-error-bg, rgba(239, 68, 68, .1))}.ate-button.danger:before{background:var(--ate-error-color, #ef4444)}.ate-button.small{width:24px;height:24px}.ate-button.medium{width:32px;height:32px}.ate-button.large{width:40px;height:40px}@keyframes pulse{0%,to{box-shadow:0 0 0 0 var(--ate-primary-light-alpha)}50%{box-shadow:0 0 0 4px transparent}}.ate-button.is-active.pulse{animation:pulse 2s infinite}@media (max-width: 768px){.ate-button{width:32px;height:32px}.ate-button .material-symbols-outlined{font-size:18px}.ate-button.text-button{padding:0 8px;font-size:13px}}\n"] }]
773
- }], 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"] }] } });
773
+ }] });
774
774
 
775
775
  class AteSeparatorComponent {
776
776
  constructor() {
777
- this.orientation = input("vertical", ...(ngDevMode ? [{ debugName: "orientation" }] : []));
778
- this.size = input("medium", ...(ngDevMode ? [{ debugName: "size" }] : []));
777
+ this.orientation = input("vertical");
778
+ this.size = input("medium");
779
779
  }
780
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteSeparatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
781
- 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: `
780
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteSeparatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
781
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.14", 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: `
782
782
  <div
783
783
  class="ate-separator"
784
784
  [class.vertical]="orientation() === 'vertical'"
@@ -788,7 +788,7 @@ class AteSeparatorComponent {
788
788
  [class.large]="size() === 'large'"></div>
789
789
  `, 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 }); }
790
790
  }
791
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteSeparatorComponent, decorators: [{
791
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteSeparatorComponent, decorators: [{
792
792
  type: Component,
793
793
  args: [{ selector: "ate-separator", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
794
794
  <div
@@ -799,7 +799,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
799
799
  [class.medium]="size() === 'medium'"
800
800
  [class.large]="size() === 'large'"></div>
801
801
  `, 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"] }]
802
- }], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
802
+ }] });
803
803
 
804
804
  const ENGLISH_TRANSLATIONS = {
805
805
  toolbar: {
@@ -1137,25 +1137,25 @@ const FRENCH_TRANSLATIONS = {
1137
1137
  };
1138
1138
  class AteI18nService {
1139
1139
  constructor() {
1140
- this._currentLocale = signal("en", ...(ngDevMode ? [{ debugName: "_currentLocale" }] : []));
1140
+ this._currentLocale = signal("en");
1141
1141
  this._translations = signal({
1142
1142
  en: ENGLISH_TRANSLATIONS,
1143
1143
  fr: FRENCH_TRANSLATIONS,
1144
- }, ...(ngDevMode ? [{ debugName: "_translations" }] : []));
1144
+ });
1145
1145
  // Public signals
1146
1146
  this.currentLocale = this._currentLocale.asReadonly();
1147
1147
  /** All loaded translations (useful for dynamic key access) */
1148
1148
  this.allTranslations = this._translations.asReadonly();
1149
- this.translations = computed(() => this._translations()[this._currentLocale()], ...(ngDevMode ? [{ debugName: "translations" }] : []));
1149
+ this.translations = computed(() => this._translations()[this._currentLocale()]);
1150
1150
  // Fast translation methods
1151
- this.t = computed(() => this.translations(), ...(ngDevMode ? [{ debugName: "t" }] : []));
1152
- this.toolbar = computed(() => this.translations().toolbar, ...(ngDevMode ? [{ debugName: "toolbar" }] : []));
1153
- this.bubbleMenu = computed(() => this.translations().bubbleMenu, ...(ngDevMode ? [{ debugName: "bubbleMenu" }] : []));
1154
- this.slashCommands = computed(() => this.translations().slashCommands, ...(ngDevMode ? [{ debugName: "slashCommands" }] : []));
1155
- this.table = computed(() => this.translations().table, ...(ngDevMode ? [{ debugName: "table" }] : []));
1156
- this.imageUpload = computed(() => this.translations().imageUpload, ...(ngDevMode ? [{ debugName: "imageUpload" }] : []));
1157
- this.editor = computed(() => this.translations().editor, ...(ngDevMode ? [{ debugName: "editor" }] : []));
1158
- this.common = computed(() => this.translations().common, ...(ngDevMode ? [{ debugName: "common" }] : []));
1151
+ this.t = computed(() => this.translations());
1152
+ this.toolbar = computed(() => this.translations().toolbar);
1153
+ this.bubbleMenu = computed(() => this.translations().bubbleMenu);
1154
+ this.slashCommands = computed(() => this.translations().slashCommands);
1155
+ this.table = computed(() => this.translations().table);
1156
+ this.imageUpload = computed(() => this.translations().imageUpload);
1157
+ this.editor = computed(() => this.translations().editor);
1158
+ this.common = computed(() => this.translations().common);
1159
1159
  // Automatically detect browser language
1160
1160
  this.detectBrowserLanguage();
1161
1161
  }
@@ -1199,10 +1199,10 @@ class AteI18nService {
1199
1199
  getSlashCommand(key) {
1200
1200
  return this.translations().slashCommands[key];
1201
1201
  }
1202
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteI18nService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1203
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteI18nService, providedIn: "root" }); }
1202
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteI18nService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1203
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteI18nService, providedIn: "root" }); }
1204
1204
  }
1205
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteI18nService, decorators: [{
1205
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteI18nService, decorators: [{
1206
1206
  type: Injectable,
1207
1207
  args: [{
1208
1208
  providedIn: "root",
@@ -1212,16 +1212,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
1212
1212
  class AteImageService {
1213
1213
  constructor() {
1214
1214
  /** Signals for image state */
1215
- this.selectedImage = signal(null, ...(ngDevMode ? [{ debugName: "selectedImage" }] : []));
1216
- this.isImageSelected = computed(() => this.selectedImage() !== null, ...(ngDevMode ? [{ debugName: "isImageSelected" }] : []));
1215
+ this.selectedImage = signal(null);
1216
+ this.isImageSelected = computed(() => this.selectedImage() !== null);
1217
1217
  /** Resizing state */
1218
- this.isResizing = signal(false, ...(ngDevMode ? [{ debugName: "isResizing" }] : []));
1218
+ this.isResizing = signal(false);
1219
1219
  this.i18n = inject(AteI18nService);
1220
1220
  this.t = this.i18n.imageUpload;
1221
1221
  /** Upload state signals */
1222
- this.isUploading = signal(false, ...(ngDevMode ? [{ debugName: "isUploading" }] : []));
1223
- this.uploadProgress = signal(0, ...(ngDevMode ? [{ debugName: "uploadProgress" }] : []));
1224
- this.uploadMessage = signal("", ...(ngDevMode ? [{ debugName: "uploadMessage" }] : []));
1222
+ this.isUploading = signal(false);
1223
+ this.uploadProgress = signal(0);
1224
+ this.uploadMessage = signal("");
1225
1225
  /**
1226
1226
  * Custom upload handler.
1227
1227
  * If set, this handler replaces the default base64 conversion.
@@ -1566,10 +1566,10 @@ class AteImageService {
1566
1566
  this.selectImage(ed);
1567
1567
  }, this.t().replacingImage, options);
1568
1568
  }
1569
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteImageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1570
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteImageService }); }
1569
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1570
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageService }); }
1571
1571
  }
1572
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteImageService, decorators: [{
1572
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageService, decorators: [{
1573
1573
  type: Injectable
1574
1574
  }] });
1575
1575
 
@@ -1640,11 +1640,11 @@ class AteColorPickerService {
1640
1640
  // State Signals (owned by this service)
1641
1641
  // ============================================
1642
1642
  /** Current edit mode: null when closed, 'text' or 'highlight' when open */
1643
- this.editMode = signal(null, ...(ngDevMode ? [{ debugName: "editMode" }] : []));
1643
+ this.editMode = signal(null);
1644
1644
  /** Reference to the element that triggered the menu (for anchoring) */
1645
- this.menuTrigger = signal(null, ...(ngDevMode ? [{ debugName: "menuTrigger" }] : []));
1645
+ this.menuTrigger = signal(null);
1646
1646
  /** Whether the user is currently interacting with the picker UI (e.g. typing) */
1647
- this.isInteracting = signal(false, ...(ngDevMode ? [{ debugName: "isInteracting" }] : []));
1647
+ this.isInteracting = signal(false);
1648
1648
  }
1649
1649
  // ============================================
1650
1650
  // Menu Lifecycle Methods
@@ -1816,10 +1816,10 @@ class AteColorPickerService {
1816
1816
  getContrastColor(color) {
1817
1817
  return getContrastColor(color);
1818
1818
  }
1819
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteColorPickerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1820
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteColorPickerService }); }
1819
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteColorPickerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1820
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteColorPickerService }); }
1821
1821
  }
1822
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteColorPickerService, decorators: [{
1822
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteColorPickerService, decorators: [{
1823
1823
  type: Injectable
1824
1824
  }] });
1825
1825
 
@@ -1829,11 +1829,11 @@ class AteLinkService {
1829
1829
  // State Signals (owned by this service)
1830
1830
  // ============================================
1831
1831
  /** Whether link edit mode is active */
1832
- this.editMode = signal(false, ...(ngDevMode ? [{ debugName: "editMode" }] : []));
1832
+ this.editMode = signal(false);
1833
1833
  /** Reference to the element that triggered the menu (for anchoring) */
1834
- this.menuTrigger = signal(null, ...(ngDevMode ? [{ debugName: "menuTrigger" }] : []));
1834
+ this.menuTrigger = signal(null);
1835
1835
  /** Whether the user is currently interacting with the link UI (input focus) */
1836
- this.isInteracting = signal(false, ...(ngDevMode ? [{ debugName: "isInteracting" }] : []));
1836
+ this.isInteracting = signal(false);
1837
1837
  }
1838
1838
  // ============================================
1839
1839
  // Menu Lifecycle Methods
@@ -1911,10 +1911,10 @@ class AteLinkService {
1911
1911
  editor.chain().focus().extendMarkRange("link").unsetLink().run();
1912
1912
  this.close();
1913
1913
  }
1914
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteLinkService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1915
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteLinkService }); }
1914
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteLinkService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1915
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteLinkService }); }
1916
1916
  }
1917
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteLinkService, decorators: [{
1917
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteLinkService, decorators: [{
1918
1918
  type: Injectable
1919
1919
  }] });
1920
1920
 
@@ -1923,90 +1923,53 @@ class AteEditorCommandsService {
1923
1923
  this.imageService = inject(AteImageService);
1924
1924
  this.colorPickerSvc = inject(AteColorPickerService);
1925
1925
  this.linkSvc = inject(AteLinkService);
1926
- this._editorState = signal(ATE_INITIAL_EDITOR_STATE, ...(ngDevMode ? [{ debugName: "_editorState", equal: (a, b) => {
1927
- // 1. Primitive global states
1928
- if (a.isFocused !== b.isFocused || a.isEditable !== b.isEditable) {
1929
- return false;
1930
- }
1931
- // 2. Detailed selection comparison
1932
- if (a.selection.from !== b.selection.from ||
1933
- a.selection.to !== b.selection.to ||
1934
- a.selection.type !== b.selection.type ||
1935
- a.selection.empty !== b.selection.empty ||
1936
- a.selection.isSingleCell !== b.selection.isSingleCell) {
1937
- return false;
1938
- }
1939
- // Helper for object comparison
1940
- const isRecordEqual = (objA, objB) => {
1941
- const keysA = Object.keys(objA);
1942
- const keysB = Object.keys(objB);
1943
- if (keysA.length !== keysB.length) {
1944
- return false;
1945
- }
1946
- return keysA.every(key => objA[key] === objB[key]);
1947
- };
1948
- // 3. Compare sub-states (marks, can, nodes)
1949
- if (!isRecordEqual(a.marks, b.marks)) {
1950
- return false;
1951
- }
1952
- if (!isRecordEqual(a.can, b.can)) {
1953
- return false;
1954
- }
1955
- if (!isRecordEqual(a.nodes, b.nodes)) {
1956
- return false;
1957
- }
1958
- // 4. Compare custom extension states
1959
- if (!isRecordEqual(a.custom, b.custom)) {
1960
- return false;
1961
- }
1962
- return true;
1963
- } }] : [{
1964
- equal: (a, b) => {
1965
- // 1. Primitive global states
1966
- if (a.isFocused !== b.isFocused || a.isEditable !== b.isEditable) {
1967
- return false;
1968
- }
1969
- // 2. Detailed selection comparison
1970
- if (a.selection.from !== b.selection.from ||
1971
- a.selection.to !== b.selection.to ||
1972
- a.selection.type !== b.selection.type ||
1973
- a.selection.empty !== b.selection.empty ||
1974
- a.selection.isSingleCell !== b.selection.isSingleCell) {
1975
- return false;
1976
- }
1977
- // Helper for object comparison
1978
- const isRecordEqual = (objA, objB) => {
1979
- const keysA = Object.keys(objA);
1980
- const keysB = Object.keys(objB);
1981
- if (keysA.length !== keysB.length) {
1982
- return false;
1983
- }
1984
- return keysA.every(key => objA[key] === objB[key]);
1985
- };
1986
- // 3. Compare sub-states (marks, can, nodes)
1987
- if (!isRecordEqual(a.marks, b.marks)) {
1988
- return false;
1989
- }
1990
- if (!isRecordEqual(a.can, b.can)) {
1991
- return false;
1992
- }
1993
- if (!isRecordEqual(a.nodes, b.nodes)) {
1994
- return false;
1995
- }
1996
- // 4. Compare custom extension states
1997
- if (!isRecordEqual(a.custom, b.custom)) {
1926
+ this._editorState = signal(ATE_INITIAL_EDITOR_STATE, {
1927
+ equal: (a, b) => {
1928
+ // 1. Primitive global states
1929
+ if (a.isFocused !== b.isFocused || a.isEditable !== b.isEditable) {
1930
+ return false;
1931
+ }
1932
+ // 2. Detailed selection comparison
1933
+ if (a.selection.from !== b.selection.from ||
1934
+ a.selection.to !== b.selection.to ||
1935
+ a.selection.type !== b.selection.type ||
1936
+ a.selection.empty !== b.selection.empty ||
1937
+ a.selection.isSingleCell !== b.selection.isSingleCell) {
1938
+ return false;
1939
+ }
1940
+ // Helper for object comparison
1941
+ const isRecordEqual = (objA, objB) => {
1942
+ const keysA = Object.keys(objA);
1943
+ const keysB = Object.keys(objB);
1944
+ if (keysA.length !== keysB.length) {
1998
1945
  return false;
1999
1946
  }
2000
- return true;
2001
- },
2002
- }]));
1947
+ return keysA.every(key => objA[key] === objB[key]);
1948
+ };
1949
+ // 3. Compare sub-states (marks, can, nodes)
1950
+ if (!isRecordEqual(a.marks, b.marks)) {
1951
+ return false;
1952
+ }
1953
+ if (!isRecordEqual(a.can, b.can)) {
1954
+ return false;
1955
+ }
1956
+ if (!isRecordEqual(a.nodes, b.nodes)) {
1957
+ return false;
1958
+ }
1959
+ // 4. Compare custom extension states
1960
+ if (!isRecordEqual(a.custom, b.custom)) {
1961
+ return false;
1962
+ }
1963
+ return true;
1964
+ },
1965
+ });
2003
1966
  /** Exposed editor state as a readonly signal */
2004
1967
  this.editorState = this._editorState.asReadonly();
2005
1968
  // ============================================
2006
1969
  // Toolbar Interaction State
2007
1970
  // ============================================
2008
1971
  /** Signal to track when the toolbar is being hovered/interacted with */
2009
- this._isToolbarInteracting = signal(false, ...(ngDevMode ? [{ debugName: "_isToolbarInteracting" }] : []));
1972
+ this._isToolbarInteracting = signal(false);
2010
1973
  this.isToolbarInteracting = this._isToolbarInteracting.asReadonly();
2011
1974
  // Access to ImageService states as readonly signals for UI binding
2012
1975
  this.isUploading = this.imageService.isUploading.asReadonly();
@@ -2407,19 +2370,19 @@ class AteEditorCommandsService {
2407
2370
  throw error;
2408
2371
  }
2409
2372
  }
2410
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteEditorCommandsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2411
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteEditorCommandsService }); }
2373
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteEditorCommandsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2374
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteEditorCommandsService }); }
2412
2375
  }
2413
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteEditorCommandsService, decorators: [{
2376
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteEditorCommandsService, decorators: [{
2414
2377
  type: Injectable
2415
2378
  }] });
2416
2379
 
2417
2380
  class AteColorPickerComponent {
2418
2381
  constructor() {
2419
- this.editor = input.required(...(ngDevMode ? [{ debugName: "editor" }] : []));
2420
- this.mode = input("text", ...(ngDevMode ? [{ debugName: "mode" }] : []));
2421
- this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
2422
- this.anchorToText = input(false, ...(ngDevMode ? [{ debugName: "anchorToText" }] : []));
2382
+ this.editor = input.required();
2383
+ this.mode = input("text");
2384
+ this.disabled = input(false);
2385
+ this.anchorToText = input(false);
2423
2386
  this.colorPickerSvc = inject(AteColorPickerService);
2424
2387
  this.i18nService = inject(AteI18nService);
2425
2388
  this.editorCommands = inject(AteEditorCommandsService);
@@ -2429,14 +2392,14 @@ class AteColorPickerComponent {
2429
2392
  const marks = this.state().marks;
2430
2393
  const color = this.mode() === "text" ? marks.computedColor : marks.computedBackground;
2431
2394
  return color || (this.mode() === "text" ? "#000000" : "#ffff00");
2432
- }, ...(ngDevMode ? [{ debugName: "currentColor" }] : []));
2395
+ });
2433
2396
  this.hasColorApplied = computed(() => {
2434
2397
  const marks = this.state().marks;
2435
2398
  return (this.mode() === "text" ? marks.color : marks.background) !== null;
2436
- }, ...(ngDevMode ? [{ debugName: "hasColorApplied" }] : []));
2399
+ });
2437
2400
  this.buttonIcon = computed(() => {
2438
2401
  return this.mode() === "text" ? "format_color_text" : "format_color_fill";
2439
- }, ...(ngDevMode ? [{ debugName: "buttonIcon" }] : []));
2402
+ });
2440
2403
  this.buttonBgColor = computed(() => {
2441
2404
  const color = this.currentColor();
2442
2405
  if (this.mode() === "highlight") {
@@ -2447,7 +2410,7 @@ class AteColorPickerComponent {
2447
2410
  return "#030617";
2448
2411
  }
2449
2412
  return "";
2450
- }, ...(ngDevMode ? [{ debugName: "buttonBgColor" }] : []));
2413
+ });
2451
2414
  this.buttonTextColor = computed(() => {
2452
2415
  const color = this.currentColor();
2453
2416
  if (this.mode() === "text") {
@@ -2457,7 +2420,7 @@ class AteColorPickerComponent {
2457
2420
  return this.colorPickerSvc.getLuminance(color) > 128 ? "#000000" : "#ffffff";
2458
2421
  }
2459
2422
  return "var(--ate-text-secondary)";
2460
- }, ...(ngDevMode ? [{ debugName: "buttonTextColor" }] : []));
2423
+ });
2461
2424
  }
2462
2425
  onToggle(event) {
2463
2426
  // If anchorToText is true, we don't pass the event so it defaults to text selection anchoring
@@ -2475,8 +2438,8 @@ class AteColorPickerComponent {
2475
2438
  }
2476
2439
  this.colorPickerSvc.close();
2477
2440
  }
2478
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteColorPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2479
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AteColorPickerComponent, isStandalone: true, selector: "ate-color-picker", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, anchorToText: { classPropertyName: "anchorToText", publicName: "anchorToText", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
2441
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteColorPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2442
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AteColorPickerComponent, isStandalone: true, selector: "ate-color-picker", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, anchorToText: { classPropertyName: "anchorToText", publicName: "anchorToText", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
2480
2443
  <div class="color-picker-wrapper">
2481
2444
  <div class="color-picker-container" [class.is-highlight]="mode() === 'highlight'">
2482
2445
  <ate-button
@@ -2501,7 +2464,7 @@ class AteColorPickerComponent {
2501
2464
  </div>
2502
2465
  `, isInline: true, styles: [".color-picker-wrapper{position:relative;display:inline-block}.color-picker-container{position:relative;display:inline-flex;align-items:center}.btn-clear-badge{position:absolute;top:-4px;right:-4px;width:14px;height:14px;padding:0;border:none;border-radius:999px;background:#0f172abf;color:#fff;display:flex;align-items:center;justify-content:center;z-index:10;opacity:0;pointer-events:none;transition:opacity .12s ease}.color-picker-container:hover .btn-clear-badge{opacity:1;pointer-events:auto}.btn-clear-badge .material-symbols-outlined{font-size:10px;line-height:1}\n"], dependencies: [{ kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }, { kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
2503
2466
  }
2504
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteColorPickerComponent, decorators: [{
2467
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteColorPickerComponent, decorators: [{
2505
2468
  type: Component,
2506
2469
  args: [{ selector: "ate-color-picker", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [AteButtonComponent, CommonModule], template: `
2507
2470
  <div class="color-picker-wrapper">
@@ -2527,14 +2490,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
2527
2490
  </div>
2528
2491
  </div>
2529
2492
  `, styles: [".color-picker-wrapper{position:relative;display:inline-block}.color-picker-container{position:relative;display:inline-flex;align-items:center}.btn-clear-badge{position:absolute;top:-4px;right:-4px;width:14px;height:14px;padding:0;border:none;border-radius:999px;background:#0f172abf;color:#fff;display:flex;align-items:center;justify-content:center;z-index:10;opacity:0;pointer-events:none;transition:opacity .12s ease}.color-picker-container:hover .btn-clear-badge{opacity:1;pointer-events:auto}.btn-clear-badge .material-symbols-outlined{font-size:10px;line-height:1}\n"] }]
2530
- }], propDecorators: { editor: [{ type: i0.Input, args: [{ isSignal: true, alias: "editor", required: true }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], anchorToText: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchorToText", required: false }] }] } });
2493
+ }] });
2531
2494
 
2532
2495
  class AteToolbarComponent {
2533
2496
  constructor() {
2534
- this.editor = input.required(...(ngDevMode ? [{ debugName: "editor" }] : []));
2535
- this.config = input.required(...(ngDevMode ? [{ debugName: "config" }] : []));
2536
- this.imageUpload = input({}, ...(ngDevMode ? [{ debugName: "imageUpload" }] : []));
2537
- this.floating = input(false, ...(ngDevMode ? [{ debugName: "floating" }] : []));
2497
+ this.editor = input.required();
2498
+ this.config = input.required();
2499
+ this.imageUpload = input({});
2500
+ this.floating = input(false);
2538
2501
  this.i18nService = inject(AteI18nService);
2539
2502
  this.editorCommands = inject(AteEditorCommandsService);
2540
2503
  this.t = this.i18nService.toolbar;
@@ -2547,8 +2510,8 @@ class AteToolbarComponent {
2547
2510
  }
2548
2511
  this.editorCommands.execute(editor, command, ...args);
2549
2512
  }
2550
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2551
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AteToolbarComponent, isStandalone: true, selector: "ate-toolbar", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null }, floating: { classPropertyName: "floating", publicName: "floating", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
2513
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2514
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AteToolbarComponent, isStandalone: true, selector: "ate-toolbar", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: true, transformFunction: null }, imageUpload: { classPropertyName: "imageUpload", publicName: "imageUpload", isSignal: true, isRequired: false, transformFunction: null }, floating: { classPropertyName: "floating", publicName: "floating", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
2552
2515
  <div class="ate-toolbar" [class.floating]="floating()">
2553
2516
  @if (config().bold) {
2554
2517
  <ate-button
@@ -2799,7 +2762,7 @@ class AteToolbarComponent {
2799
2762
  </div>
2800
2763
  `, 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 }); }
2801
2764
  }
2802
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteToolbarComponent, decorators: [{
2765
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteToolbarComponent, decorators: [{
2803
2766
  type: Component,
2804
2767
  args: [{ selector: "ate-toolbar", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [AteButtonComponent, AteSeparatorComponent, AteColorPickerComponent], template: `
2805
2768
  <div class="ate-toolbar" [class.floating]="floating()">
@@ -3051,7 +3014,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3051
3014
  }
3052
3015
  </div>
3053
3016
  `, 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"] }]
3054
- }], 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 }] }] } });
3017
+ }] });
3055
3018
 
3056
3019
  /**
3057
3020
  * Base abstract class for all Bubble Menus (Text, Image, Table, Cell).
@@ -3062,7 +3025,7 @@ class AteBaseBubbleMenu {
3062
3025
  this.i18nService = inject(AteI18nService);
3063
3026
  this.editorCommands = inject(AteEditorCommandsService);
3064
3027
  // Core Inputs
3065
- this.editor = input.required(...(ngDevMode ? [{ debugName: "editor" }] : []));
3028
+ this.editor = input.required();
3066
3029
  // Required viewChild for the menu container
3067
3030
  this.menuRef = viewChild.required("menuRef");
3068
3031
  // Internal State
@@ -3106,7 +3069,7 @@ class AteBaseBubbleMenu {
3106
3069
  this.editorCommands.linkEditMode();
3107
3070
  this.editorCommands.colorEditMode();
3108
3071
  this.updateMenu();
3109
- });
3072
+ }, { allowSignalWrites: true });
3110
3073
  }
3111
3074
  ngOnInit() {
3112
3075
  this.initTippy();
@@ -3248,12 +3211,12 @@ class AteBaseBubbleMenu {
3248
3211
  onTippyHide(_instance) {
3249
3212
  /* empty */
3250
3213
  }
3251
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteBaseBubbleMenu, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3252
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.3.16", type: AteBaseBubbleMenu, isStandalone: true, inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "menuRef", first: true, predicate: ["menuRef"], descendants: true, isSignal: true }], ngImport: i0 }); }
3214
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteBaseBubbleMenu, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
3215
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "18.2.14", type: AteBaseBubbleMenu, inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "menuRef", first: true, predicate: ["menuRef"], descendants: true, isSignal: true }], ngImport: i0 }); }
3253
3216
  }
3254
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteBaseBubbleMenu, decorators: [{
3217
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteBaseBubbleMenu, decorators: [{
3255
3218
  type: Directive
3256
- }], ctorParameters: () => [], propDecorators: { editor: [{ type: i0.Input, args: [{ isSignal: true, alias: "editor", required: true }] }], menuRef: [{ type: i0.ViewChild, args: ["menuRef", { isSignal: true }] }] } });
3219
+ }], ctorParameters: () => [] });
3257
3220
 
3258
3221
  class AteBubbleMenuComponent extends AteBaseBubbleMenu {
3259
3222
  constructor() {
@@ -3274,7 +3237,7 @@ class AteBubbleMenuComponent extends AteBaseBubbleMenu {
3274
3237
  textColor: false,
3275
3238
  link: true,
3276
3239
  separator: true,
3277
- }, ...(ngDevMode ? [{ debugName: "config" }] : []));
3240
+ });
3278
3241
  this.bubbleMenuConfig = computed(() => ({
3279
3242
  bold: true,
3280
3243
  italic: true,
@@ -3288,7 +3251,7 @@ class AteBubbleMenuComponent extends AteBaseBubbleMenu {
3288
3251
  link: true,
3289
3252
  separator: true,
3290
3253
  ...this.config(),
3291
- }), ...(ngDevMode ? [{ debugName: "bubbleMenuConfig" }] : []));
3254
+ }));
3292
3255
  }
3293
3256
  ngOnInit() {
3294
3257
  super.ngOnInit();
@@ -3336,8 +3299,8 @@ class AteBubbleMenuComponent extends AteBaseBubbleMenu {
3336
3299
  // Sub-menus now manage their own state. Clearing them here causes
3337
3300
  // premature closing when clicking between 'sibling' menu instances.
3338
3301
  }
3339
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3340
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AteBubbleMenuComponent, isStandalone: true, selector: "ate-bubble-menu", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
3302
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3303
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AteBubbleMenuComponent, isStandalone: true, selector: "ate-bubble-menu", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, usesInheritance: true, ngImport: i0, template: `
3341
3304
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
3342
3305
  @if (bubbleMenuConfig().bold) {
3343
3306
  <ate-button
@@ -3436,7 +3399,7 @@ class AteBubbleMenuComponent extends AteBaseBubbleMenu {
3436
3399
  </div>
3437
3400
  `, 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: AteColorPickerComponent, selector: "ate-color-picker", inputs: ["editor", "mode", "disabled", "anchorToText"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3438
3401
  }
3439
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteBubbleMenuComponent, decorators: [{
3402
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteBubbleMenuComponent, decorators: [{
3440
3403
  type: Component,
3441
3404
  args: [{
3442
3405
  selector: "ate-bubble-menu",
@@ -3542,7 +3505,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3542
3505
  </div>
3543
3506
  `,
3544
3507
  }]
3545
- }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }] } });
3508
+ }] });
3546
3509
 
3547
3510
  class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3548
3511
  constructor() {
@@ -3557,8 +3520,8 @@ class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3557
3520
  resizeOriginal: true,
3558
3521
  deleteImage: true,
3559
3522
  separator: true,
3560
- }, ...(ngDevMode ? [{ debugName: "config" }] : []));
3561
- this.imageUpload = input({}, ...(ngDevMode ? [{ debugName: "imageUpload" }] : []));
3523
+ });
3524
+ this.imageUpload = input({});
3562
3525
  this.imageBubbleMenuConfig = computed(() => ({
3563
3526
  changeImage: this.config().changeImage ?? true,
3564
3527
  resizeSmall: this.config().resizeSmall ?? true,
@@ -3567,11 +3530,11 @@ class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3567
3530
  resizeOriginal: this.config().resizeOriginal ?? true,
3568
3531
  deleteImage: this.config().deleteImage ?? true,
3569
3532
  separator: this.config().separator ?? true,
3570
- }), ...(ngDevMode ? [{ debugName: "imageBubbleMenuConfig" }] : []));
3533
+ }));
3571
3534
  this.hasResizeButtons = computed(() => {
3572
3535
  const c = this.imageBubbleMenuConfig();
3573
3536
  return c.resizeSmall || c.resizeMedium || c.resizeLarge || c.resizeOriginal;
3574
- }, ...(ngDevMode ? [{ debugName: "hasResizeButtons" }] : []));
3537
+ });
3575
3538
  }
3576
3539
  shouldShow() {
3577
3540
  const { nodes, isEditable, isFocused } = this.state();
@@ -3652,8 +3615,8 @@ class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3652
3615
  ed.chain().focus().deleteSelection().run();
3653
3616
  }
3654
3617
  }
3655
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteImageBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3656
- 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: `
3618
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3619
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", 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: `
3657
3620
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
3658
3621
  @if (imageBubbleMenuConfig().changeImage) {
3659
3622
  <ate-button
@@ -3704,7 +3667,7 @@ class AteImageBubbleMenuComponent extends AteBaseBubbleMenu {
3704
3667
  </div>
3705
3668
  `, 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 }); }
3706
3669
  }
3707
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteImageBubbleMenuComponent, decorators: [{
3670
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteImageBubbleMenuComponent, decorators: [{
3708
3671
  type: Component,
3709
3672
  args: [{
3710
3673
  selector: "ate-image-bubble-menu",
@@ -3762,7 +3725,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
3762
3725
  </div>
3763
3726
  `,
3764
3727
  }]
3765
- }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], imageUpload: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageUpload", required: false }] }] } });
3728
+ }] });
3766
3729
 
3767
3730
  class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3768
3731
  constructor() {
@@ -3780,7 +3743,7 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3780
3743
  toggleHeaderRow: true,
3781
3744
  toggleHeaderColumn: true,
3782
3745
  separator: true,
3783
- }, ...(ngDevMode ? [{ debugName: "config" }] : []));
3746
+ });
3784
3747
  }
3785
3748
  shouldShow() {
3786
3749
  const { selection, nodes, isEditable, isFocused } = this.state();
@@ -3836,8 +3799,8 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3836
3799
  executeCommand(editor, command, ...args) {
3837
3800
  this.editorCommands.execute(editor, command, ...args);
3838
3801
  }
3839
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteTableBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3840
- 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: `
3802
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteTableBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
3803
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", 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: `
3841
3804
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
3842
3805
  <!-- Row actions -->
3843
3806
  @if (config().addRowBefore !== false) {
@@ -3926,7 +3889,7 @@ class AteTableBubbleMenuComponent extends AteBaseBubbleMenu {
3926
3889
  </div>
3927
3890
  `, 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 }); }
3928
3891
  }
3929
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteTableBubbleMenuComponent, decorators: [{
3892
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteTableBubbleMenuComponent, decorators: [{
3930
3893
  type: Component,
3931
3894
  args: [{
3932
3895
  selector: "ate-table-bubble-menu",
@@ -4022,13 +3985,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
4022
3985
  </div>
4023
3986
  `,
4024
3987
  }]
4025
- }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }] } });
3988
+ }] });
4026
3989
 
4027
3990
  class AteCellBubbleMenuComponent extends AteBaseBubbleMenu {
4028
3991
  constructor() {
4029
3992
  super(...arguments);
4030
3993
  // Inputs
4031
- this.config = input({}, ...(ngDevMode ? [{ debugName: "config" }] : []));
3994
+ this.config = input({});
4032
3995
  // Signals
4033
3996
  this.i18n = () => this.i18nService;
4034
3997
  }
@@ -4090,8 +4053,8 @@ class AteCellBubbleMenuComponent extends AteBaseBubbleMenu {
4090
4053
  executeCommand(editor, command, ...args) {
4091
4054
  this.editorCommands.execute(editor, command, ...args);
4092
4055
  }
4093
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteCellBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
4094
- 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: `
4056
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteCellBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
4057
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", 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: `
4095
4058
  <div #menuRef class="bubble-menu" (mousedown)="$event.preventDefault()">
4096
4059
  <!-- Cell specific actions -->
4097
4060
  @if (config().mergeCells !== false && !state().selection.isSingleCell) {
@@ -4111,7 +4074,7 @@ class AteCellBubbleMenuComponent extends AteBaseBubbleMenu {
4111
4074
  </div>
4112
4075
  `, 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
4113
4076
  }
4114
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteCellBubbleMenuComponent, decorators: [{
4077
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteCellBubbleMenuComponent, decorators: [{
4115
4078
  type: Component,
4116
4079
  args: [{
4117
4080
  selector: "ate-cell-bubble-menu",
@@ -4138,7 +4101,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
4138
4101
  </div>
4139
4102
  `,
4140
4103
  }]
4141
- }], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }] } });
4104
+ }] });
4142
4105
 
4143
4106
  /**
4144
4107
  * Base abstract class for Sub-Bubble Menus (Link, Color).
@@ -4149,7 +4112,7 @@ class AteBaseSubBubbleMenu {
4149
4112
  this.i18nService = inject(AteI18nService);
4150
4113
  this.editorCommands = inject(AteEditorCommandsService);
4151
4114
  // Core Inputs
4152
- this.editor = input.required(...(ngDevMode ? [{ debugName: "editor" }] : []));
4115
+ this.editor = input.required();
4153
4116
  // Required viewChild for the menu container
4154
4117
  this.menuRef = viewChild.required("menuRef");
4155
4118
  // Internal State
@@ -4179,7 +4142,7 @@ class AteBaseSubBubbleMenu {
4179
4142
  this.state();
4180
4143
  this.onStateChange();
4181
4144
  this.updateMenu();
4182
- });
4145
+ }, { allowSignalWrites: true });
4183
4146
  }
4184
4147
  ngOnInit() {
4185
4148
  this.initTippy();
@@ -4261,12 +4224,12 @@ class AteBaseSubBubbleMenu {
4261
4224
  onTippyHide(_instance) {
4262
4225
  /* empty */
4263
4226
  }
4264
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteBaseSubBubbleMenu, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
4265
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.3.16", type: AteBaseSubBubbleMenu, isStandalone: true, inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "menuRef", first: true, predicate: ["menuRef"], descendants: true, isSignal: true }], ngImport: i0 }); }
4227
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteBaseSubBubbleMenu, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
4228
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "18.2.14", type: AteBaseSubBubbleMenu, inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "menuRef", first: true, predicate: ["menuRef"], descendants: true, isSignal: true }], ngImport: i0 }); }
4266
4229
  }
4267
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteBaseSubBubbleMenu, decorators: [{
4230
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteBaseSubBubbleMenu, decorators: [{
4268
4231
  type: Directive
4269
- }], ctorParameters: () => [], propDecorators: { editor: [{ type: i0.Input, args: [{ isSignal: true, alias: "editor", required: true }] }], menuRef: [{ type: i0.ViewChild, args: ["menuRef", { isSignal: true }] }] } });
4232
+ }], ctorParameters: () => [] });
4270
4233
 
4271
4234
  class AteLinkBubbleMenuComponent extends AteBaseSubBubbleMenu {
4272
4235
  constructor() {
@@ -4274,8 +4237,8 @@ class AteLinkBubbleMenuComponent extends AteBaseSubBubbleMenu {
4274
4237
  this.linkSvc = inject(AteLinkService);
4275
4238
  this.t = this.i18nService.bubbleMenu;
4276
4239
  this.common = this.i18nService.common;
4277
- this.linkInput = viewChild("linkInput", ...(ngDevMode ? [{ debugName: "linkInput" }] : []));
4278
- this.editUrl = signal("", ...(ngDevMode ? [{ debugName: "editUrl" }] : []));
4240
+ this.linkInput = viewChild("linkInput");
4241
+ this.editUrl = signal("");
4279
4242
  // Reactive effect for URL sync
4280
4243
  effect(() => {
4281
4244
  const state = this.state();
@@ -4287,7 +4250,7 @@ class AteLinkBubbleMenuComponent extends AteBaseSubBubbleMenu {
4287
4250
  if (!isInteracting) {
4288
4251
  this.editUrl.set(currentLinkHref);
4289
4252
  }
4290
- });
4253
+ }, { allowSignalWrites: true });
4291
4254
  }
4292
4255
  onStateChange() {
4293
4256
  this.linkSvc.editMode();
@@ -4403,8 +4366,8 @@ class AteLinkBubbleMenuComponent extends AteBaseSubBubbleMenu {
4403
4366
  this.linkSvc.close();
4404
4367
  this.hideTippy();
4405
4368
  }
4406
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteLinkBubbleMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4407
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.16", type: AteLinkBubbleMenuComponent, isStandalone: true, selector: "ate-link-bubble-menu", viewQueries: [{ propertyName: "linkInput", first: true, predicate: ["linkInput"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
4369
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteLinkBubbleMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4370
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "18.2.14", type: AteLinkBubbleMenuComponent, isStandalone: true, selector: "ate-link-bubble-menu", viewQueries: [{ propertyName: "linkInput", first: true, predicate: ["linkInput"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
4408
4371
  <div
4409
4372
  #menuRef
4410
4373
  class="bubble-menu"
@@ -4454,7 +4417,7 @@ class AteLinkBubbleMenuComponent extends AteBaseSubBubbleMenu {
4454
4417
  </div>
4455
4418
  `, 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 }); }
4456
4419
  }
4457
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteLinkBubbleMenuComponent, decorators: [{
4420
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteLinkBubbleMenuComponent, decorators: [{
4458
4421
  type: Component,
4459
4422
  args: [{ selector: "ate-link-bubble-menu", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [AteButtonComponent, AteSeparatorComponent, FormsModule], template: `
4460
4423
  <div
@@ -4505,7 +4468,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
4505
4468
  </div>
4506
4469
  </div>
4507
4470
  `, 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"] }]
4508
- }], ctorParameters: () => [], propDecorators: { linkInput: [{ type: i0.ViewChild, args: ["linkInput", { isSignal: true }] }] } });
4471
+ }], ctorParameters: () => [] });
4509
4472
 
4510
4473
  const PRESET_COLORS = [
4511
4474
  "#000000",
@@ -4528,21 +4491,21 @@ class AteColorBubbleMenuComponent extends AteBaseSubBubbleMenu {
4528
4491
  this.t = this.i18nService.toolbar;
4529
4492
  this.common = this.i18nService.common;
4530
4493
  this.presets = PRESET_COLORS;
4531
- this.colorInputRef = viewChild("colorInput", ...(ngDevMode ? [{ debugName: "colorInputRef" }] : []));
4494
+ this.colorInputRef = viewChild("colorInput");
4532
4495
  /**
4533
4496
  * LOCAL MODE: We lock the mode when the menu is shown to avoid race conditions
4534
4497
  * where the parent (bubble menu) clears the global signal before we apply the color.
4535
4498
  */
4536
- this.activeMode = signal("text", ...(ngDevMode ? [{ debugName: "activeMode" }] : []));
4499
+ this.activeMode = signal("text");
4537
4500
  this.currentColor = computed(() => {
4538
4501
  const marks = this.state().marks;
4539
4502
  const color = this.activeMode() === "text" ? marks.computedColor : marks.computedBackground;
4540
4503
  return color || (this.activeMode() === "text" ? "#000000" : "#ffff00");
4541
- }, ...(ngDevMode ? [{ debugName: "currentColor" }] : []));
4504
+ });
4542
4505
  this.hexValue = computed(() => {
4543
4506
  const color = this.currentColor();
4544
4507
  return color.replace("#", "").toUpperCase();
4545
- }, ...(ngDevMode ? [{ debugName: "hexValue" }] : []));
4508
+ });
4546
4509
  }
4547
4510
  onStateChange() {
4548
4511
  this.colorPickerSvc.editMode();
@@ -4700,8 +4663,8 @@ class AteColorBubbleMenuComponent extends AteBaseSubBubbleMenu {
4700
4663
  this.updateMenu();
4701
4664
  }, 150);
4702
4665
  }
4703
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteColorBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
4704
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AteColorBubbleMenuComponent, isStandalone: true, selector: "ate-color-bubble-menu", viewQueries: [{ propertyName: "colorInputRef", first: true, predicate: ["colorInput"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
4666
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteColorBubbleMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
4667
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AteColorBubbleMenuComponent, isStandalone: true, selector: "ate-color-bubble-menu", viewQueries: [{ propertyName: "colorInputRef", first: true, predicate: ["colorInput"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
4705
4668
  <div
4706
4669
  #menuRef
4707
4670
  class="bubble-menu color-bubble-menu"
@@ -4781,7 +4744,7 @@ class AteColorBubbleMenuComponent extends AteBaseSubBubbleMenu {
4781
4744
  </div>
4782
4745
  `, 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 }); }
4783
4746
  }
4784
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteColorBubbleMenuComponent, decorators: [{
4747
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteColorBubbleMenuComponent, decorators: [{
4785
4748
  type: Component,
4786
4749
  args: [{ selector: "ate-color-bubble-menu", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, FormsModule, AteButtonComponent, AteSeparatorComponent], template: `
4787
4750
  <div
@@ -4862,7 +4825,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
4862
4825
  </div>
4863
4826
  </div>
4864
4827
  `, 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"] }]
4865
- }], propDecorators: { colorInputRef: [{ type: i0.ViewChild, args: ["colorInput", { isSignal: true }] }] } });
4828
+ }] });
4866
4829
 
4867
4830
  /**
4868
4831
  * Clés des commandes natives dans l'ordre d'affichage
@@ -4998,17 +4961,17 @@ function filterSlashCommands(config, i18n, commands, imageOptions) {
4998
4961
  class AteSlashCommandsComponent {
4999
4962
  constructor() {
5000
4963
  this.i18nService = inject(AteI18nService);
5001
- this.editor = input.required(...(ngDevMode ? [{ debugName: "editor" }] : []));
5002
- this.config = input(undefined, ...(ngDevMode ? [{ debugName: "config" }] : []));
4964
+ this.editor = input.required();
4965
+ this.config = input(undefined);
5003
4966
  this.menuRef = viewChild.required("menuRef");
5004
4967
  this.tippyInstance = null;
5005
4968
  this.editorCommands = inject(AteEditorCommandsService);
5006
4969
  // Local state
5007
4970
  this.isActive = false;
5008
- this.currentQuery = signal("", ...(ngDevMode ? [{ debugName: "currentQuery" }] : []));
4971
+ this.currentQuery = signal("");
5009
4972
  this.slashRange = null;
5010
4973
  // Signal for selected index
5011
- this.selectedIndex = signal(0, ...(ngDevMode ? [{ debugName: "selectedIndex" }] : []));
4974
+ this.selectedIndex = signal(0);
5012
4975
  // Toolbar interaction state (from centralized service)
5013
4976
  this.isToolbarInteracting = this.editorCommands.isToolbarInteracting;
5014
4977
  this.commands = computed(() => {
@@ -5018,7 +4981,7 @@ class AteSlashCommandsComponent {
5018
4981
  }
5019
4982
  // Fallback to default native commands
5020
4983
  return createDefaultSlashCommands(this.i18nService, this.editorCommands);
5021
- }, ...(ngDevMode ? [{ debugName: "commands" }] : []));
4984
+ });
5022
4985
  this.filteredCommands = computed(() => {
5023
4986
  const query = this.currentQuery().toLowerCase();
5024
4987
  const commands = this.commands();
@@ -5028,7 +4991,7 @@ class AteSlashCommandsComponent {
5028
4991
  return commands.filter(command => command.title.toLowerCase().includes(query) ||
5029
4992
  command.description.toLowerCase().includes(query) ||
5030
4993
  command.keywords.some(keyword => keyword.toLowerCase().includes(query)));
5031
- }, ...(ngDevMode ? [{ debugName: "filteredCommands" }] : []));
4994
+ });
5032
4995
  this.updateMenu = () => {
5033
4996
  const ed = this.editor();
5034
4997
  if (!ed) {
@@ -5084,7 +5047,7 @@ class AteSlashCommandsComponent {
5084
5047
  // Use ProseMirror plugin system to intercept keys
5085
5048
  this.addKeyboardPlugin(ed);
5086
5049
  // updateMenu() will be called automatically when editor is ready
5087
- });
5050
+ }, { allowSignalWrites: true });
5088
5051
  }
5089
5052
  ngOnInit() {
5090
5053
  this.initTippy();
@@ -5272,8 +5235,8 @@ class AteSlashCommandsComponent {
5272
5235
  plugins: [keyboardPlugin, ...ed.view.state.plugins],
5273
5236
  }));
5274
5237
  }
5275
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteSlashCommandsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5276
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AteSlashCommandsComponent, isStandalone: true, selector: "ate-slash-commands", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "menuRef", first: true, predicate: ["menuRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
5238
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteSlashCommandsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5239
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: AteSlashCommandsComponent, isStandalone: true, selector: "ate-slash-commands", inputs: { editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "menuRef", first: true, predicate: ["menuRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
5277
5240
  <div #menuRef class="slash-commands-menu">
5278
5241
  @for (command of filteredCommands(); track command.title) {
5279
5242
  <div
@@ -5293,7 +5256,7 @@ class AteSlashCommandsComponent {
5293
5256
  </div>
5294
5257
  `, isInline: true, styles: [".slash-commands-menu{background:var(--ate-menu-bg);border:1px solid var(--ate-menu-border);border-radius:var(--ate-menu-border-radius, 12px);box-shadow:var(--ate-menu-shadow);padding:var(--ate-menu-padding);max-height:320px;overflow-y:auto;min-width:280px;outline:none;animation:slashMenuFadeIn .2s cubic-bezier(0,0,.2,1);scrollbar-width:thin;scrollbar-color:var(--ate-scrollbar-thumb) var(--ate-scrollbar-track)}.slash-commands-menu::-webkit-scrollbar{width:var(--ate-scrollbar-width)}.slash-commands-menu::-webkit-scrollbar-track{background:var(--ate-scrollbar-track)}.slash-commands-menu::-webkit-scrollbar-thumb{background:var(--ate-scrollbar-thumb);border:3px solid transparent;background-clip:content-box;border-radius:10px}.slash-commands-menu::-webkit-scrollbar-thumb:hover{background:var(--ate-scrollbar-thumb-hover);background-clip:content-box}@keyframes slashMenuFadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.slash-command-item{display:flex;align-items:center;gap:12px;padding:var(--ate-menu-padding);border-radius:var(--ate-menu-border-radius, 8px);cursor:pointer;transition:all .15s ease;border:var(--ate-border-width, 1px) solid transparent;outline:none;margin-bottom:2px}.slash-command-item:last-child{margin-bottom:0}.slash-command-item:hover{background:var(--ate-surface-secondary)}.slash-command-item.selected{background:var(--ate-primary-light);border-color:var(--ate-primary-light-alpha)}.slash-command-icon{display:flex;align-items:center;justify-content:center;width:32px;height:32px;background:var(--ate-surface-tertiary);border-radius:var(--ate-sub-border-radius, 8px);color:var(--ate-primary);flex-shrink:0;transition:all .15s ease}.slash-command-item.selected .slash-command-icon{background:var(--ate-primary);color:var(--ate-primary-contrast, #ffffff)}.slash-command-icon .material-symbols-outlined{font-size:18px}.slash-command-content{flex:1;min-width:0}.slash-command-title{font-weight:500;color:var(--ate-text);font-size:14px;margin-bottom:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.slash-command-description{color:var(--ate-text-secondary);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5295
5258
  }
5296
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteSlashCommandsComponent, decorators: [{
5259
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteSlashCommandsComponent, decorators: [{
5297
5260
  type: Component,
5298
5261
  args: [{ selector: "ate-slash-commands", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: `
5299
5262
  <div #menuRef class="slash-commands-menu">
@@ -5314,7 +5277,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
5314
5277
  }
5315
5278
  </div>
5316
5279
  `, styles: [".slash-commands-menu{background:var(--ate-menu-bg);border:1px solid var(--ate-menu-border);border-radius:var(--ate-menu-border-radius, 12px);box-shadow:var(--ate-menu-shadow);padding:var(--ate-menu-padding);max-height:320px;overflow-y:auto;min-width:280px;outline:none;animation:slashMenuFadeIn .2s cubic-bezier(0,0,.2,1);scrollbar-width:thin;scrollbar-color:var(--ate-scrollbar-thumb) var(--ate-scrollbar-track)}.slash-commands-menu::-webkit-scrollbar{width:var(--ate-scrollbar-width)}.slash-commands-menu::-webkit-scrollbar-track{background:var(--ate-scrollbar-track)}.slash-commands-menu::-webkit-scrollbar-thumb{background:var(--ate-scrollbar-thumb);border:3px solid transparent;background-clip:content-box;border-radius:10px}.slash-commands-menu::-webkit-scrollbar-thumb:hover{background:var(--ate-scrollbar-thumb-hover);background-clip:content-box}@keyframes slashMenuFadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}.slash-command-item{display:flex;align-items:center;gap:12px;padding:var(--ate-menu-padding);border-radius:var(--ate-menu-border-radius, 8px);cursor:pointer;transition:all .15s ease;border:var(--ate-border-width, 1px) solid transparent;outline:none;margin-bottom:2px}.slash-command-item:last-child{margin-bottom:0}.slash-command-item:hover{background:var(--ate-surface-secondary)}.slash-command-item.selected{background:var(--ate-primary-light);border-color:var(--ate-primary-light-alpha)}.slash-command-icon{display:flex;align-items:center;justify-content:center;width:32px;height:32px;background:var(--ate-surface-tertiary);border-radius:var(--ate-sub-border-radius, 8px);color:var(--ate-primary);flex-shrink:0;transition:all .15s ease}.slash-command-item.selected .slash-command-icon{background:var(--ate-primary);color:var(--ate-primary-contrast, #ffffff)}.slash-command-icon .material-symbols-outlined{font-size:18px}.slash-command-content{flex:1;min-width:0}.slash-command-title{font-weight:500;color:var(--ate-text);font-size:14px;margin-bottom:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.slash-command-description{color:var(--ate-text-secondary);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
5317
- }], ctorParameters: () => [], propDecorators: { editor: [{ type: i0.Input, args: [{ isSignal: true, alias: "editor", required: true }] }], config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], menuRef: [{ type: i0.ViewChild, args: ["menuRef", { isSignal: true }] }] } });
5280
+ }], ctorParameters: () => [] });
5318
5281
 
5319
5282
  /**
5320
5283
  * Edit Toggle Component
@@ -5322,12 +5285,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
5322
5285
  */
5323
5286
  class AteEditToggleComponent {
5324
5287
  constructor() {
5325
- this.editable = input.required(...(ngDevMode ? [{ debugName: "editable" }] : []));
5326
- this.translations = input.required(...(ngDevMode ? [{ debugName: "translations" }] : []));
5288
+ this.editable = input.required();
5289
+ this.translations = input.required();
5327
5290
  this.editToggle = output();
5328
5291
  }
5329
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteEditToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5330
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.16", type: AteEditToggleComponent, isStandalone: true, selector: "ate-edit-toggle", inputs: { editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: true, transformFunction: null }, translations: { classPropertyName: "translations", publicName: "translations", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { editToggle: "editToggle" }, ngImport: i0, template: `
5292
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteEditToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
5293
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.14", type: AteEditToggleComponent, isStandalone: true, selector: "ate-edit-toggle", inputs: { editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: true, transformFunction: null }, translations: { classPropertyName: "translations", publicName: "translations", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { editToggle: "editToggle" }, ngImport: i0, template: `
5331
5294
  <div class="ate-edit-toggle-container" [class.is-editable]="editable()">
5332
5295
  <ate-button
5333
5296
  [icon]="editable() ? 'visibility' : 'edit'"
@@ -5339,7 +5302,7 @@ class AteEditToggleComponent {
5339
5302
  </div>
5340
5303
  `, isInline: true, styles: [".ate-edit-toggle-container{position:absolute;margin-top:16px;right:16px;z-index:50}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AteButtonComponent, selector: "ate-button", inputs: ["icon", "title", "active", "disabled", "color", "backgroundColor", "variant", "size", "iconSize"], outputs: ["buttonClick"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
5341
5304
  }
5342
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteEditToggleComponent, decorators: [{
5305
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteEditToggleComponent, decorators: [{
5343
5306
  type: Component,
5344
5307
  args: [{ selector: "ate-edit-toggle", standalone: true, imports: [CommonModule, AteButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
5345
5308
  <div class="ate-edit-toggle-container" [class.is-editable]="editable()">
@@ -5352,7 +5315,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
5352
5315
  backgroundColor="var(--ate-primary-lighter)" />
5353
5316
  </div>
5354
5317
  `, styles: [".ate-edit-toggle-container{position:absolute;margin-top:16px;right:16px;z-index:50}\n"] }]
5355
- }], propDecorators: { editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: true }] }], translations: [{ type: i0.Input, args: [{ isSignal: true, alias: "translations", required: true }] }], editToggle: [{ type: i0.Output, args: ["editToggle"] }] } });
5318
+ }] });
5356
5319
 
5357
5320
  /**
5358
5321
  * Noop Value Accessor Directive
@@ -5368,8 +5331,8 @@ class AteNoopValueAccessorDirective {
5368
5331
  registerOnTouched(_fn) {
5369
5332
  /* empty */
5370
5333
  }
5371
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteNoopValueAccessorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
5372
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.16", type: AteNoopValueAccessorDirective, isStandalone: true, providers: [
5334
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteNoopValueAccessorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
5335
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: AteNoopValueAccessorDirective, isStandalone: true, providers: [
5373
5336
  {
5374
5337
  provide: NG_VALUE_ACCESSOR,
5375
5338
  multi: true,
@@ -5377,7 +5340,7 @@ class AteNoopValueAccessorDirective {
5377
5340
  },
5378
5341
  ], ngImport: i0 }); }
5379
5342
  }
5380
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AteNoopValueAccessorDirective, decorators: [{
5343
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteNoopValueAccessorDirective, decorators: [{
5381
5344
  type: Directive,
5382
5345
  args: [{
5383
5346
  standalone: true,
@@ -5391,271 +5354,707 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
5391
5354
  }]
5392
5355
  }] });
5393
5356
 
5394
- const AteSelectionCalculator = editor => {
5395
- const { selection } = editor.state;
5396
- const { from, to } = selection;
5397
- let selectionType = "none";
5398
- if (selection instanceof TextSelection) {
5399
- selectionType = "text";
5357
+ /**
5358
+ * Base abstract class for custom 'Angular Nodes'.
5359
+ *
5360
+ * Extend this class in your custom components to automatically receive TipTap editor
5361
+ * properties (node attributes, selection state, etc.) as reactive Signals.
5362
+ *
5363
+ * @example
5364
+ * ```typescript
5365
+ * @Component({
5366
+ * selector: 'app-counter',
5367
+ * template: `
5368
+ * <div>
5369
+ * <button (click)="increment()">Count: {{ node().attrs['count'] }}</button>
5370
+ * </div>
5371
+ * `
5372
+ * })
5373
+ * export class CounterComponent extends AteAngularNodeView {
5374
+ * increment() {
5375
+ * const count = this.node().attrs['count'] || 0;
5376
+ * this.updateAttributes({ count: count + 1 });
5377
+ * }
5378
+ * }
5379
+ * ```
5380
+ */
5381
+ class AteAngularNodeView {
5382
+ /**
5383
+ * Internal method to initialize the component with NodeView props.
5384
+ * This is called by the AngularNodeViewRenderer.
5385
+ *
5386
+ * @internal
5387
+ */
5388
+ _initNodeView(props) {
5389
+ // Create signals from the props
5390
+ const editorSignal = signal(props.editor);
5391
+ const nodeSignal = signal(props.node);
5392
+ const decorationsSignal = signal(props.decorations);
5393
+ const selectedSignal = signal(props.selected);
5394
+ const extensionSignal = signal(props.extension);
5395
+ // Assign to the component
5396
+ this.editor = editorSignal.asReadonly();
5397
+ this.node = nodeSignal.asReadonly();
5398
+ this.decorations = decorationsSignal.asReadonly();
5399
+ this.selected = selectedSignal.asReadonly();
5400
+ this.extension = extensionSignal.asReadonly();
5401
+ this.getPos = props.getPos;
5402
+ this.updateAttributes = props.updateAttributes;
5403
+ this.deleteNode = props.deleteNode;
5404
+ // Store writable signals for updates
5405
+ this._writableSignals = {
5406
+ node: nodeSignal,
5407
+ decorations: decorationsSignal,
5408
+ selected: selectedSignal,
5409
+ };
5400
5410
  }
5401
- else if (selection instanceof NodeSelection) {
5402
- selectionType = "node";
5411
+ /**
5412
+ * Internal method to update the component when the node changes.
5413
+ * This is called by the AngularNodeViewRenderer.
5414
+ *
5415
+ * @internal
5416
+ */
5417
+ _updateNodeView(node, decorations) {
5418
+ if (this._writableSignals) {
5419
+ this._writableSignals.node.set(node);
5420
+ this._writableSignals.decorations.set(decorations);
5421
+ }
5403
5422
  }
5404
- else if (selection instanceof CellSelection) {
5405
- selectionType = "cell";
5423
+ /**
5424
+ * Internal method to update the selection state.
5425
+ * This is called by the AngularNodeViewRenderer.
5426
+ *
5427
+ * @internal
5428
+ */
5429
+ _selectNodeView() {
5430
+ if (this._writableSignals) {
5431
+ this._writableSignals.selected.set(true);
5432
+ }
5406
5433
  }
5407
- let isSingleCell = false;
5408
- if (selection instanceof CellSelection) {
5409
- isSingleCell = selection.$anchorCell.pos === selection.$headCell.pos;
5434
+ /**
5435
+ * Internal method to update the deselection state.
5436
+ * This is called by the AngularNodeViewRenderer.
5437
+ *
5438
+ * @internal
5439
+ */
5440
+ _deselectNodeView() {
5441
+ if (this._writableSignals) {
5442
+ this._writableSignals.selected.set(false);
5443
+ }
5410
5444
  }
5411
- return {
5412
- isFocused: editor.view.hasFocus(),
5413
- isEditable: editor.isEditable,
5414
- selection: {
5415
- type: selectionType,
5416
- from,
5417
- to,
5418
- empty: selection.empty || (selectionType === "text" && from === to),
5419
- isSingleCell: isSingleCell,
5420
- },
5421
- nodes: {
5422
- activeNodeName: editor.state.doc.nodeAt(editor.state.selection.$head.pos)?.type.name || null,
5423
- },
5424
- };
5425
- };
5445
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteAngularNodeView, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
5446
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: AteAngularNodeView, ngImport: i0 }); }
5447
+ }
5448
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AteAngularNodeView, decorators: [{
5449
+ type: Directive
5450
+ }] });
5426
5451
 
5427
- const AteMarksCalculator = editor => {
5428
- const isCodeBlock = editor.isActive("codeBlock");
5429
- const isCode = editor.isActive("code"); // Inline code mark
5430
- const isImage = editor.isActive("image") || editor.isActive("resizableImage");
5431
- // Check if marks are generally allowed based on context
5432
- const marksAllowed = !isCodeBlock && !isImage;
5433
- // For inline code specifically, we don't allow nesting OTHER marks inside it,
5434
- // but the code mark ITSELF must be togglable to be removed.
5435
- const isInsideInlineCode = isCode;
5436
- // 1. Resolve target element once for this calculation
5437
- const getTargetElement = () => {
5438
- if (typeof window === "undefined" || !editor.view?.dom) {
5439
- return null;
5440
- }
5441
- try {
5442
- const { from } = editor.state.selection;
5443
- const { node } = editor.view.domAtPos(from);
5444
- return node.nodeType === Node.TEXT_NODE ? node.parentElement : node;
5445
- }
5446
- catch (_e) {
5447
- return null;
5452
+ /**
5453
+ * Universal Renderer for Angular Components as TipTap NodeViews.
5454
+ *
5455
+ * Supports:
5456
+ * - TipTap-Aware components (extending AteAngularNodeView)
5457
+ * - Standard library components (automatic @Input() sync)
5458
+ * - Signal-based inputs and outputs (Angular 18+)
5459
+ * - Content projection (editableContent)
5460
+ * - Unified lifecycle and event management
5461
+ */
5462
+ function AteNodeViewRenderer(component, options) {
5463
+ return props => {
5464
+ const { node, view: _view, getPos, decorations, editor, extension } = props;
5465
+ const { injector, inputs = {}, wrapperTag = "div", wrapperClass, editableContent = false, contentSelector, onOutput, ignoreMutation = true, } = options;
5466
+ const dom = document.createElement(wrapperTag);
5467
+ if (wrapperClass) {
5468
+ dom.className = wrapperClass;
5448
5469
  }
5449
- };
5450
- const targetEl = getTargetElement() || (typeof window !== "undefined" ? editor.view?.dom : null);
5451
- const computedStyle = targetEl && typeof window !== "undefined" ? window.getComputedStyle(targetEl) : null;
5452
- // 2. Lightweight helper to extract properties from the pre-calculated style object
5453
- const getStyle = (prop) => {
5454
- if (!computedStyle) {
5455
- return null;
5470
+ const applicationRef = injector.get(ApplicationRef);
5471
+ const environmentInjector = injector.get(EnvironmentInjector);
5472
+ // 1. Setup Content Projection (ng-content)
5473
+ let initialNodes = [];
5474
+ let contentDOM = null;
5475
+ if (editableContent && !contentSelector) {
5476
+ contentDOM = document.createElement("div");
5477
+ contentDOM.setAttribute("data-node-view-content", "");
5478
+ initialNodes = [[contentDOM]];
5456
5479
  }
5457
- const val = computedStyle.getPropertyValue(prop);
5458
- return normalizeColor(val);
5459
- };
5460
- const colorMark = editor.getAttributes("textStyle")["color"] || null;
5461
- const backgroundMark = editor.getAttributes("highlight")["color"] || null;
5462
- return {
5463
- marks: {
5464
- bold: editor.isActive("bold"),
5465
- italic: editor.isActive("italic"),
5466
- underline: editor.isActive("underline"),
5467
- strike: editor.isActive("strike"),
5468
- code: isCode,
5469
- superscript: editor.isActive("superscript"),
5470
- subscript: editor.isActive("subscript"),
5471
- highlight: editor.isActive("highlight"),
5472
- link: editor.isActive("link"),
5473
- linkHref: editor.getAttributes("link")["href"] || null,
5474
- color: colorMark,
5475
- computedColor: colorMark || getStyle("color"),
5476
- background: backgroundMark,
5477
- computedBackground: backgroundMark || getStyle("background-color"),
5478
- linkOpenOnClick: editor.extensionManager.extensions.find(ext => ext.name === "link")?.options?.openOnClick ??
5479
- false,
5480
- },
5481
- can: {
5482
- toggleBold: marksAllowed && !isInsideInlineCode && editor.can().toggleBold(),
5483
- toggleItalic: marksAllowed && !isInsideInlineCode && editor.can().toggleItalic(),
5484
- toggleUnderline: marksAllowed && !isInsideInlineCode && editor.can().toggleUnderline(),
5485
- toggleStrike: marksAllowed && !isInsideInlineCode && editor.can().toggleStrike(),
5486
- toggleCode: marksAllowed && editor.can().toggleCode(),
5487
- toggleHighlight: marksAllowed && !isInsideInlineCode && editor.can().toggleHighlight(),
5488
- toggleLink: marksAllowed &&
5489
- !isInsideInlineCode &&
5490
- (editor.can().setLink({ href: "" }) || editor.can().unsetLink()),
5491
- toggleSuperscript: marksAllowed && !isInsideInlineCode && editor.can().toggleSuperscript(),
5492
- toggleSubscript: marksAllowed && !isInsideInlineCode && editor.can().toggleSubscript(),
5493
- setColor: marksAllowed && !isInsideInlineCode && editor.can().setColor(""),
5494
- setHighlight: marksAllowed && !isInsideInlineCode && editor.can().setHighlight(),
5495
- undo: editor.can().undo(),
5496
- redo: editor.can().redo(),
5497
- },
5498
- };
5499
- };
5500
-
5501
- const AteTableCalculator = editor => {
5502
- const isTable = editor.isActive("table");
5503
- if (!isTable) {
5480
+ // 2. Create the Angular Component
5481
+ const componentRef = createComponent(component, {
5482
+ environmentInjector,
5483
+ elementInjector: injector,
5484
+ projectableNodes: initialNodes,
5485
+ });
5486
+ const instance = componentRef.instance;
5487
+ const subscriptions = [];
5488
+ // 3. Initialize TipTap-Aware instances
5489
+ if (instance instanceof AteAngularNodeView) {
5490
+ instance._initNodeView({
5491
+ editor,
5492
+ node,
5493
+ decorations,
5494
+ selected: false,
5495
+ extension,
5496
+ getPos,
5497
+ updateAttributes: attrs => editor.commands.updateAttributes(node.type.name, attrs),
5498
+ deleteNode: () => {
5499
+ const pos = getPos();
5500
+ if (pos !== undefined) {
5501
+ editor.commands.deleteRange({ from: pos, to: pos + node.nodeSize });
5502
+ }
5503
+ },
5504
+ });
5505
+ }
5506
+ // 4. Synchronize Inputs (Handles standard @Input and Signal-based inputs)
5507
+ const syncInputs = (nodeToSync) => {
5508
+ // Combine base inputs from options with dynamic node attributes
5509
+ const mergedInputs = { ...inputs, ...nodeToSync.attrs };
5510
+ Object.entries(mergedInputs).forEach(([key, value]) => {
5511
+ if (key !== "id" && value !== null && value !== undefined) {
5512
+ try {
5513
+ componentRef.setInput(key, value);
5514
+ }
5515
+ catch {
5516
+ // Silently ignore inputs that don't exist on the component
5517
+ }
5518
+ }
5519
+ });
5520
+ };
5521
+ syncInputs(node);
5522
+ // 5. Setup Outputs (Handles EventEmitter and OutputRef)
5523
+ if (onOutput) {
5524
+ Object.entries(instance).forEach(([key, potentialOutput]) => {
5525
+ if (potentialOutput &&
5526
+ typeof potentialOutput
5527
+ .subscribe === "function") {
5528
+ const sub = potentialOutput.subscribe((value) => {
5529
+ onOutput(key, value);
5530
+ });
5531
+ if (sub instanceof Subscription) {
5532
+ subscriptions.push(sub);
5533
+ }
5534
+ }
5535
+ });
5536
+ }
5537
+ // 6. Attach to DOM and ApplicationRef
5538
+ applicationRef.attachView(componentRef.hostView);
5539
+ const componentElement = componentRef.location.nativeElement;
5540
+ // Target specific element for content if selector provided
5541
+ if (editableContent && contentSelector) {
5542
+ contentDOM = componentElement.querySelector(contentSelector);
5543
+ }
5544
+ dom.appendChild(componentElement);
5545
+ // Initial detection to ensure the component is rendered
5546
+ componentRef.changeDetectorRef.detectChanges();
5547
+ // 7. Return the TipTap NodeView Interface
5504
5548
  return {
5505
- nodes: {
5506
- isTable: false,
5507
- isTableCell: false,
5508
- isTableHeaderRow: false,
5509
- isTableHeaderColumn: false,
5549
+ dom,
5550
+ contentDOM,
5551
+ update: (updatedNode, updatedDecorations) => {
5552
+ if (updatedNode.type !== node.type) {
5553
+ return false;
5554
+ }
5555
+ // Update Aware component signals
5556
+ if (instance instanceof AteAngularNodeView) {
5557
+ instance._updateNodeView(updatedNode, updatedDecorations);
5558
+ }
5559
+ // Update inputs
5560
+ syncInputs(updatedNode);
5561
+ // Notify and Detect changes
5562
+ componentRef.changeDetectorRef.detectChanges();
5563
+ if (options.onUpdate) {
5564
+ options.onUpdate(updatedNode);
5565
+ }
5566
+ return true;
5567
+ },
5568
+ selectNode: () => {
5569
+ if (instance instanceof AteAngularNodeView) {
5570
+ instance._selectNodeView();
5571
+ }
5572
+ dom.classList.add("ProseMirror-selectednode");
5573
+ },
5574
+ deselectNode: () => {
5575
+ if (instance instanceof AteAngularNodeView) {
5576
+ instance._deselectNodeView();
5577
+ }
5578
+ dom.classList.remove("ProseMirror-selectednode");
5579
+ },
5580
+ destroy: () => {
5581
+ if (options.onDestroy) {
5582
+ options.onDestroy();
5583
+ }
5584
+ subscriptions.forEach(s => s.unsubscribe());
5585
+ applicationRef.detachView(componentRef.hostView);
5586
+ componentRef.destroy();
5587
+ },
5588
+ stopEvent: event => {
5589
+ const target = event.target;
5590
+ const isEditable = target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable;
5591
+ return isEditable;
5592
+ },
5593
+ ignoreMutation: mutation => {
5594
+ if (typeof ignoreMutation === "function") {
5595
+ return ignoreMutation(mutation);
5596
+ }
5597
+ return ignoreMutation;
5510
5598
  },
5511
5599
  };
5512
- }
5513
- const { selection } = editor.state;
5514
- return {
5515
- nodes: {
5516
- isTable: true,
5517
- isTableNodeSelected: selection instanceof NodeSelection && selection.node.type.name === "table",
5518
- isTableCell: editor.isActive("tableCell") || editor.isActive("tableHeader"),
5519
- isTableHeaderRow: editor.isActive("tableHeader", { row: true }),
5520
- isTableHeaderColumn: editor.isActive("tableHeader", { column: true }),
5521
- },
5522
- can: {
5523
- addRowBefore: editor.can().addRowBefore(),
5524
- addRowAfter: editor.can().addRowAfter(),
5525
- deleteRow: editor.can().deleteRow(),
5526
- addColumnBefore: editor.can().addColumnBefore(),
5527
- addColumnAfter: editor.can().addColumnAfter(),
5528
- deleteColumn: editor.can().deleteColumn(),
5529
- deleteTable: editor.can().deleteTable(),
5530
- mergeCells: editor.can().mergeCells(),
5531
- splitCell: editor.can().splitCell(),
5532
- toggleHeaderRow: editor.can().toggleHeaderRow(),
5533
- toggleHeaderColumn: editor.can().toggleHeaderColumn(),
5534
- },
5535
- };
5536
- };
5537
-
5538
- const AteImageCalculator = editor => {
5539
- return {
5540
- nodes: {
5541
- isImage: editor.isActive("image") || editor.isActive("resizableImage"),
5542
- },
5543
- };
5544
- };
5545
-
5546
- const AteStructureCalculator = editor => {
5547
- return {
5548
- nodes: {
5549
- isBlockquote: editor.isActive("blockquote"),
5550
- isCodeBlock: editor.isActive("codeBlock"),
5551
- isBulletList: editor.isActive("bulletList"),
5552
- isOrderedList: editor.isActive("orderedList"),
5553
- h1: editor.isActive("heading", { level: 1 }),
5554
- h2: editor.isActive("heading", { level: 2 }),
5555
- h3: editor.isActive("heading", { level: 3 }),
5556
- alignLeft: editor.isActive({ textAlign: "left" }),
5557
- alignCenter: editor.isActive({ textAlign: "center" }),
5558
- alignRight: editor.isActive({ textAlign: "right" }),
5559
- alignJustify: editor.isActive({ textAlign: "justify" }),
5560
- },
5561
- can: {
5562
- toggleHeading1: editor.can().toggleHeading({ level: 1 }),
5563
- toggleHeading2: editor.can().toggleHeading({ level: 2 }),
5564
- toggleHeading3: editor.can().toggleHeading({ level: 3 }),
5565
- toggleBulletList: editor.can().toggleBulletList(),
5566
- toggleOrderedList: editor.can().toggleOrderedList(),
5567
- toggleBlockquote: editor.can().toggleBlockquote(),
5568
- toggleCodeBlock: editor.can().toggleCodeBlock(),
5569
- setTextAlignLeft: editor.can().setTextAlign("left"),
5570
- setTextAlignCenter: editor.can().setTextAlign("center"),
5571
- setTextAlignRight: editor.can().setTextAlign("right"),
5572
- setTextAlignJustify: editor.can().setTextAlign("justify"),
5573
- insertHorizontalRule: editor.can().setHorizontalRule(),
5574
- insertTable: editor.can().insertTable(),
5575
- insertImage: editor.can().setResizableImage({ src: "" }),
5576
- },
5577
5600
  };
5578
- };
5601
+ }
5579
5602
 
5603
+ const RESERVED_NAMES = [
5604
+ "doc",
5605
+ "paragraph",
5606
+ "text",
5607
+ "hardBreak",
5608
+ "bulletList",
5609
+ "orderedList",
5610
+ "listItem",
5611
+ "blockquote",
5612
+ "codeBlock",
5613
+ "heading",
5614
+ "horizontalRule",
5615
+ ];
5580
5616
  /**
5581
- * DiscoveryCalculator automatically detects and tracks the state of any TipTap extension.
5582
- * It provides a "fallback" reactive state for any mark or node not explicitly handled
5583
- * by specialized calculators.
5617
+ * Derives the TipTap node name and HTML tag from a component class.
5584
5618
  */
5585
- const AteDiscoveryCalculator = (editor) => {
5586
- const state = {
5587
- marks: {},
5588
- nodes: {},
5589
- };
5590
- // We skip core extensions that are already handled by specialized calculators
5591
- // to avoid redundant calculations and maintain precise attribute tracking.
5592
- const handled = [
5593
- "bold",
5594
- "italic",
5595
- "underline",
5596
- "strike",
5597
- "code",
5598
- "link",
5599
- "highlight",
5600
- "superscript",
5601
- "subscript",
5602
- "table",
5603
- "image",
5604
- "resizableImage",
5605
- "heading",
5606
- "bulletList",
5607
- "orderedList",
5608
- "blockquote",
5609
- "textAlign",
5610
- "textStyle",
5611
- "color",
5612
- ];
5613
- editor.extensionManager.extensions.forEach(extension => {
5614
- const name = extension.name;
5615
- const type = extension.type;
5616
- // Skip internal/core extensions or already handled ones
5617
- if ([
5618
- "selection",
5619
- "editable",
5620
- "focus",
5621
- "undo",
5622
- "redo",
5623
- "history",
5624
- "placeholder",
5625
- "characterCount",
5626
- ].includes(name)) {
5627
- return;
5619
+ function deriveMetadata(component, customName) {
5620
+ let nodeName = customName;
5621
+ if (!nodeName) {
5622
+ nodeName = component.name
5623
+ .replace(/Component$/, "")
5624
+ .replace(/Node$/, "")
5625
+ .replace(/^([A-Z])/, m => m.toLowerCase());
5626
+ console.warn(`[ATE] Auto-deriving node name '${nodeName}' for component ${component.name}. ` +
5627
+ `Provide an explicit 'name' in options to avoid potential naming collisions.`);
5628
+ }
5629
+ if (RESERVED_NAMES.includes(nodeName)) {
5630
+ throw new Error(`[ATE] The name '${nodeName}' is a reserved TipTap node name. ` +
5631
+ `Please provide a unique name for your custom component.`);
5632
+ }
5633
+ const tag = nodeName.toLowerCase().replace(/([A-Z])/g, "-$1");
5634
+ return { nodeName, tag };
5635
+ }
5636
+ /**
5637
+ * Creates TipTap attributes from component inputs (Standard Mode).
5638
+ */
5639
+ function createStandardAttributes(defaultInputs = {}) {
5640
+ const tiptapAttributes = {};
5641
+ Object.entries(defaultInputs).forEach(([key, defaultValue]) => {
5642
+ tiptapAttributes[key] = {
5643
+ default: defaultValue,
5644
+ parseHTML: (element) => {
5645
+ const attr = element.getAttribute(`data-${key}`);
5646
+ if (attr === null) {
5647
+ return defaultValue;
5648
+ }
5649
+ try {
5650
+ return JSON.parse(attr);
5651
+ }
5652
+ catch {
5653
+ return attr;
5654
+ }
5655
+ },
5656
+ renderHTML: (attrs) => {
5657
+ const value = attrs[key];
5658
+ if (value === undefined || value === null) {
5659
+ return {};
5660
+ }
5661
+ const serialized = typeof value === "object" ? JSON.stringify(value) : String(value);
5662
+ return { [`data-${key}`]: serialized };
5663
+ },
5664
+ };
5665
+ });
5666
+ return tiptapAttributes;
5667
+ }
5668
+ /**
5669
+ * Factory to transform an Angular component into a TipTap Node extension.
5670
+ * Supports both "TipTap-Aware" and "Standard" modes.
5671
+ *
5672
+ * @internal
5673
+ */
5674
+ function createAngularComponentExtension(injector, options) {
5675
+ const { component, name: customName, attributes, defaultInputs, contentSelector, contentMode = "block", editableContent = false, group = "block", draggable = true, ignoreMutation = true, onOutput, HTMLAttributes = {}, parseHTML: customParseHTML, renderHTML: customRenderHTML, } = options;
5676
+ const { nodeName, tag } = deriveMetadata(component, customName);
5677
+ const isTipTapAware = Object.prototype.isPrototypeOf.call(AteAngularNodeView, component);
5678
+ const atom = !editableContent;
5679
+ // 1. Prepare Attributes
5680
+ const tiptapAttributes = isTipTapAware
5681
+ ? attributes || {}
5682
+ : createStandardAttributes(defaultInputs);
5683
+ // 2. Create Node Extension
5684
+ return Node$1.create({
5685
+ name: nodeName,
5686
+ group,
5687
+ inline: group === "inline",
5688
+ atom,
5689
+ draggable,
5690
+ content: editableContent ? (contentMode === "inline" ? "inline*" : "block*") : undefined,
5691
+ addAttributes() {
5692
+ return tiptapAttributes;
5693
+ },
5694
+ parseHTML() {
5695
+ if (customParseHTML) {
5696
+ return customParseHTML.call(this);
5697
+ }
5698
+ return [{ tag }, { tag: `div[data-component="${nodeName}"]` }];
5699
+ },
5700
+ renderHTML({ node, HTMLAttributes: attrs }) {
5701
+ if (customRenderHTML) {
5702
+ return customRenderHTML.call(this, { node, HTMLAttributes: attrs });
5703
+ }
5704
+ return [tag, mergeAttributes(HTMLAttributes, attrs, { "data-component": nodeName })];
5705
+ },
5706
+ addNodeView() {
5707
+ return AteNodeViewRenderer(component, {
5708
+ injector,
5709
+ inputs: defaultInputs,
5710
+ wrapperTag: group === "inline" ? "span" : "div",
5711
+ wrapperClass: isTipTapAware
5712
+ ? `ate-node-${nodeName}`
5713
+ : `embedded-component embedded-${nodeName}`,
5714
+ atom,
5715
+ editableContent,
5716
+ contentSelector,
5717
+ contentMode,
5718
+ onOutput,
5719
+ ignoreMutation,
5720
+ });
5721
+ },
5722
+ });
5723
+ }
5724
+
5725
+ /**
5726
+ * Internal registry to store the root injector for the editor.
5727
+ * This allows registerAngularComponent to work without explicitly passing the injector.
5728
+ * @internal
5729
+ */
5730
+ let globalInjector = null;
5731
+ function setGlobalInjector(injector) {
5732
+ globalInjector = injector;
5733
+ }
5734
+ function getGlobalInjector() {
5735
+ if (!globalInjector) {
5736
+ throw new Error("[ATE] Global Injector not found. Make sure to call provideAteEditor() in your app.config.ts or main.ts.");
5737
+ }
5738
+ return globalInjector;
5739
+ }
5740
+
5741
+ /**
5742
+ * Registers ANY Angular component as a TipTap node extension.
5743
+ *
5744
+ * This function is the single public entry point for adding custom components.
5745
+ * It supports two distinct modes:
5746
+ *
5747
+ * 1. **TipTap-Aware Mode** (the component extends `AteAngularNodeView`):
5748
+ * Grants direct access to the TipTap API (`editor`, `node`, `updateAttributes`, etc.) within the component.
5749
+ *
5750
+ * 2. **Standard Mode** (library or legacy components):
5751
+ * Allows using any existing Angular component. Its `@Input()` properties are automatically
5752
+ * synchronized with TipTap node attributes.
5753
+ *
5754
+ * @param injectorOrOptions - The Angular Injector OR the configuration options
5755
+ * @param maybeOptions - Configuration options (if the first param was an injector)
5756
+ * @returns A TipTap Node extension ready to be used
5757
+ *
5758
+ * @example
5759
+ * ```typescript
5760
+ * // Modern way (requires provideAteEditor())
5761
+ * registerAngularComponent({
5762
+ * component: MyComponent,
5763
+ * name: 'myComponent'
5764
+ * });
5765
+ *
5766
+ * // Classic way
5767
+ * registerAngularComponent(injector, {
5768
+ * component: MyComponent
5769
+ * });
5770
+ * ```
5771
+ */
5772
+ function registerAngularComponent(injectorOrOptions, maybeOptions) {
5773
+ let injector;
5774
+ let options;
5775
+ // Duck-typing check: Injectors have a 'get' method
5776
+ const isInjector = (obj) => obj !== null && typeof obj === "object" && typeof obj.get === "function";
5777
+ if (isInjector(injectorOrOptions)) {
5778
+ injector = injectorOrOptions;
5779
+ options = maybeOptions;
5780
+ }
5781
+ else {
5782
+ injector = getGlobalInjector();
5783
+ options = injectorOrOptions;
5784
+ }
5785
+ return createAngularComponentExtension(injector, options);
5786
+ }
5787
+
5788
+ /**
5789
+ * Injection Token for global editor configuration.
5790
+ */
5791
+ const ATE_GLOBAL_CONFIG = new InjectionToken("ATE_GLOBAL_CONFIG");
5792
+
5793
+ const AteSelectionCalculator = editor => {
5794
+ const { selection } = editor.state;
5795
+ const { from, to } = selection;
5796
+ let selectionType = "none";
5797
+ if (selection instanceof TextSelection) {
5798
+ selectionType = "text";
5799
+ }
5800
+ else if (selection instanceof NodeSelection) {
5801
+ selectionType = "node";
5802
+ }
5803
+ else if (selection instanceof CellSelection) {
5804
+ selectionType = "cell";
5805
+ }
5806
+ let isSingleCell = false;
5807
+ if (selection instanceof CellSelection) {
5808
+ isSingleCell = selection.$anchorCell.pos === selection.$headCell.pos;
5809
+ }
5810
+ return {
5811
+ isFocused: editor.view.hasFocus(),
5812
+ isEditable: editor.isEditable,
5813
+ selection: {
5814
+ type: selectionType,
5815
+ from,
5816
+ to,
5817
+ empty: selection.empty || (selectionType === "text" && from === to),
5818
+ isSingleCell: isSingleCell,
5819
+ },
5820
+ nodes: {
5821
+ activeNodeName: editor.state.doc.nodeAt(editor.state.selection.$head.pos)?.type.name || null,
5822
+ },
5823
+ };
5824
+ };
5825
+
5826
+ const AteMarksCalculator = editor => {
5827
+ const isCodeBlock = editor.isActive("codeBlock");
5828
+ const isCode = editor.isActive("code"); // Inline code mark
5829
+ const isImage = editor.isActive("image") || editor.isActive("resizableImage");
5830
+ // Check if marks are generally allowed based on context
5831
+ const marksAllowed = !isCodeBlock && !isImage;
5832
+ // For inline code specifically, we don't allow nesting OTHER marks inside it,
5833
+ // but the code mark ITSELF must be togglable to be removed.
5834
+ const isInsideInlineCode = isCode;
5835
+ // 1. Resolve target element once for this calculation
5836
+ const getTargetElement = () => {
5837
+ if (typeof window === "undefined" || !editor.view?.dom) {
5838
+ return null;
5628
5839
  }
5629
- if (handled.includes(name)) {
5630
- return;
5840
+ try {
5841
+ const { from } = editor.state.selection;
5842
+ const { node } = editor.view.domAtPos(from);
5843
+ return node.nodeType === Node.TEXT_NODE ? node.parentElement : node;
5631
5844
  }
5632
- if (type === "mark") {
5633
- state.marks[name] = editor.isActive(name);
5845
+ catch (_e) {
5846
+ return null;
5634
5847
  }
5635
- else if (type === "node") {
5636
- state.nodes[name] = editor.isActive(name);
5848
+ };
5849
+ const targetEl = getTargetElement() || (typeof window !== "undefined" ? editor.view?.dom : null);
5850
+ const computedStyle = targetEl && typeof window !== "undefined" ? window.getComputedStyle(targetEl) : null;
5851
+ // 2. Lightweight helper to extract properties from the pre-calculated style object
5852
+ const getStyle = (prop) => {
5853
+ if (!computedStyle) {
5854
+ return null;
5637
5855
  }
5638
- });
5639
- return state;
5640
- };
5641
-
5642
- const AteLinkClickBehavior = Extension.create({
5643
- name: "linkClickBehavior",
5644
- addProseMirrorPlugins() {
5645
- return [
5646
- new Plugin({
5647
- key: new PluginKey("linkClickBehavior"),
5648
- props: {
5649
- handleClick(view, _pos, event) {
5650
- // handleClick only runs in the browser, but we guard it for absolute SSR safety
5651
- if (typeof window === "undefined") {
5652
- return false;
5653
- }
5654
- const isModKey = event.ctrlKey || event.metaKey;
5655
- // If editor is editable, only proceed if Ctrl/Cmd is pressed
5656
- if (view.editable && !isModKey) {
5657
- return false;
5658
- }
5856
+ const val = computedStyle.getPropertyValue(prop);
5857
+ return normalizeColor(val);
5858
+ };
5859
+ const colorMark = editor.getAttributes("textStyle")["color"] || null;
5860
+ const backgroundMark = editor.getAttributes("highlight")["color"] || null;
5861
+ return {
5862
+ marks: {
5863
+ bold: editor.isActive("bold"),
5864
+ italic: editor.isActive("italic"),
5865
+ underline: editor.isActive("underline"),
5866
+ strike: editor.isActive("strike"),
5867
+ code: isCode,
5868
+ superscript: editor.isActive("superscript"),
5869
+ subscript: editor.isActive("subscript"),
5870
+ highlight: editor.isActive("highlight"),
5871
+ link: editor.isActive("link"),
5872
+ linkHref: editor.getAttributes("link")["href"] || null,
5873
+ color: colorMark,
5874
+ computedColor: colorMark || getStyle("color"),
5875
+ background: backgroundMark,
5876
+ computedBackground: backgroundMark || getStyle("background-color"),
5877
+ linkOpenOnClick: editor.extensionManager.extensions.find(ext => ext.name === "link")?.options?.openOnClick ??
5878
+ false,
5879
+ },
5880
+ can: {
5881
+ toggleBold: marksAllowed && !isInsideInlineCode && editor.can().toggleBold(),
5882
+ toggleItalic: marksAllowed && !isInsideInlineCode && editor.can().toggleItalic(),
5883
+ toggleUnderline: marksAllowed && !isInsideInlineCode && editor.can().toggleUnderline(),
5884
+ toggleStrike: marksAllowed && !isInsideInlineCode && editor.can().toggleStrike(),
5885
+ toggleCode: marksAllowed && editor.can().toggleCode(),
5886
+ toggleHighlight: marksAllowed && !isInsideInlineCode && editor.can().toggleHighlight(),
5887
+ toggleLink: marksAllowed &&
5888
+ !isInsideInlineCode &&
5889
+ (editor.can().setLink({ href: "" }) || editor.can().unsetLink()),
5890
+ toggleSuperscript: marksAllowed && !isInsideInlineCode && editor.can().toggleSuperscript(),
5891
+ toggleSubscript: marksAllowed && !isInsideInlineCode && editor.can().toggleSubscript(),
5892
+ setColor: marksAllowed && !isInsideInlineCode && editor.can().setColor(""),
5893
+ setHighlight: marksAllowed && !isInsideInlineCode && editor.can().setHighlight(),
5894
+ undo: editor.can().undo(),
5895
+ redo: editor.can().redo(),
5896
+ },
5897
+ };
5898
+ };
5899
+
5900
+ const AteTableCalculator = editor => {
5901
+ const isTable = editor.isActive("table");
5902
+ if (!isTable) {
5903
+ return {
5904
+ nodes: {
5905
+ isTable: false,
5906
+ isTableCell: false,
5907
+ isTableHeaderRow: false,
5908
+ isTableHeaderColumn: false,
5909
+ },
5910
+ };
5911
+ }
5912
+ const { selection } = editor.state;
5913
+ return {
5914
+ nodes: {
5915
+ isTable: true,
5916
+ isTableNodeSelected: selection instanceof NodeSelection && selection.node.type.name === "table",
5917
+ isTableCell: editor.isActive("tableCell") || editor.isActive("tableHeader"),
5918
+ isTableHeaderRow: editor.isActive("tableHeader", { row: true }),
5919
+ isTableHeaderColumn: editor.isActive("tableHeader", { column: true }),
5920
+ },
5921
+ can: {
5922
+ addRowBefore: editor.can().addRowBefore(),
5923
+ addRowAfter: editor.can().addRowAfter(),
5924
+ deleteRow: editor.can().deleteRow(),
5925
+ addColumnBefore: editor.can().addColumnBefore(),
5926
+ addColumnAfter: editor.can().addColumnAfter(),
5927
+ deleteColumn: editor.can().deleteColumn(),
5928
+ deleteTable: editor.can().deleteTable(),
5929
+ mergeCells: editor.can().mergeCells(),
5930
+ splitCell: editor.can().splitCell(),
5931
+ toggleHeaderRow: editor.can().toggleHeaderRow(),
5932
+ toggleHeaderColumn: editor.can().toggleHeaderColumn(),
5933
+ },
5934
+ };
5935
+ };
5936
+
5937
+ const AteImageCalculator = editor => {
5938
+ return {
5939
+ nodes: {
5940
+ isImage: editor.isActive("image") || editor.isActive("resizableImage"),
5941
+ },
5942
+ };
5943
+ };
5944
+
5945
+ const AteStructureCalculator = editor => {
5946
+ return {
5947
+ nodes: {
5948
+ isBlockquote: editor.isActive("blockquote"),
5949
+ isCodeBlock: editor.isActive("codeBlock"),
5950
+ isBulletList: editor.isActive("bulletList"),
5951
+ isOrderedList: editor.isActive("orderedList"),
5952
+ h1: editor.isActive("heading", { level: 1 }),
5953
+ h2: editor.isActive("heading", { level: 2 }),
5954
+ h3: editor.isActive("heading", { level: 3 }),
5955
+ alignLeft: editor.isActive({ textAlign: "left" }),
5956
+ alignCenter: editor.isActive({ textAlign: "center" }),
5957
+ alignRight: editor.isActive({ textAlign: "right" }),
5958
+ alignJustify: editor.isActive({ textAlign: "justify" }),
5959
+ },
5960
+ can: {
5961
+ toggleHeading1: editor.can().toggleHeading({ level: 1 }),
5962
+ toggleHeading2: editor.can().toggleHeading({ level: 2 }),
5963
+ toggleHeading3: editor.can().toggleHeading({ level: 3 }),
5964
+ toggleBulletList: editor.can().toggleBulletList(),
5965
+ toggleOrderedList: editor.can().toggleOrderedList(),
5966
+ toggleBlockquote: editor.can().toggleBlockquote(),
5967
+ toggleCodeBlock: editor.can().toggleCodeBlock(),
5968
+ setTextAlignLeft: editor.can().setTextAlign("left"),
5969
+ setTextAlignCenter: editor.can().setTextAlign("center"),
5970
+ setTextAlignRight: editor.can().setTextAlign("right"),
5971
+ setTextAlignJustify: editor.can().setTextAlign("justify"),
5972
+ insertHorizontalRule: editor.can().setHorizontalRule(),
5973
+ insertTable: editor.can().insertTable(),
5974
+ insertImage: editor.can().setResizableImage({ src: "" }),
5975
+ },
5976
+ };
5977
+ };
5978
+
5979
+ /**
5980
+ * DiscoveryCalculator automatically detects and tracks the state of any TipTap extension.
5981
+ * It provides a "fallback" reactive state for any mark or node not explicitly handled
5982
+ * by specialized calculators.
5983
+ */
5984
+ const AteDiscoveryCalculator = (editor) => {
5985
+ const state = {
5986
+ marks: {},
5987
+ nodes: {},
5988
+ };
5989
+ // We skip core extensions that are already handled by specialized calculators
5990
+ // to avoid redundant calculations and maintain precise attribute tracking.
5991
+ const handled = [
5992
+ "bold",
5993
+ "italic",
5994
+ "underline",
5995
+ "strike",
5996
+ "code",
5997
+ "link",
5998
+ "highlight",
5999
+ "superscript",
6000
+ "subscript",
6001
+ "table",
6002
+ "image",
6003
+ "resizableImage",
6004
+ "heading",
6005
+ "bulletList",
6006
+ "orderedList",
6007
+ "blockquote",
6008
+ "textAlign",
6009
+ "textStyle",
6010
+ "color",
6011
+ ];
6012
+ editor.extensionManager.extensions.forEach(extension => {
6013
+ const name = extension.name;
6014
+ const type = extension.type;
6015
+ // Skip internal/core extensions or already handled ones
6016
+ if ([
6017
+ "selection",
6018
+ "editable",
6019
+ "focus",
6020
+ "undo",
6021
+ "redo",
6022
+ "history",
6023
+ "placeholder",
6024
+ "characterCount",
6025
+ ].includes(name)) {
6026
+ return;
6027
+ }
6028
+ if (handled.includes(name)) {
6029
+ return;
6030
+ }
6031
+ if (type === "mark") {
6032
+ state.marks[name] = editor.isActive(name);
6033
+ }
6034
+ else if (type === "node") {
6035
+ state.nodes[name] = editor.isActive(name);
6036
+ }
6037
+ });
6038
+ return state;
6039
+ };
6040
+
6041
+ const AteLinkClickBehavior = Extension.create({
6042
+ name: "linkClickBehavior",
6043
+ addProseMirrorPlugins() {
6044
+ return [
6045
+ new Plugin({
6046
+ key: new PluginKey("linkClickBehavior"),
6047
+ props: {
6048
+ handleClick(view, _pos, event) {
6049
+ // handleClick only runs in the browser, but we guard it for absolute SSR safety
6050
+ if (typeof window === "undefined") {
6051
+ return false;
6052
+ }
6053
+ const isModKey = event.ctrlKey || event.metaKey;
6054
+ // If editor is editable, only proceed if Ctrl/Cmd is pressed
6055
+ if (view.editable && !isModKey) {
6056
+ return false;
6057
+ }
5659
6058
  const attrs = getAttributes(view.state, "link");
5660
6059
  if (attrs["href"]) {
5661
6060
  window.open(attrs["href"], "_blank", "noopener,noreferrer");
@@ -5746,6 +6145,14 @@ const ATE_DEFAULT_CELL_MENU_CONFIG = {
5746
6145
  };
5747
6146
 
5748
6147
  // Slash commands configuration is handled dynamically via slashCommandsConfigComputed
6148
+ /**
6149
+ * The main rich-text editor component for Angular.
6150
+ *
6151
+ * Powered by Tiptap and built with a native Signal-based architecture, it provides
6152
+ * a seamless, high-performance editing experience. Supports automatic registration
6153
+ * of Angular components as interactive nodes ('Angular Nodes'), full Reactive Forms
6154
+ * integration, and extensive customization via the AteEditorConfig.
6155
+ */
5749
6156
  class AngularTiptapEditorComponent {
5750
6157
  // ============================================
5751
6158
  // Toolbar / Bubble Menu Coordination
@@ -5758,50 +6165,50 @@ class AngularTiptapEditorComponent {
5758
6165
  }
5759
6166
  constructor() {
5760
6167
  /** Configuration globale de l'éditeur */
5761
- this.config = input({}, ...(ngDevMode ? [{ debugName: "config" }] : []));
5762
- this.content = input("", ...(ngDevMode ? [{ debugName: "content" }] : []));
5763
- this.placeholder = input("", ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
5764
- this.editable = input(true, ...(ngDevMode ? [{ debugName: "editable" }] : []));
5765
- this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
5766
- this.minHeight = input(200, ...(ngDevMode ? [{ debugName: "minHeight" }] : []));
5767
- this.height = input(undefined, ...(ngDevMode ? [{ debugName: "height" }] : []));
5768
- this.maxHeight = input(undefined, ...(ngDevMode ? [{ debugName: "maxHeight" }] : []));
5769
- this.fillContainer = input(false, ...(ngDevMode ? [{ debugName: "fillContainer" }] : []));
5770
- this.showToolbar = input(true, ...(ngDevMode ? [{ debugName: "showToolbar" }] : []));
5771
- this.showFooter = input(true, ...(ngDevMode ? [{ debugName: "showFooter" }] : []));
5772
- this.showCharacterCount = input(true, ...(ngDevMode ? [{ debugName: "showCharacterCount" }] : []));
5773
- this.showWordCount = input(true, ...(ngDevMode ? [{ debugName: "showWordCount" }] : []));
5774
- this.maxCharacters = input(undefined, ...(ngDevMode ? [{ debugName: "maxCharacters" }] : []));
5775
- this.enableOfficePaste = input(true, ...(ngDevMode ? [{ debugName: "enableOfficePaste" }] : []));
5776
- this.enableSlashCommands = input(true, ...(ngDevMode ? [{ debugName: "enableSlashCommands" }] : []));
5777
- this.slashCommands = input({}, ...(ngDevMode ? [{ debugName: "slashCommands" }] : []));
5778
- this.customSlashCommands = input(undefined, ...(ngDevMode ? [{ debugName: "customSlashCommands" }] : []));
5779
- this.locale = input(undefined, ...(ngDevMode ? [{ debugName: "locale" }] : []));
5780
- this.autofocus = input(false, ...(ngDevMode ? [{ debugName: "autofocus" }] : []));
5781
- this.seamless = input(false, ...(ngDevMode ? [{ debugName: "seamless" }] : []));
5782
- this.floatingToolbar = input(false, ...(ngDevMode ? [{ debugName: "floatingToolbar" }] : []));
5783
- this.showEditToggle = input(false, ...(ngDevMode ? [{ debugName: "showEditToggle" }] : []));
5784
- this.spellcheck = input(true, ...(ngDevMode ? [{ debugName: "spellcheck" }] : []));
5785
- this.tiptapExtensions = input([], ...(ngDevMode ? [{ debugName: "tiptapExtensions" }] : []));
5786
- this.tiptapOptions = input({}, ...(ngDevMode ? [{ debugName: "tiptapOptions" }] : []));
6168
+ this.config = input({});
6169
+ this.content = input("");
6170
+ this.placeholder = input("");
6171
+ this.editable = input(true);
6172
+ this.disabled = input(false);
6173
+ this.minHeight = input(200);
6174
+ this.height = input(undefined);
6175
+ this.maxHeight = input(undefined);
6176
+ this.fillContainer = input(false);
6177
+ this.showToolbar = input(true);
6178
+ this.showFooter = input(true);
6179
+ this.showCharacterCount = input(true);
6180
+ this.showWordCount = input(true);
6181
+ this.maxCharacters = input(undefined);
6182
+ this.enableOfficePaste = input(true);
6183
+ this.enableSlashCommands = input(true);
6184
+ this.slashCommands = input({});
6185
+ this.customSlashCommands = input(undefined);
6186
+ this.locale = input(undefined);
6187
+ this.autofocus = input(false);
6188
+ this.seamless = input(false);
6189
+ this.floatingToolbar = input(false);
6190
+ this.showEditToggle = input(false);
6191
+ this.spellcheck = input(true);
6192
+ this.tiptapExtensions = input([]);
6193
+ this.tiptapOptions = input({});
5787
6194
  // Nouveaux inputs pour les bubble menus
5788
- this.showBubbleMenu = input(true, ...(ngDevMode ? [{ debugName: "showBubbleMenu" }] : []));
5789
- this.bubbleMenu = input(ATE_DEFAULT_BUBBLE_MENU_CONFIG, ...(ngDevMode ? [{ debugName: "bubbleMenu" }] : []));
5790
- this.showImageBubbleMenu = input(true, ...(ngDevMode ? [{ debugName: "showImageBubbleMenu" }] : []));
5791
- this.imageBubbleMenu = input(ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG, ...(ngDevMode ? [{ debugName: "imageBubbleMenu" }] : []));
6195
+ this.showBubbleMenu = input(true);
6196
+ this.bubbleMenu = input(ATE_DEFAULT_BUBBLE_MENU_CONFIG);
6197
+ this.showImageBubbleMenu = input(true);
6198
+ this.imageBubbleMenu = input(ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG);
5792
6199
  // Configuration de la toolbar
5793
- this.toolbar = input({}, ...(ngDevMode ? [{ debugName: "toolbar" }] : []));
6200
+ this.toolbar = input({});
5794
6201
  // Configuration des menus de table
5795
- this.showTableBubbleMenu = input(true, ...(ngDevMode ? [{ debugName: "showTableBubbleMenu" }] : []));
5796
- this.tableBubbleMenu = input(ATE_DEFAULT_TABLE_MENU_CONFIG, ...(ngDevMode ? [{ debugName: "tableBubbleMenu" }] : []));
5797
- this.showCellBubbleMenu = input(true, ...(ngDevMode ? [{ debugName: "showCellBubbleMenu" }] : []));
5798
- this.cellBubbleMenu = input(ATE_DEFAULT_CELL_MENU_CONFIG, ...(ngDevMode ? [{ debugName: "cellBubbleMenu" }] : []));
6202
+ this.showTableBubbleMenu = input(true);
6203
+ this.tableBubbleMenu = input(ATE_DEFAULT_TABLE_MENU_CONFIG);
6204
+ this.showCellBubbleMenu = input(true);
6205
+ this.cellBubbleMenu = input(ATE_DEFAULT_CELL_MENU_CONFIG);
5799
6206
  /**
5800
6207
  * Additionnal state calculators to extend the reactive editor state.
5801
6208
  */
5802
- this.stateCalculators = input([], ...(ngDevMode ? [{ debugName: "stateCalculators" }] : []));
6209
+ this.stateCalculators = input([]);
5803
6210
  // Nouveau input pour la configuration de l'upload d'images
5804
- this.imageUpload = input({}, ...(ngDevMode ? [{ debugName: "imageUpload" }] : []));
6211
+ this.imageUpload = input({});
5805
6212
  /**
5806
6213
  * Custom handler for image uploads.
5807
6214
  * When provided, images will be processed through this handler instead of being converted to base64.
@@ -5821,7 +6228,7 @@ class AngularTiptapEditorComponent {
5821
6228
  * // <angular-tiptap-editor [imageUploadHandler]="myUploadHandler" />
5822
6229
  * ```
5823
6230
  */
5824
- this.imageUploadHandler = input(undefined, ...(ngDevMode ? [{ debugName: "imageUploadHandler" }] : []));
6231
+ this.imageUploadHandler = input(undefined);
5825
6232
  // Nouveaux outputs
5826
6233
  this.contentChange = output();
5827
6234
  this.editorCreated = output();
@@ -5832,11 +6239,11 @@ class AngularTiptapEditorComponent {
5832
6239
  // ViewChild with signal
5833
6240
  this.editorElement = viewChild.required("editorElement");
5834
6241
  // Private signals for internal state
5835
- this._editor = signal(null, ...(ngDevMode ? [{ debugName: "_editor" }] : []));
5836
- this._characterCount = signal(0, ...(ngDevMode ? [{ debugName: "_characterCount" }] : []));
5837
- this._wordCount = signal(0, ...(ngDevMode ? [{ debugName: "_wordCount" }] : []));
5838
- this._isDragOver = signal(false, ...(ngDevMode ? [{ debugName: "_isDragOver" }] : []));
5839
- this._editorFullyInitialized = signal(false, ...(ngDevMode ? [{ debugName: "_editorFullyInitialized" }] : []));
6242
+ this._editor = signal(null);
6243
+ this._characterCount = signal(0);
6244
+ this._wordCount = signal(0);
6245
+ this._isDragOver = signal(false);
6246
+ this._editorFullyInitialized = signal(false);
5840
6247
  // Anti-echo: track last emitted HTML to prevent cursor reset on parent echo
5841
6248
  this.lastEmittedHtml = null;
5842
6249
  // Read-only access to signals
@@ -5845,58 +6252,58 @@ class AngularTiptapEditorComponent {
5845
6252
  this.wordCount = this._wordCount.asReadonly();
5846
6253
  this.isDragOver = this._isDragOver.asReadonly();
5847
6254
  this.editorFullyInitialized = this._editorFullyInitialized.asReadonly();
5848
- this._isFormControlDisabled = signal(false, ...(ngDevMode ? [{ debugName: "_isFormControlDisabled" }] : []));
6255
+ this._isFormControlDisabled = signal(false);
5849
6256
  this.isFormControlDisabled = this._isFormControlDisabled.asReadonly();
5850
6257
  // Combined disabled state (Input + FormControl)
5851
- this.mergedDisabled = computed(() => (this.config().disabled ?? this.disabled()) || this.isFormControlDisabled(), ...(ngDevMode ? [{ debugName: "mergedDisabled" }] : []));
6258
+ this.mergedDisabled = computed(() => (this.effectiveConfig().disabled ?? this.disabled()) || this.isFormControlDisabled());
5852
6259
  // Computed for editor states
5853
- this.isEditorReady = computed(() => this.editor() !== null, ...(ngDevMode ? [{ debugName: "isEditorReady" }] : []));
6260
+ this.isEditorReady = computed(() => this.editor() !== null);
5854
6261
  // ============================================
5855
6262
  // UNIFIED CONFIGURATION COMPUTED PROPERTIES
5856
6263
  // ============================================
5857
6264
  // Appearance & Fundamentals
5858
6265
  this.finalSeamless = computed(() => {
5859
- const fromConfig = this.config().mode;
6266
+ const fromConfig = this.effectiveConfig().mode;
5860
6267
  if (fromConfig !== undefined) {
5861
6268
  return fromConfig === "seamless";
5862
6269
  }
5863
6270
  return this.seamless();
5864
- }, ...(ngDevMode ? [{ debugName: "finalSeamless" }] : []));
5865
- this.finalEditable = computed(() => this.config().editable ?? this.editable(), ...(ngDevMode ? [{ debugName: "finalEditable" }] : []));
5866
- this.finalPlaceholder = computed(() => this.config().placeholder ??
5867
- (this.placeholder() || this.currentTranslations().editor.placeholder), ...(ngDevMode ? [{ debugName: "finalPlaceholder" }] : []));
5868
- this.finalFillContainer = computed(() => this.config().fillContainer ?? this.fillContainer(), ...(ngDevMode ? [{ debugName: "finalFillContainer" }] : []));
5869
- this.finalShowFooter = computed(() => this.config().showFooter ?? this.showFooter(), ...(ngDevMode ? [{ debugName: "finalShowFooter" }] : []));
5870
- this.finalShowEditToggle = computed(() => this.config().showEditToggle ?? this.showEditToggle(), ...(ngDevMode ? [{ debugName: "finalShowEditToggle" }] : []));
5871
- this.finalHeight = computed(() => this.config().height ?? (this.height() ? `${this.height()}px` : undefined), ...(ngDevMode ? [{ debugName: "finalHeight" }] : []));
5872
- this.finalMinHeight = computed(() => this.config().minHeight ?? (this.minHeight() ? `${this.minHeight()}px` : undefined), ...(ngDevMode ? [{ debugName: "finalMinHeight" }] : []));
5873
- this.finalMaxHeight = computed(() => this.config().maxHeight ?? (this.maxHeight() ? `${this.maxHeight()}px` : undefined), ...(ngDevMode ? [{ debugName: "finalMaxHeight" }] : []));
5874
- this.finalSpellcheck = computed(() => this.config().spellcheck ?? this.spellcheck(), ...(ngDevMode ? [{ debugName: "finalSpellcheck" }] : []));
5875
- this.finalEnableOfficePaste = computed(() => this.config().enableOfficePaste ?? this.enableOfficePaste(), ...(ngDevMode ? [{ debugName: "finalEnableOfficePaste" }] : []));
6271
+ });
6272
+ this.finalEditable = computed(() => this.effectiveConfig().editable ?? this.editable());
6273
+ this.finalPlaceholder = computed(() => this.effectiveConfig().placeholder ??
6274
+ (this.placeholder() || this.currentTranslations().editor.placeholder));
6275
+ this.finalFillContainer = computed(() => this.effectiveConfig().fillContainer ?? this.fillContainer());
6276
+ this.finalShowFooter = computed(() => this.effectiveConfig().showFooter ?? this.showFooter());
6277
+ this.finalShowEditToggle = computed(() => this.effectiveConfig().showEditToggle ?? this.showEditToggle());
6278
+ this.finalHeight = computed(() => this.effectiveConfig().height ?? (this.height() ? `${this.height()}px` : undefined));
6279
+ this.finalMinHeight = computed(() => this.effectiveConfig().minHeight ?? (this.minHeight() ? `${this.minHeight()}px` : undefined));
6280
+ this.finalMaxHeight = computed(() => this.effectiveConfig().maxHeight ?? (this.maxHeight() ? `${this.maxHeight()}px` : undefined));
6281
+ this.finalSpellcheck = computed(() => this.effectiveConfig().spellcheck ?? this.spellcheck());
6282
+ this.finalEnableOfficePaste = computed(() => this.effectiveConfig().enableOfficePaste ?? this.enableOfficePaste());
5876
6283
  // Features
5877
- this.finalShowToolbar = computed(() => this.config().showToolbar ?? this.showToolbar(), ...(ngDevMode ? [{ debugName: "finalShowToolbar" }] : []));
6284
+ this.finalShowToolbar = computed(() => this.effectiveConfig().showToolbar ?? this.showToolbar());
5878
6285
  this.finalToolbarConfig = computed(() => {
5879
- const fromConfig = this.config().toolbar;
6286
+ const fromConfig = this.effectiveConfig().toolbar;
5880
6287
  const base = ATE_DEFAULT_TOOLBAR_CONFIG;
5881
6288
  if (fromConfig) {
5882
6289
  return { ...base, ...fromConfig };
5883
6290
  }
5884
6291
  const fromInput = this.toolbar();
5885
6292
  return Object.keys(fromInput).length === 0 ? base : { ...base, ...fromInput };
5886
- }, ...(ngDevMode ? [{ debugName: "finalToolbarConfig" }] : []));
5887
- this.finalFloatingToolbar = computed(() => this.config().floatingToolbar ?? this.floatingToolbar(), ...(ngDevMode ? [{ debugName: "finalFloatingToolbar" }] : []));
5888
- this.finalShowBubbleMenu = computed(() => this.config().showBubbleMenu ?? this.showBubbleMenu(), ...(ngDevMode ? [{ debugName: "finalShowBubbleMenu" }] : []));
6293
+ });
6294
+ this.finalFloatingToolbar = computed(() => this.effectiveConfig().floatingToolbar ?? this.floatingToolbar());
6295
+ this.finalShowBubbleMenu = computed(() => this.effectiveConfig().showBubbleMenu ?? this.showBubbleMenu());
5889
6296
  this.finalBubbleMenuConfig = computed(() => {
5890
- const fromConfig = this.config().bubbleMenu;
6297
+ const fromConfig = this.effectiveConfig().bubbleMenu;
5891
6298
  const base = ATE_DEFAULT_BUBBLE_MENU_CONFIG;
5892
6299
  if (fromConfig) {
5893
6300
  return { ...base, ...fromConfig };
5894
6301
  }
5895
6302
  return Object.keys(this.bubbleMenu()).length === 0 ? base : { ...base, ...this.bubbleMenu() };
5896
- }, ...(ngDevMode ? [{ debugName: "finalBubbleMenuConfig" }] : []));
5897
- this.finalShowImageBubbleMenu = computed(() => this.config().showImageBubbleMenu ?? this.showImageBubbleMenu(), ...(ngDevMode ? [{ debugName: "finalShowImageBubbleMenu" }] : []));
6303
+ });
6304
+ this.finalShowImageBubbleMenu = computed(() => this.effectiveConfig().showImageBubbleMenu ?? this.showImageBubbleMenu());
5898
6305
  this.finalImageBubbleMenuConfig = computed(() => {
5899
- const fromConfig = this.config().imageBubbleMenu;
6306
+ const fromConfig = this.effectiveConfig().imageBubbleMenu;
5900
6307
  const base = ATE_DEFAULT_IMAGE_BUBBLE_MENU_CONFIG;
5901
6308
  if (fromConfig) {
5902
6309
  return { ...base, ...fromConfig };
@@ -5904,10 +6311,10 @@ class AngularTiptapEditorComponent {
5904
6311
  return Object.keys(this.imageBubbleMenu()).length === 0
5905
6312
  ? base
5906
6313
  : { ...base, ...this.imageBubbleMenu() };
5907
- }, ...(ngDevMode ? [{ debugName: "finalImageBubbleMenuConfig" }] : []));
5908
- this.finalShowTableBubbleMenu = computed(() => this.config().showTableMenu ?? this.showTableBubbleMenu(), ...(ngDevMode ? [{ debugName: "finalShowTableBubbleMenu" }] : []));
6314
+ });
6315
+ this.finalShowTableBubbleMenu = computed(() => this.effectiveConfig().showTableMenu ?? this.showTableBubbleMenu());
5909
6316
  this.finalTableBubbleMenuConfig = computed(() => {
5910
- const fromConfig = this.config().tableBubbleMenu;
6317
+ const fromConfig = this.effectiveConfig().tableBubbleMenu;
5911
6318
  const base = ATE_DEFAULT_TABLE_MENU_CONFIG;
5912
6319
  if (fromConfig) {
5913
6320
  return { ...base, ...fromConfig };
@@ -5915,10 +6322,10 @@ class AngularTiptapEditorComponent {
5915
6322
  return Object.keys(this.tableBubbleMenu()).length === 0
5916
6323
  ? base
5917
6324
  : { ...base, ...this.tableBubbleMenu() };
5918
- }, ...(ngDevMode ? [{ debugName: "finalTableBubbleMenuConfig" }] : []));
5919
- this.finalShowCellBubbleMenu = computed(() => this.config().showCellMenu ?? this.showCellBubbleMenu(), ...(ngDevMode ? [{ debugName: "finalShowCellBubbleMenu" }] : []));
6325
+ });
6326
+ this.finalShowCellBubbleMenu = computed(() => this.effectiveConfig().showCellMenu ?? this.showCellBubbleMenu());
5920
6327
  this.finalCellBubbleMenuConfig = computed(() => {
5921
- const fromConfig = this.config().cellBubbleMenu;
6328
+ const fromConfig = this.effectiveConfig().cellBubbleMenu;
5922
6329
  const base = ATE_DEFAULT_CELL_MENU_CONFIG;
5923
6330
  if (fromConfig) {
5924
6331
  return { ...base, ...fromConfig };
@@ -5926,11 +6333,13 @@ class AngularTiptapEditorComponent {
5926
6333
  return Object.keys(this.cellBubbleMenu()).length === 0
5927
6334
  ? base
5928
6335
  : { ...base, ...this.cellBubbleMenu() };
5929
- }, ...(ngDevMode ? [{ debugName: "finalCellBubbleMenuConfig" }] : []));
5930
- this.finalEnableSlashCommands = computed(() => this.config().enableSlashCommands ?? this.enableSlashCommands(), ...(ngDevMode ? [{ debugName: "finalEnableSlashCommands" }] : []));
6336
+ });
6337
+ this.finalEnableSlashCommands = computed(() => this.effectiveConfig().enableSlashCommands ?? this.enableSlashCommands());
5931
6338
  this.finalSlashCommandsConfig = computed(() => {
5932
- const fromConfig = this.config().slashCommands;
5933
- const customConfig = this.customSlashCommands();
6339
+ const fromConfig = this.effectiveConfig().slashCommands;
6340
+ const fromGlobalCustom = this.effectiveConfig().customSlashCommands;
6341
+ const fromInputCustom = this.customSlashCommands();
6342
+ const customConfig = fromInputCustom ?? fromGlobalCustom;
5934
6343
  if (customConfig) {
5935
6344
  return customConfig;
5936
6345
  }
@@ -5941,16 +6350,21 @@ class AngularTiptapEditorComponent {
5941
6350
  return {
5942
6351
  commands: filterSlashCommands(baseConfig, this.i18nService, this.editorCommandsService, this.finalImageUploadConfig()),
5943
6352
  };
5944
- }, ...(ngDevMode ? [{ debugName: "finalSlashCommandsConfig" }] : []));
6353
+ });
5945
6354
  // Behavior
5946
- this.finalAutofocus = computed(() => this.config().autofocus ?? this.autofocus(), ...(ngDevMode ? [{ debugName: "finalAutofocus" }] : []));
5947
- this.finalMaxCharacters = computed(() => this.config().maxCharacters ?? this.maxCharacters(), ...(ngDevMode ? [{ debugName: "finalMaxCharacters" }] : []));
5948
- this.finalShowCharacterCount = computed(() => this.config().showCharacterCount ?? this.showCharacterCount(), ...(ngDevMode ? [{ debugName: "finalShowCharacterCount" }] : []));
5949
- this.finalShowWordCount = computed(() => this.config().showWordCount ?? this.showWordCount(), ...(ngDevMode ? [{ debugName: "finalShowWordCount" }] : []));
5950
- this.finalLocale = computed(() => this.config().locale ?? this.locale(), ...(ngDevMode ? [{ debugName: "finalLocale" }] : []));
6355
+ this.finalAutofocus = computed(() => this.effectiveConfig().autofocus ?? this.autofocus());
6356
+ this.finalMaxCharacters = computed(() => this.effectiveConfig().maxCharacters ?? this.maxCharacters());
6357
+ this.finalShowCharacterCount = computed(() => this.effectiveConfig().showCharacterCount ?? this.showCharacterCount());
6358
+ this.finalShowWordCount = computed(() => this.effectiveConfig().showWordCount ?? this.showWordCount());
6359
+ this.finalLocale = computed(() => this.effectiveConfig().locale ?? this.locale());
6360
+ // Extensions & Options
6361
+ this.finalTiptapExtensions = computed(() => this.effectiveConfig().tiptapExtensions ?? this.tiptapExtensions() ?? []);
6362
+ this.finalTiptapOptions = computed(() => this.effectiveConfig().tiptapOptions ?? this.tiptapOptions() ?? {});
6363
+ this.finalStateCalculators = computed(() => this.effectiveConfig().stateCalculators ?? this.stateCalculators() ?? []);
6364
+ this.finalAngularNodesConfig = computed(() => this.effectiveConfig().angularNodes ?? []);
5951
6365
  // Image Upload
5952
6366
  this.finalImageUploadConfig = computed(() => {
5953
- const fromConfig = this.config().imageUpload;
6367
+ const fromConfig = this.effectiveConfig().imageUpload;
5954
6368
  const fromInput = this.imageUpload();
5955
6369
  const merged = {
5956
6370
  maxSize: 5, // Default 5MB
@@ -5969,8 +6383,8 @@ class AngularTiptapEditorComponent {
5969
6383
  ...merged,
5970
6384
  maxSize: merged.maxSize * 1024 * 1024, // Convert MB to bytes for internal service
5971
6385
  };
5972
- }, ...(ngDevMode ? [{ debugName: "finalImageUploadConfig" }] : []));
5973
- this.finalImageUploadHandler = computed(() => this.config().imageUpload?.handler ?? this.imageUploadHandler(), ...(ngDevMode ? [{ debugName: "finalImageUploadHandler" }] : []));
6386
+ });
6387
+ this.finalImageUploadHandler = computed(() => this.effectiveConfig().imageUpload?.handler ?? this.imageUploadHandler());
5974
6388
  // Computed for current translations (allows per-instance override via config or input)
5975
6389
  this.currentTranslations = computed(() => {
5976
6390
  const localeOverride = this.finalLocale();
@@ -5979,7 +6393,7 @@ class AngularTiptapEditorComponent {
5979
6393
  return allTranslations[localeOverride] || this.i18nService.translations();
5980
6394
  }
5981
6395
  return this.i18nService.translations();
5982
- }, ...(ngDevMode ? [{ debugName: "currentTranslations" }] : []));
6396
+ });
5983
6397
  this._destroyRef = inject(DestroyRef);
5984
6398
  // NgControl for management of FormControls
5985
6399
  this.ngControl = inject(NgControl, { self: true, optional: true });
@@ -5987,6 +6401,17 @@ class AngularTiptapEditorComponent {
5987
6401
  this.editorCommandsService = inject(AteEditorCommandsService);
5988
6402
  // Access editor state via service
5989
6403
  this.editorState = this.editorCommandsService.editorState;
6404
+ this.injector = inject(Injector);
6405
+ this.globalConfig = inject(ATE_GLOBAL_CONFIG, { optional: true });
6406
+ /**
6407
+ * Final merged configuration.
6408
+ * Priority: Input [config] > Global config via provideAteEditor()
6409
+ */
6410
+ this.effectiveConfig = computed(() => {
6411
+ const fromInput = this.config();
6412
+ const fromGlobal = this.globalConfig || {};
6413
+ return { ...fromGlobal, ...fromInput };
6414
+ });
5990
6415
  // Effect to update editor content (with anti-echo)
5991
6416
  effect(() => {
5992
6417
  const content = this.content(); // Sole reactive dependency
@@ -6010,7 +6435,7 @@ class AngularTiptapEditorComponent {
6010
6435
  }
6011
6436
  editor.commands.setContent(content, false);
6012
6437
  });
6013
- });
6438
+ }, { allowSignalWrites: true });
6014
6439
  // Effect to update height properties
6015
6440
  effect(() => {
6016
6441
  const minHeight = this.finalMinHeight();
@@ -6025,7 +6450,7 @@ class AngularTiptapEditorComponent {
6025
6450
  element.style.setProperty("--editor-max-height", maxHeight ?? "none");
6026
6451
  element.style.setProperty("--editor-overflow", needsScroll ? "auto" : "visible");
6027
6452
  }
6028
- });
6453
+ }, { allowSignalWrites: true });
6029
6454
  // Effect to monitor editability changes
6030
6455
  effect(() => {
6031
6456
  const currentEditor = this.editor();
@@ -6036,12 +6461,12 @@ class AngularTiptapEditorComponent {
6036
6461
  if (currentEditor) {
6037
6462
  this.editorCommandsService.setEditable(currentEditor, isEditable);
6038
6463
  }
6039
- });
6464
+ }, { allowSignalWrites: true });
6040
6465
  // Effect to synchronize image upload handler with the service
6041
6466
  effect(() => {
6042
6467
  const handler = this.finalImageUploadHandler();
6043
6468
  this.editorCommandsService.uploadHandler = handler || null;
6044
- });
6469
+ }, { allowSignalWrites: true });
6045
6470
  // Effect to update character count limit dynamically
6046
6471
  effect(() => {
6047
6472
  const editor = this.editor();
@@ -6052,12 +6477,13 @@ class AngularTiptapEditorComponent {
6052
6477
  characterCountExtension.options.limit = limit;
6053
6478
  }
6054
6479
  }
6055
- });
6056
- // Effect to re-initialize editor when extensions or options change
6480
+ }, { allowSignalWrites: true });
6481
+ // Effect to re-initialize editor when technical configuration changes
6057
6482
  effect(() => {
6058
- // Monitor extensions and options
6059
- this.tiptapExtensions();
6060
- this.tiptapOptions();
6483
+ // Monitor technical dependencies
6484
+ this.finalTiptapExtensions();
6485
+ this.finalTiptapOptions();
6486
+ this.finalAngularNodesConfig();
6061
6487
  untracked(() => {
6062
6488
  // Only if already initialized (post AfterViewInit)
6063
6489
  if (this.editorFullyInitialized()) {
@@ -6069,7 +6495,7 @@ class AngularTiptapEditorComponent {
6069
6495
  }
6070
6496
  }
6071
6497
  });
6072
- });
6498
+ }, { allowSignalWrites: true });
6073
6499
  }
6074
6500
  ngAfterViewInit() {
6075
6501
  // La vue est déjà complètement initialisée dans ngAfterViewInit
@@ -6136,7 +6562,7 @@ class AngularTiptapEditorComponent {
6136
6562
  AteImageCalculator,
6137
6563
  AteStructureCalculator,
6138
6564
  AteDiscoveryCalculator,
6139
- ...this.stateCalculators(),
6565
+ ...this.finalStateCalculators(),
6140
6566
  ],
6141
6567
  }),
6142
6568
  ];
@@ -6153,8 +6579,22 @@ class AngularTiptapEditorComponent {
6153
6579
  limit: this.finalMaxCharacters(),
6154
6580
  }));
6155
6581
  }
6582
+ // Register automatic node views from config
6583
+ const autoNodeViews = this.finalAngularNodesConfig();
6584
+ autoNodeViews.forEach(reg => {
6585
+ const options = typeof reg === "function"
6586
+ ? { component: reg }
6587
+ : reg;
6588
+ try {
6589
+ const extension = registerAngularComponent(this.injector, options);
6590
+ extensions.push(extension);
6591
+ }
6592
+ catch (e) {
6593
+ console.error("[ATE] Failed to auto-register node view:", e);
6594
+ }
6595
+ });
6156
6596
  // Allow addition of custom extensions, but avoid duplicates by filtering by name
6157
- const customExtensions = this.tiptapExtensions();
6597
+ const customExtensions = this.finalTiptapExtensions();
6158
6598
  if (customExtensions.length > 0) {
6159
6599
  const existingNames = new Set(extensions
6160
6600
  .map(ext => ext?.name)
@@ -6166,7 +6606,7 @@ class AngularTiptapEditorComponent {
6166
6606
  extensions.push(...toAdd);
6167
6607
  }
6168
6608
  // Also allow any tiptap user options
6169
- const userOptions = this.tiptapOptions();
6609
+ const userOptions = this.finalTiptapOptions();
6170
6610
  const newEditor = new Editor({
6171
6611
  ...userOptions,
6172
6612
  element: this.editorElement().nativeElement,
@@ -6341,8 +6781,8 @@ class AngularTiptapEditorComponent {
6341
6781
  }, 0);
6342
6782
  }
6343
6783
  }
6344
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AngularTiptapEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6345
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", 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 }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, seamless: { classPropertyName: "seamless", publicName: "seamless", isSignal: true, isRequired: false, transformFunction: null }, floatingToolbar: { classPropertyName: "floatingToolbar", publicName: "floatingToolbar", isSignal: true, isRequired: false, transformFunction: null }, 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 } }, outputs: { contentChange: "contentChange", editorCreated: "editorCreated", editorUpdate: "editorUpdate", editorFocus: "editorFocus", editorBlur: "editorBlur", editableChange: "editableChange" }, 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'", "attr.data-theme": "config().theme" } }, providers: [AteEditorCommandsService, AteImageService, AteColorPickerService, AteLinkService], viewQueries: [{ propertyName: "editorElement", first: true, predicate: ["editorElement"], descendants: true, isSignal: true }], hostDirectives: [{ directive: AteNoopValueAccessorDirective }], ngImport: i0, template: `
6784
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AngularTiptapEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6785
+ 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 }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, seamless: { classPropertyName: "seamless", publicName: "seamless", isSignal: true, isRequired: false, transformFunction: null }, floatingToolbar: { classPropertyName: "floatingToolbar", publicName: "floatingToolbar", isSignal: true, isRequired: false, transformFunction: null }, 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 } }, outputs: { contentChange: "contentChange", editorCreated: "editorCreated", editorUpdate: "editorUpdate", editorFocus: "editorFocus", editorBlur: "editorBlur", editableChange: "editableChange" }, 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'", "attr.data-theme": "config().theme" } }, providers: [AteEditorCommandsService, AteImageService, AteColorPickerService, AteLinkService], viewQueries: [{ propertyName: "editorElement", first: true, predicate: ["editorElement"], descendants: true, isSignal: true }], hostDirectives: [{ directive: AteNoopValueAccessorDirective }], ngImport: i0, template: `
6346
6786
  <div class="ate-editor">
6347
6787
  <!-- Toolbar -->
6348
6788
  @if (finalEditable() && !mergedDisabled() && finalShowToolbar() && editor()) {
@@ -6462,7 +6902,7 @@ class AngularTiptapEditorComponent {
6462
6902
  </div>
6463
6903
  `, 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 }); }
6464
6904
  }
6465
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AngularTiptapEditorComponent, decorators: [{
6905
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AngularTiptapEditorComponent, decorators: [{
6466
6906
  type: Component,
6467
6907
  args: [{ selector: "angular-tiptap-editor", standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, hostDirectives: [AteNoopValueAccessorDirective], host: {
6468
6908
  "[class.fill-container]": "finalFillContainer()",
@@ -6566,532 +7006,170 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
6566
7006
  [config]="finalTableBubbleMenuConfig()"
6567
7007
  [style.display]="editorFullyInitialized() ? 'block' : 'none'"></ate-table-bubble-menu>
6568
7008
  }
6569
-
6570
- <!-- Cell Menu -->
6571
- @if (finalEditable() && finalShowCellBubbleMenu() && editor()) {
6572
- <ate-cell-bubble-menu
6573
- [editor]="editor()!"
6574
- [config]="finalCellBubbleMenuConfig()"
6575
- [style.display]="editorFullyInitialized() ? 'block' : 'none'"></ate-cell-bubble-menu>
6576
- }
6577
-
6578
- <!-- Counters -->
6579
- @if (
6580
- finalEditable() &&
6581
- !mergedDisabled() &&
6582
- finalShowFooter() &&
6583
- (finalShowCharacterCount() || finalShowWordCount())
6584
- ) {
6585
- <div
6586
- class="character-count"
6587
- [class.limit-reached]="finalMaxCharacters() && characterCount() >= finalMaxCharacters()!">
6588
- @if (finalShowCharacterCount()) {
6589
- {{ characterCount() }}
6590
- {{ currentTranslations().editor.character }}{{ characterCount() > 1 ? "s" : "" }}
6591
- @if (finalMaxCharacters()) {
6592
- / {{ finalMaxCharacters() }}
6593
- }
6594
- }
6595
-
6596
- @if (finalShowCharacterCount() && finalShowWordCount()) {
6597
- ,
6598
- }
6599
-
6600
- @if (finalShowWordCount()) {
6601
- {{ wordCount() }}
6602
- {{ currentTranslations().editor.word }}{{ wordCount() > 1 ? "s" : "" }}
6603
- }
6604
- </div>
6605
- }
6606
- </div>
6607
- `, 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"] }]
6608
- }], 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 }] }] } });
6609
-
6610
- /**
6611
- * Clés des boutons de la barre d'outils native
6612
- */
6613
- const ATE_TOOLBAR_KEYS = [
6614
- "bold",
6615
- "italic",
6616
- "underline",
6617
- "strike",
6618
- "code",
6619
- "codeBlock",
6620
- "superscript",
6621
- "subscript",
6622
- "highlight",
6623
- "highlightPicker",
6624
- "heading1",
6625
- "heading2",
6626
- "heading3",
6627
- "bulletList",
6628
- "orderedList",
6629
- "blockquote",
6630
- "alignLeft",
6631
- "alignCenter",
6632
- "alignRight",
6633
- "alignJustify",
6634
- "link",
6635
- "image",
6636
- "horizontalRule",
6637
- "table",
6638
- "undo",
6639
- "redo",
6640
- "clear",
6641
- "textColor",
6642
- "separator",
6643
- ];
6644
-
6645
- /**
6646
- * Clés des options du menu bulle de texte
6647
- */
6648
- const ATE_BUBBLE_MENU_KEYS = [
6649
- "bold",
6650
- "italic",
6651
- "underline",
6652
- "strike",
6653
- "code",
6654
- "superscript",
6655
- "subscript",
6656
- "highlight",
6657
- "highlightPicker",
6658
- "textColor",
6659
- "link",
6660
- "separator",
6661
- ];
6662
- /**
6663
- * Clés des options du menu bulle d'image
6664
- */
6665
- const ATE_IMAGE_BUBBLE_MENU_KEYS = [
6666
- "changeImage",
6667
- "resizeSmall",
6668
- "resizeMedium",
6669
- "resizeLarge",
6670
- "resizeOriginal",
6671
- "deleteImage",
6672
- "separator",
6673
- ];
6674
- /**
6675
- * Clés des options du menu de table
6676
- */
6677
- const ATE_TABLE_BUBBLE_MENU_KEYS = [
6678
- "addRowBefore",
6679
- "addRowAfter",
6680
- "deleteRow",
6681
- "addColumnBefore",
6682
- "addColumnAfter",
6683
- "deleteColumn",
6684
- "deleteTable",
6685
- "toggleHeaderRow",
6686
- "toggleHeaderColumn",
6687
- "separator",
6688
- ];
6689
- /**
6690
- * Clés des options du menu de cellule
6691
- */
6692
- const ATE_CELL_BUBBLE_MENU_KEYS = ["mergeCells", "splitCell"];
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;
7009
+
7010
+ <!-- Cell Menu -->
7011
+ @if (finalEditable() && finalShowCellBubbleMenu() && editor()) {
7012
+ <ate-cell-bubble-menu
7013
+ [editor]="editor()!"
7014
+ [config]="finalCellBubbleMenuConfig()"
7015
+ [style.display]="editorFullyInitialized() ? 'block' : 'none'"></ate-cell-bubble-menu>
7016
+ }
7017
+
7018
+ <!-- Counters -->
7019
+ @if (
7020
+ finalEditable() &&
7021
+ !mergedDisabled() &&
7022
+ finalShowFooter() &&
7023
+ (finalShowCharacterCount() || finalShowWordCount())
7024
+ ) {
7025
+ <div
7026
+ class="character-count"
7027
+ [class.limit-reached]="finalMaxCharacters() && characterCount() >= finalMaxCharacters()!">
7028
+ @if (finalShowCharacterCount()) {
7029
+ {{ characterCount() }}
7030
+ {{ currentTranslations().editor.character }}{{ characterCount() > 1 ? "s" : "" }}
7031
+ @if (finalMaxCharacters()) {
7032
+ / {{ finalMaxCharacters() }}
7033
+ }
7034
+ }
7035
+
7036
+ @if (finalShowCharacterCount() && finalShowWordCount()) {
7037
+ ,
7038
+ }
7039
+
7040
+ @if (finalShowWordCount()) {
7041
+ {{ wordCount() }}
7042
+ {{ currentTranslations().editor.word }}{{ wordCount() > 1 ? "s" : "" }}
7043
+ }
7044
+ </div>
7045
+ }
7046
+ </div>
7047
+ `, 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"] }]
7048
+ }], ctorParameters: () => [] });
7049
+
7050
+ /**
7051
+ * Provides the necessary configuration and initialization for the Angular TipTap Editor.
7052
+ * This should be called in your app.config.ts (for standalone) or main.ts.
7053
+ *
7054
+ * This provider is essential for 'Angular Nodes' to work correctly, as it captures the
7055
+ * root Injector required to instantiate custom Angular components within the editor.
7056
+ * @example
7057
+ * ```ts
7058
+ * bootstrapApplication(AppComponent, {
7059
+ * providers: [
7060
+ * provideAteEditor({
7061
+ * theme: 'dark',
7062
+ * mode: 'seamless'
7063
+ * })
7064
+ * ]
7065
+ * });
7066
+ * ```
7067
+ */
7068
+ function provideAteEditor(config) {
7069
+ return makeEnvironmentProviders([
7070
+ {
7071
+ provide: ATE_GLOBAL_CONFIG,
7072
+ useValue: config || {},
7073
+ },
7074
+ {
7075
+ provide: APP_INITIALIZER,
7076
+ useFactory: (injector) => () => {
7077
+ setGlobalInjector(injector);
6934
7078
  },
6935
- };
6936
- };
7079
+ deps: [Injector],
7080
+ multi: true,
7081
+ },
7082
+ ]);
6937
7083
  }
6938
7084
 
6939
- const RESERVED_NAMES = [
6940
- "doc",
6941
- "paragraph",
6942
- "text",
6943
- "hardBreak",
7085
+ /**
7086
+ * Clés des boutons de la barre d'outils native
7087
+ */
7088
+ const ATE_TOOLBAR_KEYS = [
7089
+ "bold",
7090
+ "italic",
7091
+ "underline",
7092
+ "strike",
7093
+ "code",
7094
+ "codeBlock",
7095
+ "superscript",
7096
+ "subscript",
7097
+ "highlight",
7098
+ "highlightPicker",
7099
+ "heading1",
7100
+ "heading2",
7101
+ "heading3",
6944
7102
  "bulletList",
6945
7103
  "orderedList",
6946
- "listItem",
6947
7104
  "blockquote",
6948
- "codeBlock",
6949
- "heading",
7105
+ "alignLeft",
7106
+ "alignCenter",
7107
+ "alignRight",
7108
+ "alignJustify",
7109
+ "link",
7110
+ "image",
6950
7111
  "horizontalRule",
7112
+ "table",
7113
+ "undo",
7114
+ "redo",
7115
+ "clear",
7116
+ "textColor",
7117
+ "separator",
6951
7118
  ];
7119
+
6952
7120
  /**
6953
- * Derives the TipTap node name and HTML tag from a component class.
7121
+ * Clés des options du menu bulle de texte
6954
7122
  */
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
- }
7123
+ const ATE_BUBBLE_MENU_KEYS = [
7124
+ "bold",
7125
+ "italic",
7126
+ "underline",
7127
+ "strike",
7128
+ "code",
7129
+ "superscript",
7130
+ "subscript",
7131
+ "highlight",
7132
+ "highlightPicker",
7133
+ "textColor",
7134
+ "link",
7135
+ "separator",
7136
+ ];
6972
7137
  /**
6973
- * Creates TipTap attributes from component inputs (Standard Mode).
7138
+ * Clés des options du menu bulle d'image
6974
7139
  */
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
- }
7140
+ const ATE_IMAGE_BUBBLE_MENU_KEYS = [
7141
+ "changeImage",
7142
+ "resizeSmall",
7143
+ "resizeMedium",
7144
+ "resizeLarge",
7145
+ "resizeOriginal",
7146
+ "deleteImage",
7147
+ "separator",
7148
+ ];
7004
7149
  /**
7005
- * Factory to transform an Angular component into a TipTap Node extension.
7006
- * Supports both "TipTap-Aware" and "Standard" modes.
7007
- *
7008
- * @internal
7150
+ * Clés des options du menu de table
7009
7151
  */
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
-
7152
+ const ATE_TABLE_BUBBLE_MENU_KEYS = [
7153
+ "addRowBefore",
7154
+ "addRowAfter",
7155
+ "deleteRow",
7156
+ "addColumnBefore",
7157
+ "addColumnAfter",
7158
+ "deleteColumn",
7159
+ "deleteTable",
7160
+ "toggleHeaderRow",
7161
+ "toggleHeaderColumn",
7162
+ "separator",
7163
+ ];
7061
7164
  /**
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
- * ```
7165
+ * Clés des options du menu de cellule
7086
7166
  */
7087
- function registerAngularComponent(injector, options) {
7088
- return createAngularComponentExtension(injector, options);
7089
- }
7167
+ const ATE_CELL_BUBBLE_MENU_KEYS = ["mergeCells", "splitCell"];
7090
7168
 
7091
7169
  /*
7092
7170
  * Public API Surface of tiptap-editor
7093
7171
  */
7094
- // Main component
7172
+ // Main component & Provider
7095
7173
  /** @deprecated Renamed to `ATE_INITIAL_EDITOR_STATE`. This alias will be removed in v3.0.0. */
7096
7174
  const INITIAL_EDITOR_STATE = ATE_INITIAL_EDITOR_STATE;
7097
7175
  /** @deprecated Renamed to `ATE_SLASH_COMMAND_KEYS`. This alias will be removed in v3.0.0. */
@@ -7125,5 +7203,5 @@ const DEFAULT_CELL_MENU_CONFIG = ATE_DEFAULT_CELL_MENU_CONFIG;
7125
7203
  * Generated bundle index. Do not edit.
7126
7204
  */
7127
7205
 
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 };
7206
+ 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_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, 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, provideAteEditor, registerAngularComponent };
7129
7207
  //# sourceMappingURL=flogeez-angular-tiptap-editor.mjs.map