@flogeez/angular-tiptap-editor 3.3.0 → 3.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 (35) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +17 -19
  3. package/esm2022/lib/components/bubble-menus/base/ate-base-bubble-menu.mjs +3 -3
  4. package/esm2022/lib/components/bubble-menus/base/ate-base-sub-bubble-menu.mjs +1 -1
  5. package/esm2022/lib/components/bubble-menus/color/ate-color-bubble-menu.component.mjs +2 -2
  6. package/esm2022/lib/components/bubble-menus/link/ate-link-bubble-menu.component.mjs +2 -2
  7. package/esm2022/lib/components/editor/angular-tiptap-editor.component.mjs +25 -7
  8. package/esm2022/lib/components/editor/ate-block-controls.component.mjs +4 -4
  9. package/esm2022/lib/components/slash-commands/ate-slash-commands.component.mjs +2 -2
  10. package/esm2022/lib/components/table-of-contents/ate-table-of-contents.component.mjs +363 -0
  11. package/esm2022/lib/components/table-of-contents/ate-toc-node.component.mjs +59 -0
  12. package/esm2022/lib/config/ate-slash-commands.config.mjs +10 -1
  13. package/esm2022/lib/extensions/ate-block-controls.extension.mjs +3 -3
  14. package/esm2022/lib/i18n/ateTranslationsModel.mjs +1 -1
  15. package/esm2022/lib/i18n/de_ateTranslations.mjs +7 -1
  16. package/esm2022/lib/i18n/en_ateTranslations.mjs +7 -1
  17. package/esm2022/lib/i18n/fr_ateTranslations.mjs +7 -1
  18. package/esm2022/lib/node-view/ate-angular-node-view.mjs +8 -2
  19. package/esm2022/lib/node-view/ate-node-view.renderer.mjs +11 -6
  20. package/esm2022/lib/services/ate-image.service.mjs +2 -2
  21. package/esm2022/public-api.mjs +3 -1
  22. package/fesm2022/flogeez-angular-tiptap-editor.mjs +6732 -6265
  23. package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
  24. package/lib/components/bubble-menus/base/ate-base-bubble-menu.d.ts +1 -1
  25. package/lib/components/bubble-menus/base/ate-base-sub-bubble-menu.d.ts +1 -1
  26. package/lib/components/table-of-contents/ate-table-of-contents.component.d.ts +48 -0
  27. package/lib/components/table-of-contents/ate-toc-node.component.d.ts +19 -0
  28. package/lib/config/ate-slash-commands.config.d.ts +1 -1
  29. package/lib/i18n/ateTranslationsModel.d.ts +6 -0
  30. package/lib/node-view/ate-angular-node-view.d.ts +4 -0
  31. package/lib/services/ate-i18n.service.d.ts +10 -0
  32. package/package.json +1 -1
  33. package/public-api.d.ts +2 -0
  34. package/src/lib/styles/ate-variables.global.css +173 -0
  35. package/src/lib/styles/index.css +1 -0
@@ -14,7 +14,7 @@ export declare abstract class AteBaseBubbleMenu implements AfterViewInit, OnDest
14
14
  editor: import("@angular/core").InputSignal<Editor>;
15
15
  menuRef: import("@angular/core").Signal<ElementRef<HTMLDivElement>>;
16
16
  protected tippyInstance: TippyInstance | null;
17
- protected updateTimeout: number | null;
17
+ protected updateTimeout: ReturnType<typeof setTimeout> | null;
18
18
  protected readonly isToolbarInteracting: import("@angular/core").Signal<boolean>;
19
19
  readonly state: import("@angular/core").Signal<import("@flogeez/angular-tiptap-editor").AteEditorStateSnapshot>;
20
20
  constructor();
@@ -14,7 +14,7 @@ export declare abstract class AteBaseSubBubbleMenu implements AfterViewInit, OnD
14
14
  editor: import("@angular/core").InputSignal<Editor>;
15
15
  menuRef: import("@angular/core").Signal<ElementRef<HTMLDivElement>>;
16
16
  protected tippyInstance: TippyInstance | null;
17
- protected updateTimeout: number | null;
17
+ protected updateTimeout: ReturnType<typeof setTimeout> | null;
18
18
  readonly state: import("@angular/core").Signal<import("@flogeez/angular-tiptap-editor").AteEditorStateSnapshot>;
19
19
  constructor();
20
20
  ngAfterViewInit(): void;
@@ -0,0 +1,48 @@
1
+ import { OnDestroy } from "@angular/core";
2
+ import { Editor } from "@tiptap/core";
3
+ import { AteEditorRef } from "../../models/ate-editor-ref";
4
+ import * as i0 from "@angular/core";
5
+ export interface AteTocItem {
6
+ text: string;
7
+ level: number;
8
+ pos: number;
9
+ id: string;
10
+ active: boolean;
11
+ }
12
+ export type AteTocVariant = "card" | "transparent" | "minimal";
13
+ /**
14
+ * Table of Contents Component (Notion-style)
15
+ * Dynamically extracts headings from the active editor and displays them.
16
+ * Configurable via inputs (floating, position, variants, hover expansion) and CSS variables.
17
+ */
18
+ export declare class AteTableOfContentsComponent implements OnDestroy {
19
+ editor: import("@angular/core").InputSignal<string | Editor | AteEditorRef | null | undefined>;
20
+ title: import("@angular/core").InputSignal<string | null>;
21
+ showTitle: import("@angular/core").InputSignal<boolean>;
22
+ floating: import("@angular/core").InputSignal<boolean>;
23
+ position: import("@angular/core").InputSignal<"left" | "right">;
24
+ variant: import("@angular/core").InputSignal<AteTocVariant>;
25
+ hoverExpand: import("@angular/core").InputSignal<boolean>;
26
+ private readonly registry;
27
+ private readonly i18n;
28
+ dashWidth(level: number): number;
29
+ readonly headerTitle: import("@angular/core").Signal<string>;
30
+ readonly resolvedEditor: import("@angular/core").Signal<Editor | null>;
31
+ readonly items: import("@angular/core").WritableSignal<AteTocItem[]>;
32
+ isMouseHovered: import("@angular/core").WritableSignal<boolean>;
33
+ isFocused: import("@angular/core").WritableSignal<boolean>;
34
+ readonly isExpanded: import("@angular/core").Signal<boolean>;
35
+ constructor();
36
+ ngOnDestroy(): void;
37
+ onScroll(): void;
38
+ setMouseHover(hovered: boolean): void;
39
+ setFocused(focused: boolean): void;
40
+ scrollToHeading(item: AteTocItem, event: MouseEvent): void;
41
+ private bindEditorEvents;
42
+ private unbindEditorEvents;
43
+ private readonly onEditorUpdate;
44
+ private updateHeadings;
45
+ private checkActiveHeading;
46
+ static ɵfac: i0.ɵɵFactoryDeclaration<AteTableOfContentsComponent, never>;
47
+ static ɵcmp: i0.ɵɵComponentDeclaration<AteTableOfContentsComponent, "ate-table-of-contents", never, { "editor": { "alias": "editor"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "showTitle": { "alias": "showTitle"; "required": false; "isSignal": true; }; "floating": { "alias": "floating"; "required": false; "isSignal": true; }; "position": { "alias": "position"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "hoverExpand": { "alias": "hoverExpand"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
48
+ }
@@ -0,0 +1,19 @@
1
+ import { Injector } from "@angular/core";
2
+ import { AteAngularNodeView } from "../../node-view/ate-angular-node-view";
3
+ import { RegisterAngularComponentOptions } from "../../node-view/ate-node-view.models";
4
+ import * as i0 from "@angular/core";
5
+ /**
6
+ * Custom Angular NodeView wrapper for displaying Table of Contents directly inside the editor content.
7
+ */
8
+ export declare class AteTocNodeComponent extends AteAngularNodeView {
9
+ static ɵfac: i0.ɵɵFactoryDeclaration<AteTocNodeComponent, never>;
10
+ static ɵcmp: i0.ɵɵComponentDeclaration<AteTocNodeComponent, "ate-toc-node", never, {}, {}, never, never, true, never>;
11
+ }
12
+ /**
13
+ * Registration options for the Table of Contents Angular NodeView
14
+ */
15
+ export declare const AteTocNodeOptions: RegisterAngularComponentOptions<AteTocNodeComponent>;
16
+ /**
17
+ * Creates the Table of Contents TipTap Node Extension instance.
18
+ */
19
+ export declare function getAteTocNodeExtension(injector?: Injector): import("@tiptap/core").Node<any, any>;
@@ -4,7 +4,7 @@ import { AteEditorCommandsService } from "../services/ate-editor-commands.servic
4
4
  /**
5
5
  * Clés des commandes natives dans l'ordre d'affichage
6
6
  */
7
- export declare const ATE_SLASH_COMMAND_KEYS: readonly ["heading1", "heading2", "heading3", "bulletList", "orderedList", "blockquote", "code", "image", "horizontalRule", "table"];
7
+ export declare const ATE_SLASH_COMMAND_KEYS: readonly ["heading1", "heading2", "heading3", "bulletList", "orderedList", "blockquote", "code", "image", "horizontalRule", "table", "tableOfContents"];
8
8
  export type AteSlashCommandKey = (typeof ATE_SLASH_COMMAND_KEYS)[number];
9
9
  /**
10
10
  * Configuration simplifiée pour activer/désactiver les slash commands natives.
@@ -104,6 +104,11 @@ export interface AteTranslations {
104
104
  description: string;
105
105
  keywords: string[];
106
106
  };
107
+ tableOfContents: {
108
+ title: string;
109
+ description: string;
110
+ keywords: string[];
111
+ };
107
112
  };
108
113
  table: {
109
114
  addRowBefore: string;
@@ -161,6 +166,7 @@ export interface AteTranslations {
161
166
  viewMode: string;
162
167
  blockAdd: string;
163
168
  blockDrag: string;
169
+ tableOfContents: string;
164
170
  };
165
171
  common: {
166
172
  cancel: string;
@@ -49,6 +49,10 @@ export declare abstract class AteAngularNodeView {
49
49
  * The ProseMirror node
50
50
  */
51
51
  node: Signal<ProseMirrorNode>;
52
+ /**
53
+ * Helper signal to directly access node attributes
54
+ */
55
+ attributes: Signal<Record<string, unknown>>;
52
56
  /**
53
57
  * Decorations applied to this node
54
58
  */
@@ -113,6 +113,11 @@ export declare class AteI18nService {
113
113
  description: string;
114
114
  keywords: string[];
115
115
  };
116
+ tableOfContents: {
117
+ title: string;
118
+ description: string;
119
+ keywords: string[];
120
+ };
116
121
  }>;
117
122
  readonly table: import("@angular/core").Signal<{
118
123
  addRowBefore: string;
@@ -170,6 +175,7 @@ export declare class AteI18nService {
170
175
  viewMode: string;
171
176
  blockAdd: string;
172
177
  blockDrag: string;
178
+ tableOfContents: string;
173
179
  }>;
174
180
  readonly common: import("@angular/core").Signal<{
175
181
  cancel: string;
@@ -243,6 +249,10 @@ export declare class AteI18nService {
243
249
  title: string;
244
250
  description: string;
245
251
  keywords: string[];
252
+ } | {
253
+ title: string;
254
+ description: string;
255
+ keywords: string[];
246
256
  };
247
257
  static ɵfac: i0.ɵɵFactoryDeclaration<AteI18nService, never>;
248
258
  static ɵprov: i0.ɵɵInjectableDeclaration<AteI18nService>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flogeez/angular-tiptap-editor",
3
- "version": "3.3.0",
3
+ "version": "3.4.1",
4
4
  "description": "A modern, customizable rich-text editor for Angular (18+), built with Tiptap and featuring complete internationalization support",
5
5
  "keywords": [
6
6
  "angular",
package/public-api.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export * from "./lib/components/editor/angular-tiptap-editor.component";
2
+ export { AteTableOfContentsComponent, type AteTocItem, type AteTocVariant } from "./lib/components/table-of-contents/ate-table-of-contents.component";
3
+ export { AteTocNodeComponent, AteTocNodeOptions, getAteTocNodeExtension } from "./lib/components/table-of-contents/ate-toc-node.component";
2
4
  export * from "./lib/ate-editor.provider";
3
5
  export * from "./lib/directives/ate-noop-value-accessor.directive";
4
6
  export * from "./lib/directives/ate-tooltip.directive";
@@ -0,0 +1,173 @@
1
+ /* ==========================================================================
2
+ Full Design Tokens & CSS Custom Properties for angular-tiptap-editor
3
+ ========================================================================== */
4
+ :root {
5
+ /* ===== BASE TOKENS ===== */
6
+ --ate-primary: #2563eb;
7
+ --ate-primary-hover: #153ca9;
8
+ --ate-primary-contrast: #ffffff;
9
+ --ate-primary-light: color-mix(in srgb, var(--ate-primary), transparent 90%);
10
+ --ate-primary-lighter: color-mix(in srgb, var(--ate-primary), transparent 95%);
11
+ --ate-primary-light-alpha: color-mix(in srgb, var(--ate-primary), transparent 85%);
12
+
13
+ --ate-surface: #ffffff;
14
+ --ate-surface-secondary: #f8f9fa;
15
+ --ate-surface-tertiary: #f1f5f9;
16
+ --ate-surface-hover: rgba(37, 99, 235, 0.05);
17
+
18
+ --ate-text: #2d3748;
19
+ --ate-text-primary: #1e293b;
20
+ --ate-text-secondary: #64748b;
21
+ --ate-text-muted: #a0aec0;
22
+
23
+ --ate-border: #e2e8f0;
24
+
25
+ --ate-highlight-bg: #fef08a;
26
+ --ate-highlight-color: #854d0e;
27
+
28
+ --ate-button-hover: #f1f5f9;
29
+ --ate-button-active: #e2e8f0;
30
+
31
+ --ate-selection-bg: var(--ate-primary-light-alpha);
32
+
33
+ --ate-error-color: #c53030;
34
+ --ate-error-bg: #fed7d7;
35
+ --ate-error-border: #feb2b2;
36
+
37
+ /* ===== COMPONENT TOKENS ===== */
38
+ --ate-border-color: var(--ate-border);
39
+ --ate-border-width: 2px;
40
+ --ate-border-radius: 12px;
41
+ --ate-sub-border-radius: 8px;
42
+ --ate-focus-color: var(--ate-primary);
43
+ --ate-background: var(--ate-surface);
44
+
45
+ /* Content */
46
+ --ate-text-color: var(--ate-text);
47
+ --ate-placeholder-color: var(--ate-text-muted);
48
+ --ate-line-height: 1.6;
49
+ --ate-content-padding-block: 16px;
50
+ --ate-content-padding-inline: 16px;
51
+ --ate-content-gutter: 0px;
52
+
53
+ /* Menus (Slash/Bubble/TOC) */
54
+ --ate-menu-bg: var(--ate-surface);
55
+ --ate-menu-border-radius: var(--ate-border-radius);
56
+ --ate-menu-border: var(--ate-border);
57
+ --ate-menu-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
58
+ --ate-menu-padding: 4px;
59
+ --ate-menu-gap: 2px;
60
+
61
+ /* Toolbar */
62
+ --ate-toolbar-padding: var(--ate-menu-padding);
63
+ --ate-toolbar-gap: var(--ate-menu-gap);
64
+ --ate-toolbar-background: var(--ate-surface-secondary);
65
+ --ate-toolbar-border-color: var(--ate-border);
66
+ --ate-toolbar-button-color: var(--ate-text-secondary);
67
+ --ate-toolbar-button-hover-background: transparent;
68
+ --ate-toolbar-button-active-background: var(--ate-primary-light);
69
+ --ate-toolbar-button-active-color: var(--ate-primary);
70
+
71
+ /* Counter & Footer */
72
+ --ate-counter-color: var(--ate-text-secondary);
73
+ --ate-counter-background: var(--ate-surface-secondary);
74
+ --ate-counter-border-color: var(--ate-border);
75
+
76
+ /* Table of Contents (TOC) */
77
+ --ate-toc-width: 240px;
78
+ --ate-toc-gap: 2px;
79
+ --ate-toc-item-height: 16px;
80
+ --ate-toc-item-hover-height: 24px;
81
+ --ate-toc-border-radius: var(--ate-border-radius);
82
+ --ate-toc-padding: var(--ate-menu-padding);
83
+ --ate-toc-hitbox-padding: 16px;
84
+ --ate-toc-hitbox-padding-vertical: 8px;
85
+
86
+ /* Drag & Drop */
87
+ --ate-drag-background: #f0f8ff;
88
+ --ate-drag-border-color: var(--ate-primary);
89
+
90
+ /* Blockquote */
91
+ --ate-blockquote-border-color: var(--ate-border);
92
+ --ate-blockquote-background: var(--ate-surface-secondary);
93
+
94
+ /* Code */
95
+ --ate-code-background: var(--ate-surface-secondary);
96
+ --ate-code-color: var(--ate-text);
97
+ --ate-code-border-color: var(--ate-border);
98
+
99
+ --ate-code-block-background: #0f172a;
100
+ --ate-code-block-color: #e2e8f0;
101
+ --ate-code-block-border-color: var(--ate-border);
102
+
103
+ /* Images */
104
+ --ate-image-border-radius: 16px;
105
+ --ate-image-selected-color: var(--ate-primary);
106
+
107
+ /* Scrollbars */
108
+ --ate-scrollbar-width: 10px;
109
+ --ate-scrollbar-thumb: var(--ate-border);
110
+ --ate-scrollbar-thumb-hover: var(--ate-text-muted);
111
+ --ate-scrollbar-track: transparent;
112
+
113
+ /* Tables */
114
+ --ate-table-border-color: var(--ate-border);
115
+ --ate-table-header-background: var(--ate-surface-secondary);
116
+ --ate-table-header-color: var(--ate-text);
117
+ --ate-table-cell-background: var(--ate-surface);
118
+ --ate-table-cell-selected-background: var(--ate-primary-light);
119
+ --ate-table-resize-handle-color: var(--ate-primary);
120
+ --ate-table-row-hover-background: var(--ate-primary-lighter);
121
+
122
+ /* Floating UI & Tooltips */
123
+ --ate-tooltip-bg: var(--ate-code-block-background, #0f172a);
124
+ --ate-tooltip-color: var(--ate-code-block-color, #e2e8f0);
125
+ }
126
+
127
+ /* Dark mode global theme support */
128
+ .dark,
129
+ :root.dark,
130
+ body.dark,
131
+ :root[data-theme="dark"],
132
+ [data-theme="dark"] {
133
+ --ate-primary: #3b82f6;
134
+ --ate-primary-contrast: #ffffff;
135
+ --ate-primary-light: color-mix(in srgb, var(--ate-primary), transparent 85%);
136
+ --ate-primary-lighter: color-mix(in srgb, var(--ate-primary), transparent 92%);
137
+ --ate-primary-light-alpha: color-mix(in srgb, var(--ate-primary), transparent 80%);
138
+
139
+ --ate-surface: #020617;
140
+ --ate-surface-secondary: #0f172a;
141
+ --ate-surface-tertiary: #1e293b;
142
+ --ate-surface-hover: rgba(59, 130, 246, 0.1);
143
+
144
+ --ate-text: #f8fafc;
145
+ --ate-text-primary: #f8fafc;
146
+ --ate-text-secondary: #94a3b8;
147
+ --ate-text-muted: #64748b;
148
+
149
+ --ate-border: #1e293b;
150
+
151
+ --ate-highlight-bg: #854d0e;
152
+ --ate-highlight-color: #fef08a;
153
+
154
+ --ate-button-hover: #1e293b;
155
+ --ate-button-active: #0f172a;
156
+
157
+ --ate-menu-border: rgba(255, 255, 255, 0.1);
158
+ --ate-menu-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.3), 0 10px 10px -5px rgba(0, 0, 0, 0.2);
159
+
160
+ --ate-error-color: #f87171;
161
+ --ate-error-bg: #450a0a;
162
+ --ate-error-border: #7f1d1d;
163
+
164
+ --ate-drag-background: var(--ate-surface-tertiary);
165
+ --ate-drag-border-color: var(--ate-primary);
166
+ --ate-blockquote-border-color: var(--ate-primary);
167
+ --ate-toolbar-button-active-background: var(--ate-primary-light);
168
+ --ate-toolbar-button-active-color: var(--ate-primary);
169
+ --ate-button-hover: var(--ate-surface-tertiary);
170
+ --ate-button-active: var(--ate-surface-secondary);
171
+ --ate-scrollbar-thumb: var(--ate-surface-tertiary);
172
+ --ate-scrollbar-thumb-hover: var(--ate-text-muted);
173
+ }
@@ -1,3 +1,4 @@
1
+ @import "./ate-variables.global.css";
1
2
  @import "./ate-bubble-menu.global.css";
2
3
  @import "./ate-tooltip.global.css";
3
4
  @import "./material-symbols.css";