@flogeez/angular-tiptap-editor 3.1.2 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +2 -2
- package/esm2022/flogeez-angular-tiptap-editor.mjs +5 -0
- package/esm2022/lib/ate-editor.provider.mjs +38 -0
- package/esm2022/lib/components/bubble-menus/base/ate-base-bubble-menu.mjs +207 -0
- package/esm2022/lib/components/bubble-menus/base/ate-base-sub-bubble-menu.mjs +137 -0
- package/esm2022/lib/components/bubble-menus/color/ate-color-bubble-menu.component.mjs +365 -0
- package/esm2022/lib/components/bubble-menus/image/ate-image-bubble-menu.component.mjs +309 -0
- package/esm2022/lib/components/bubble-menus/link/ate-link-bubble-menu.component.mjs +247 -0
- package/esm2022/lib/components/bubble-menus/table/ate-cell-bubble-menu.component.mjs +126 -0
- package/esm2022/lib/components/bubble-menus/table/ate-table-bubble-menu.component.mjs +271 -0
- package/esm2022/lib/components/bubble-menus/text/ate-bubble-menu.component.mjs +272 -0
- package/esm2022/lib/components/color-picker/ate-color-picker.component.mjs +123 -0
- package/esm2022/lib/components/edit-toggle/ate-edit-toggle.component.mjs +42 -0
- package/esm2022/lib/components/editor/angular-tiptap-editor.component.mjs +1031 -0
- package/esm2022/lib/components/editor/ate-block-controls.component.mjs +256 -0
- package/esm2022/lib/components/slash-commands/ate-slash-commands.component.mjs +328 -0
- package/esm2022/lib/components/toolbar/ate-toolbar.component.mjs +531 -0
- package/esm2022/lib/components/ui/ate-button.component.mjs +91 -0
- package/esm2022/lib/components/ui/ate-separator.component.mjs +11 -0
- package/esm2022/lib/config/ate-editor.config.mjs +133 -0
- package/esm2022/lib/config/ate-global-config.token.mjs +6 -0
- package/esm2022/lib/config/ate-slash-commands.config.mjs +130 -0
- package/esm2022/lib/directives/ate-noop-value-accessor.directive.mjs +40 -0
- package/esm2022/lib/directives/ate-tooltip.directive.mjs +138 -0
- package/esm2022/lib/extensions/ate-block-controls.extension.mjs +156 -0
- package/esm2022/lib/extensions/ate-link-click-behavior.extension.mjs +32 -0
- package/esm2022/lib/extensions/ate-resizable-image.extension.mjs +277 -0
- package/esm2022/lib/extensions/ate-table.extension.mjs +27 -0
- package/esm2022/lib/extensions/ate-tiptap-state.extension.mjs +85 -0
- package/esm2022/lib/extensions/ate-upload-progress.extension.mjs +195 -0
- package/esm2022/lib/extensions/calculators/ate-discovery.calculator.mjs +62 -0
- package/esm2022/lib/extensions/calculators/ate-image.calculator.mjs +8 -0
- package/esm2022/lib/extensions/calculators/ate-marks.calculator.mjs +75 -0
- package/esm2022/lib/extensions/calculators/ate-selection.calculator.mjs +35 -0
- package/esm2022/lib/extensions/calculators/ate-structure.calculator.mjs +34 -0
- package/esm2022/lib/extensions/calculators/ate-table.calculator.mjs +38 -0
- package/esm2022/lib/models/ate-bubble-menu.model.mjs +53 -0
- package/esm2022/lib/models/ate-editor-config.model.mjs +2 -0
- package/esm2022/lib/models/ate-editor-state.model.mjs +90 -0
- package/esm2022/lib/models/ate-image.model.mjs +2 -0
- package/esm2022/lib/models/ate-slash-command.model.mjs +2 -0
- package/esm2022/lib/models/ate-toolbar.model.mjs +35 -0
- package/esm2022/lib/node-view/ate-angular-node-view.mjs +97 -0
- package/esm2022/lib/node-view/ate-injector.registry.mjs +16 -0
- package/esm2022/lib/node-view/ate-node-view.factory.mjs +125 -0
- package/esm2022/lib/node-view/ate-node-view.models.mjs +2 -0
- package/esm2022/lib/node-view/ate-node-view.renderer.mjs +154 -0
- package/esm2022/lib/node-view/ate-register-angular-component.mjs +49 -0
- package/esm2022/lib/services/ate-color-picker.service.mjs +194 -0
- package/esm2022/lib/services/ate-editor-commands.service.mjs +474 -0
- package/esm2022/lib/services/ate-i18n.service.mjs +422 -0
- package/esm2022/lib/services/ate-image.service.mjs +459 -0
- package/esm2022/lib/services/ate-link.service.mjs +99 -0
- package/esm2022/lib/utils/ate-color.utils.mjs +60 -0
- package/esm2022/public-api.mjs +40 -0
- package/fesm2022/flogeez-angular-tiptap-editor.mjs +321 -354
- package/fesm2022/flogeez-angular-tiptap-editor.mjs.map +1 -1
- package/index.d.ts +3 -1734
- package/lib/ate-editor.provider.d.ts +21 -0
- package/lib/components/bubble-menus/base/ate-base-bubble-menu.d.ts +71 -0
- package/lib/components/bubble-menus/base/ate-base-sub-bubble-menu.d.ts +60 -0
- package/lib/components/bubble-menus/color/ate-color-bubble-menu.component.d.ts +77 -0
- package/lib/components/bubble-menus/image/ate-image-bubble-menu.component.d.ts +49 -0
- package/lib/components/bubble-menus/link/ate-link-bubble-menu.component.d.ts +55 -0
- package/lib/components/bubble-menus/table/ate-cell-bubble-menu.component.d.ts +16 -0
- package/lib/components/bubble-menus/table/ate-table-bubble-menu.component.d.ts +25 -0
- package/lib/components/bubble-menus/text/ate-bubble-menu.component.d.ts +53 -0
- package/lib/components/color-picker/ate-color-picker.component.d.ts +54 -0
- package/lib/components/edit-toggle/ate-edit-toggle.component.d.ts +13 -0
- package/lib/components/editor/angular-tiptap-editor.component.d.ts +242 -0
- package/lib/components/editor/ate-block-controls.component.d.ts +44 -0
- package/lib/components/slash-commands/ate-slash-commands.component.d.ts +34 -0
- package/lib/components/toolbar/ate-toolbar.component.d.ts +47 -0
- package/lib/components/ui/ate-button.component.d.ts +25 -0
- package/lib/components/ui/ate-separator.component.d.ts +5 -0
- package/lib/config/ate-editor.config.d.ts +19 -0
- package/lib/config/ate-global-config.token.d.ts +6 -0
- package/lib/config/ate-slash-commands.config.d.ts +41 -0
- package/lib/directives/ate-noop-value-accessor.directive.d.ts +13 -0
- package/lib/directives/ate-tooltip.directive.d.ts +30 -0
- package/lib/extensions/ate-block-controls.extension.d.ts +10 -0
- package/lib/extensions/ate-link-click-behavior.extension.d.ts +2 -0
- package/lib/extensions/ate-resizable-image.extension.d.ts +27 -0
- package/lib/extensions/ate-table.extension.d.ts +2 -0
- package/lib/extensions/ate-tiptap-state.extension.d.ts +7 -0
- package/lib/extensions/ate-upload-progress.extension.d.ts +7 -0
- package/lib/extensions/calculators/ate-discovery.calculator.d.ts +7 -0
- package/lib/extensions/calculators/ate-image.calculator.d.ts +2 -0
- package/lib/extensions/calculators/ate-marks.calculator.d.ts +2 -0
- package/lib/extensions/calculators/ate-selection.calculator.d.ts +2 -0
- package/lib/extensions/calculators/ate-structure.calculator.d.ts +2 -0
- package/lib/extensions/calculators/ate-table.calculator.d.ts +2 -0
- package/lib/models/ate-bubble-menu.model.d.ts +33 -0
- package/lib/models/ate-editor-config.model.d.ts +113 -0
- package/lib/models/ate-editor-state.model.d.ts +109 -0
- package/lib/models/ate-image.model.d.ts +104 -0
- package/lib/models/ate-slash-command.model.d.ts +17 -0
- package/lib/models/ate-toolbar.model.d.ts +18 -0
- package/lib/node-view/ate-angular-node-view.d.ts +115 -0
- package/lib/node-view/ate-injector.registry.d.ts +3 -0
- package/lib/node-view/ate-node-view.factory.d.ts +10 -0
- package/lib/node-view/ate-node-view.models.d.ts +138 -0
- package/lib/node-view/ate-node-view.renderer.d.ts +23 -0
- package/lib/node-view/ate-register-angular-component.d.ts +35 -0
- package/lib/services/ate-color-picker.service.d.ts +65 -0
- package/lib/services/ate-editor-commands.service.d.ts +75 -0
- package/lib/services/ate-i18n.service.d.ts +406 -0
- package/lib/services/ate-image.service.d.ts +82 -0
- package/lib/services/ate-link.service.d.ts +42 -0
- package/lib/utils/ate-color.utils.d.ts +12 -0
- package/package.json +3 -1
- package/public-api.d.ts +31 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/core";
|
|
2
|
+
/**
|
|
3
|
+
* Clés des options du menu bulle de texte
|
|
4
|
+
*/
|
|
5
|
+
export declare const ATE_BUBBLE_MENU_KEYS: readonly ["bold", "italic", "underline", "strike", "code", "superscript", "subscript", "highlight", "highlightPicker", "textColor", "link", "separator"];
|
|
6
|
+
export type AteBubbleMenuKey = (typeof ATE_BUBBLE_MENU_KEYS)[number];
|
|
7
|
+
export interface AteBubbleMenuConfig extends Partial<Record<AteBubbleMenuKey, boolean>> {
|
|
8
|
+
custom?: AteCustomBubbleMenuItem[];
|
|
9
|
+
}
|
|
10
|
+
export interface AteCustomBubbleMenuItem {
|
|
11
|
+
key: string;
|
|
12
|
+
label: string;
|
|
13
|
+
icon: string;
|
|
14
|
+
command: (editor: Editor) => void | Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Clés des options du menu bulle d'image
|
|
18
|
+
*/
|
|
19
|
+
export declare const ATE_IMAGE_BUBBLE_MENU_KEYS: readonly ["changeImage", "downloadImage", "resizeSmall", "resizeMedium", "resizeLarge", "resizeOriginal", "alignLeft", "alignCenter", "alignRight", "deleteImage", "separator"];
|
|
20
|
+
export type AteImageBubbleMenuKey = (typeof ATE_IMAGE_BUBBLE_MENU_KEYS)[number];
|
|
21
|
+
export type AteImageBubbleMenuConfig = Partial<Record<AteImageBubbleMenuKey, boolean>>;
|
|
22
|
+
/**
|
|
23
|
+
* Clés des options du menu de table
|
|
24
|
+
*/
|
|
25
|
+
export declare const ATE_TABLE_BUBBLE_MENU_KEYS: readonly ["addRowBefore", "addRowAfter", "deleteRow", "addColumnBefore", "addColumnAfter", "deleteColumn", "deleteTable", "toggleHeaderRow", "toggleHeaderColumn", "separator"];
|
|
26
|
+
export type AteTableBubbleMenuKey = (typeof ATE_TABLE_BUBBLE_MENU_KEYS)[number];
|
|
27
|
+
export type AteTableBubbleMenuConfig = Partial<Record<AteTableBubbleMenuKey, boolean>>;
|
|
28
|
+
/**
|
|
29
|
+
* Clés des options du menu de cellule
|
|
30
|
+
*/
|
|
31
|
+
export declare const ATE_CELL_BUBBLE_MENU_KEYS: readonly ["mergeCells", "splitCell"];
|
|
32
|
+
export type AteCellBubbleMenuKey = (typeof ATE_CELL_BUBBLE_MENU_KEYS)[number];
|
|
33
|
+
export type AteCellBubbleMenuConfig = Partial<Record<AteCellBubbleMenuKey, boolean>>;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Type } from "@angular/core";
|
|
2
|
+
import { AteToolbarConfig } from "./ate-toolbar.model";
|
|
3
|
+
import { RegisterAngularComponentOptions } from "../node-view/ate-node-view.models";
|
|
4
|
+
import { AteBubbleMenuConfig, AteImageBubbleMenuConfig, AteTableBubbleMenuConfig, AteCellBubbleMenuConfig } from "./ate-bubble-menu.model";
|
|
5
|
+
import { AteSlashCommandsConfig } from "../config/ate-slash-commands.config";
|
|
6
|
+
import { AteImageUploadConfig } from "./ate-image.model";
|
|
7
|
+
import { Extension, Node, Mark, EditorOptions } from "@tiptap/core";
|
|
8
|
+
import { AteStateCalculator } from "./ate-editor-state.model";
|
|
9
|
+
import { AteCustomSlashCommands } from "./ate-slash-command.model";
|
|
10
|
+
/**
|
|
11
|
+
* Type representing an Angular component that can be registered as an editor node.
|
|
12
|
+
* Can be a direct Component class or a full registration options object.
|
|
13
|
+
*/
|
|
14
|
+
export type AteAngularNode = Type<unknown> | RegisterAngularComponentOptions<unknown>;
|
|
15
|
+
/** Possible display modes for block level controls */
|
|
16
|
+
export type AteBlockControlsMode = "inside" | "outside" | "none";
|
|
17
|
+
/** Possible values for editor autofocus */
|
|
18
|
+
export type AteAutofocusMode = "start" | "end" | "all" | boolean | number;
|
|
19
|
+
/**
|
|
20
|
+
* Global configuration interface for Angular Tiptap Editor.
|
|
21
|
+
* Uses a flat structure for common settings and objects for complex configurations.
|
|
22
|
+
*/
|
|
23
|
+
export interface AteEditorConfig {
|
|
24
|
+
/** Editor theme: light, dark, or system auto-detection */
|
|
25
|
+
theme?: "light" | "dark" | "auto";
|
|
26
|
+
/** Display mode: classic or seamless (no borders/background) */
|
|
27
|
+
mode?: "classic" | "seamless";
|
|
28
|
+
/** Editor height (e.g., '300px', 300, 'auto') */
|
|
29
|
+
height?: string | number;
|
|
30
|
+
/** Focus position on initialization */
|
|
31
|
+
autofocus?: AteAutofocusMode;
|
|
32
|
+
/** Placeholder text displayed when the editor is empty */
|
|
33
|
+
placeholder?: string;
|
|
34
|
+
/** Initial editing state (if false, the editor is read-only) */
|
|
35
|
+
editable?: boolean;
|
|
36
|
+
/** Minimum editor height (e.g., '200px', 200) */
|
|
37
|
+
minHeight?: string | number;
|
|
38
|
+
/** Maximum editor height (e.g., '500px', 500) */
|
|
39
|
+
maxHeight?: string | number;
|
|
40
|
+
/** If true, the editor takes 100% of the parent container's height */
|
|
41
|
+
fillContainer?: boolean;
|
|
42
|
+
/** Disabled state (often used with forms) */
|
|
43
|
+
disabled?: boolean;
|
|
44
|
+
/** Editor locale (overrides the global i18n service) */
|
|
45
|
+
locale?: string;
|
|
46
|
+
/** Enable browser spellcheck */
|
|
47
|
+
spellcheck?: boolean;
|
|
48
|
+
/** Enable smart cleanup when pasting from Office/Word */
|
|
49
|
+
enableOfficePaste?: boolean;
|
|
50
|
+
/** Show or hide the toolbar */
|
|
51
|
+
showToolbar?: boolean;
|
|
52
|
+
/** Show or hide the footer (counters area) */
|
|
53
|
+
showFooter?: boolean;
|
|
54
|
+
/** Show or hide the character count */
|
|
55
|
+
showCharacterCount?: boolean;
|
|
56
|
+
/** Show or hide the word count */
|
|
57
|
+
showWordCount?: boolean;
|
|
58
|
+
/** Show or hide the read-only/edit toggle button */
|
|
59
|
+
showEditToggle?: boolean;
|
|
60
|
+
/** Show or hide the text context menu */
|
|
61
|
+
showBubbleMenu?: boolean;
|
|
62
|
+
/** Show or hide the image context menu */
|
|
63
|
+
showImageBubbleMenu?: boolean;
|
|
64
|
+
/** Show or hide the table menu */
|
|
65
|
+
showTableMenu?: boolean;
|
|
66
|
+
/** Show or hide the cell menu */
|
|
67
|
+
showCellMenu?: boolean;
|
|
68
|
+
/** Whether to allow image downloading from bubble menu */
|
|
69
|
+
downloadImage?: boolean;
|
|
70
|
+
/** Enable or disable slash commands (/) */
|
|
71
|
+
enableSlashCommands?: boolean;
|
|
72
|
+
/** Maximum number of characters allowed */
|
|
73
|
+
maxCharacters?: number;
|
|
74
|
+
/**
|
|
75
|
+
* Block level controls (plus button and drag handle) display mode.
|
|
76
|
+
* - 'inside': Elements are placed inside the editor (reserves space via padding).
|
|
77
|
+
* - 'outside': Elements float outside the editor boundary (no layout shift).
|
|
78
|
+
* - 'none': Disabled (not displayed).
|
|
79
|
+
*/
|
|
80
|
+
blockControls?: AteBlockControlsMode;
|
|
81
|
+
/** Detailed toolbar configuration (items, groups) */
|
|
82
|
+
toolbar?: AteToolbarConfig;
|
|
83
|
+
/** Text context menu configuration */
|
|
84
|
+
bubbleMenu?: AteBubbleMenuConfig;
|
|
85
|
+
/** Image context menu configuration */
|
|
86
|
+
imageBubbleMenu?: AteImageBubbleMenuConfig;
|
|
87
|
+
/** Table context menu configuration */
|
|
88
|
+
tableBubbleMenu?: AteTableBubbleMenuConfig;
|
|
89
|
+
/** Cell context menu configuration */
|
|
90
|
+
cellBubbleMenu?: AteCellBubbleMenuConfig;
|
|
91
|
+
/** Slash commands configuration (/) */
|
|
92
|
+
slashCommands?: AteSlashCommandsConfig;
|
|
93
|
+
/** If true, shows the floating toolbar on focus */
|
|
94
|
+
floatingToolbar?: boolean;
|
|
95
|
+
/** Technical configuration for image uploads */
|
|
96
|
+
imageUpload?: AteImageUploadConfig;
|
|
97
|
+
/**
|
|
98
|
+
* List of Angular components to automatically register as interactive editor nodes.
|
|
99
|
+
* This is the preferred way to extend the editor with custom Angular logic.
|
|
100
|
+
*/
|
|
101
|
+
angularNodes?: AteAngularNode[];
|
|
102
|
+
/** Standard TipTap extensions (Nodes, Marks, or Plugins) */
|
|
103
|
+
tiptapExtensions?: (Extension | Node | Mark)[];
|
|
104
|
+
/** Raw TipTap editor options (e.g., enableInputRules, injectCSS, etc.) */
|
|
105
|
+
tiptapOptions?: Partial<EditorOptions>;
|
|
106
|
+
/** Reactive state calculators to extend the editor's live state */
|
|
107
|
+
stateCalculators?: AteStateCalculator[];
|
|
108
|
+
/**
|
|
109
|
+
* Fully custom slash commands configuration.
|
|
110
|
+
* When provided, it replaces the default groups based on toolbar toggles.
|
|
111
|
+
*/
|
|
112
|
+
customSlashCommands?: AteCustomSlashCommands;
|
|
113
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/core";
|
|
2
|
+
export type AteStateCalculator = (editor: Editor) => Partial<{
|
|
3
|
+
[K in keyof AteEditorStateSnapshot]: AteEditorStateSnapshot[K] extends object ? Partial<AteEditorStateSnapshot[K]> : AteEditorStateSnapshot[K];
|
|
4
|
+
}>;
|
|
5
|
+
export interface AteEditorStateSnapshot {
|
|
6
|
+
/** Global editor states */
|
|
7
|
+
isFocused: boolean;
|
|
8
|
+
isEditable: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Detailed selection information to avoid overlap between menus
|
|
11
|
+
*/
|
|
12
|
+
selection: {
|
|
13
|
+
type: "text" | "node" | "cell" | "none";
|
|
14
|
+
from: number;
|
|
15
|
+
to: number;
|
|
16
|
+
empty: boolean;
|
|
17
|
+
/** Specific for CellSelection */
|
|
18
|
+
isSingleCell: boolean;
|
|
19
|
+
};
|
|
20
|
+
/** Text formatting states (Marks) */
|
|
21
|
+
marks: {
|
|
22
|
+
bold: boolean;
|
|
23
|
+
italic: boolean;
|
|
24
|
+
underline: boolean;
|
|
25
|
+
strike: boolean;
|
|
26
|
+
code: boolean;
|
|
27
|
+
superscript: boolean;
|
|
28
|
+
subscript: boolean;
|
|
29
|
+
highlight: boolean;
|
|
30
|
+
link: boolean;
|
|
31
|
+
linkHref: string | null;
|
|
32
|
+
color: string | null;
|
|
33
|
+
computedColor: string | null;
|
|
34
|
+
background: string | null;
|
|
35
|
+
computedBackground: string | null;
|
|
36
|
+
linkOpenOnClick: boolean;
|
|
37
|
+
};
|
|
38
|
+
/** Capability states (canExecute) */
|
|
39
|
+
can: {
|
|
40
|
+
toggleBold: boolean;
|
|
41
|
+
toggleItalic: boolean;
|
|
42
|
+
toggleUnderline: boolean;
|
|
43
|
+
toggleStrike: boolean;
|
|
44
|
+
toggleCode: boolean;
|
|
45
|
+
toggleHighlight: boolean;
|
|
46
|
+
toggleLink: boolean;
|
|
47
|
+
toggleSuperscript: boolean;
|
|
48
|
+
toggleSubscript: boolean;
|
|
49
|
+
setColor: boolean;
|
|
50
|
+
setHighlight: boolean;
|
|
51
|
+
undo: boolean;
|
|
52
|
+
redo: boolean;
|
|
53
|
+
/** Table specific capabilities */
|
|
54
|
+
addRowBefore: boolean;
|
|
55
|
+
addRowAfter: boolean;
|
|
56
|
+
deleteRow: boolean;
|
|
57
|
+
addColumnBefore: boolean;
|
|
58
|
+
addColumnAfter: boolean;
|
|
59
|
+
deleteColumn: boolean;
|
|
60
|
+
deleteTable: boolean;
|
|
61
|
+
mergeCells: boolean;
|
|
62
|
+
splitCell: boolean;
|
|
63
|
+
toggleHeaderRow: boolean;
|
|
64
|
+
toggleHeaderColumn: boolean;
|
|
65
|
+
/** Structure/Node capabilities */
|
|
66
|
+
toggleHeading1: boolean;
|
|
67
|
+
toggleHeading2: boolean;
|
|
68
|
+
toggleHeading3: boolean;
|
|
69
|
+
toggleBulletList: boolean;
|
|
70
|
+
toggleOrderedList: boolean;
|
|
71
|
+
toggleBlockquote: boolean;
|
|
72
|
+
toggleCodeBlock: boolean;
|
|
73
|
+
setTextAlignLeft: boolean;
|
|
74
|
+
setTextAlignCenter: boolean;
|
|
75
|
+
setTextAlignRight: boolean;
|
|
76
|
+
setTextAlignJustify: boolean;
|
|
77
|
+
insertHorizontalRule: boolean;
|
|
78
|
+
insertTable: boolean;
|
|
79
|
+
insertImage: boolean;
|
|
80
|
+
};
|
|
81
|
+
/** Current node context */
|
|
82
|
+
nodes: {
|
|
83
|
+
isTable: boolean;
|
|
84
|
+
isTableNodeSelected: boolean;
|
|
85
|
+
isTableCell: boolean;
|
|
86
|
+
isImage: boolean;
|
|
87
|
+
isBlockquote: boolean;
|
|
88
|
+
isCodeBlock: boolean;
|
|
89
|
+
isBulletList: boolean;
|
|
90
|
+
isOrderedList: boolean;
|
|
91
|
+
/** Headings */
|
|
92
|
+
h1: boolean;
|
|
93
|
+
h2: boolean;
|
|
94
|
+
h3: boolean;
|
|
95
|
+
/** Alignment */
|
|
96
|
+
alignLeft: boolean;
|
|
97
|
+
alignCenter: boolean;
|
|
98
|
+
alignRight: boolean;
|
|
99
|
+
alignJustify: boolean;
|
|
100
|
+
/** Table specific */
|
|
101
|
+
isTableHeaderRow: boolean;
|
|
102
|
+
isTableHeaderColumn: boolean;
|
|
103
|
+
/** Name of the active node at selection head */
|
|
104
|
+
activeNodeName: string | null;
|
|
105
|
+
};
|
|
106
|
+
/** Placeholder for custom extension states */
|
|
107
|
+
custom: Record<string, unknown>;
|
|
108
|
+
}
|
|
109
|
+
export declare const ATE_INITIAL_EDITOR_STATE: AteEditorStateSnapshot;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Observable } from "rxjs";
|
|
2
|
+
export interface AteImageData {
|
|
3
|
+
src: string;
|
|
4
|
+
alt?: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
width?: number;
|
|
7
|
+
height?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface AteImageUploadResult {
|
|
10
|
+
src: string;
|
|
11
|
+
name: string;
|
|
12
|
+
size: number;
|
|
13
|
+
type: string;
|
|
14
|
+
width?: number;
|
|
15
|
+
height?: number;
|
|
16
|
+
originalSize?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface AteResizeOptions {
|
|
19
|
+
width?: number;
|
|
20
|
+
height?: number;
|
|
21
|
+
maintainAspectRatio?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export interface AteImageUploadOptions {
|
|
24
|
+
quality?: number;
|
|
25
|
+
maxWidth?: number;
|
|
26
|
+
maxHeight?: number;
|
|
27
|
+
maxSize?: number;
|
|
28
|
+
allowedTypes?: string[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Context passed to the image upload handler containing information about the image
|
|
32
|
+
*/
|
|
33
|
+
export interface AteImageUploadContext {
|
|
34
|
+
/** Original file being uploaded */
|
|
35
|
+
file: File;
|
|
36
|
+
/** Width of the processed image */
|
|
37
|
+
width: number;
|
|
38
|
+
/** Height of the processed image */
|
|
39
|
+
height: number;
|
|
40
|
+
/** MIME type of the image */
|
|
41
|
+
type: string;
|
|
42
|
+
/** Base64 data URL of the processed image (after compression/resize) */
|
|
43
|
+
base64: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Result expected from a custom image upload handler.
|
|
47
|
+
* Must contain at least the `src` property with the image URL.
|
|
48
|
+
*/
|
|
49
|
+
export interface AteImageUploadHandlerResult {
|
|
50
|
+
/** URL of the uploaded image (can be a remote URL or any string) */
|
|
51
|
+
src: string;
|
|
52
|
+
/** Optional custom alt text */
|
|
53
|
+
alt?: string;
|
|
54
|
+
/** Optional custom title */
|
|
55
|
+
title?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Custom handler function for image uploads.
|
|
59
|
+
* Allows users to implement their own image storage logic (e.g., upload to S3, Cloudinary, etc.)
|
|
60
|
+
*
|
|
61
|
+
* Can return either a Promise or an Observable (Angular-friendly).
|
|
62
|
+
*
|
|
63
|
+
* @param context - Context containing the image file and metadata
|
|
64
|
+
* @returns Promise or Observable resolving to ImageUploadHandlerResult
|
|
65
|
+
*
|
|
66
|
+
* @example Using Promise (async/await)
|
|
67
|
+
* ```typescript
|
|
68
|
+
* uploadHandler: ImageUploadHandler = async (ctx) => {
|
|
69
|
+
* const formData = new FormData();
|
|
70
|
+
* formData.append('image', ctx.file);
|
|
71
|
+
* const result = await firstValueFrom(this.http.post<{url: string}>('/api/upload', formData));
|
|
72
|
+
* return { src: result.url };
|
|
73
|
+
* };
|
|
74
|
+
* ```
|
|
75
|
+
*
|
|
76
|
+
* @example Using Observable (Angular HttpClient)
|
|
77
|
+
* ```typescript
|
|
78
|
+
* uploadHandler: ImageUploadHandler = (ctx) => {
|
|
79
|
+
* const formData = new FormData();
|
|
80
|
+
* formData.append('image', ctx.file);
|
|
81
|
+
* return this.http.post<{url: string}>('/api/upload', formData).pipe(
|
|
82
|
+
* map(result => ({ src: result.url }))
|
|
83
|
+
* );
|
|
84
|
+
* };
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export type AteImageUploadHandler = (context: AteImageUploadContext) => Promise<AteImageUploadHandlerResult> | Observable<AteImageUploadHandlerResult>;
|
|
88
|
+
/**
|
|
89
|
+
* Interface dedicated to image upload configuration.
|
|
90
|
+
*/
|
|
91
|
+
export interface AteImageUploadConfig {
|
|
92
|
+
/** Callback function to handle upload (Promise or Observable) */
|
|
93
|
+
handler?: AteImageUploadHandler;
|
|
94
|
+
/** Compression quality (0 to 1) */
|
|
95
|
+
quality?: number;
|
|
96
|
+
/** Maximum allowed width in pixels */
|
|
97
|
+
maxWidth?: number;
|
|
98
|
+
/** Maximum allowed height in pixels */
|
|
99
|
+
maxHeight?: number;
|
|
100
|
+
/** Maximum allowed size in MB */
|
|
101
|
+
maxSize?: number;
|
|
102
|
+
/** Accepted file types (e.g., ['image/jpeg', 'image/png']) */
|
|
103
|
+
allowedTypes?: string[];
|
|
104
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/core";
|
|
2
|
+
/**
|
|
3
|
+
* Interface representing a single item in the slash commands menu.
|
|
4
|
+
*/
|
|
5
|
+
export interface AteSlashCommandItem {
|
|
6
|
+
title: string;
|
|
7
|
+
description: string;
|
|
8
|
+
icon: string;
|
|
9
|
+
keywords: string[];
|
|
10
|
+
command: (editor: Editor) => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Custom slash commands configuration.
|
|
14
|
+
*/
|
|
15
|
+
export interface AteCustomSlashCommands {
|
|
16
|
+
commands?: AteSlashCommandItem[];
|
|
17
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Editor } from "@tiptap/core";
|
|
2
|
+
/**
|
|
3
|
+
* Clés des boutons de la barre d'outils native
|
|
4
|
+
*/
|
|
5
|
+
export declare const ATE_TOOLBAR_KEYS: readonly ["bold", "italic", "underline", "strike", "code", "codeBlock", "superscript", "subscript", "highlight", "highlightPicker", "heading1", "heading2", "heading3", "bulletList", "orderedList", "blockquote", "alignLeft", "alignCenter", "alignRight", "alignJustify", "link", "image", "horizontalRule", "table", "undo", "redo", "clear", "textColor", "separator"];
|
|
6
|
+
export type AteToolbarKey = (typeof ATE_TOOLBAR_KEYS)[number];
|
|
7
|
+
export interface AteToolbarConfig extends Partial<Record<AteToolbarKey, boolean>> {
|
|
8
|
+
/**
|
|
9
|
+
* Boutons personnalisés à ajouter
|
|
10
|
+
*/
|
|
11
|
+
custom?: AteCustomToolbarItem[];
|
|
12
|
+
}
|
|
13
|
+
export interface AteCustomToolbarItem {
|
|
14
|
+
key: string;
|
|
15
|
+
label: string;
|
|
16
|
+
icon: string;
|
|
17
|
+
command: (editor: Editor) => void | Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Signal } from "@angular/core";
|
|
2
|
+
import { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
|
3
|
+
import { Decoration } from "@tiptap/pm/view";
|
|
4
|
+
import { Editor } from "@tiptap/core";
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/**
|
|
7
|
+
* Props that are injected into Angular NodeView components
|
|
8
|
+
*/
|
|
9
|
+
export interface AteAngularNodeViewProps {
|
|
10
|
+
editor: Editor;
|
|
11
|
+
node: ProseMirrorNode;
|
|
12
|
+
decorations: readonly Decoration[];
|
|
13
|
+
selected: boolean;
|
|
14
|
+
extension: unknown;
|
|
15
|
+
getPos: () => number | undefined;
|
|
16
|
+
updateAttributes: (attrs: Record<string, unknown>) => void;
|
|
17
|
+
deleteNode: () => void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Base abstract class for custom 'Angular Nodes'.
|
|
21
|
+
*
|
|
22
|
+
* Extend this class in your custom components to automatically receive TipTap editor
|
|
23
|
+
* properties (node attributes, selection state, etc.) as reactive Signals.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* @Component({
|
|
28
|
+
* selector: 'app-counter',
|
|
29
|
+
* template: `
|
|
30
|
+
* <div>
|
|
31
|
+
* <button (click)="increment()">Count: {{ node().attrs['count'] }}</button>
|
|
32
|
+
* </div>
|
|
33
|
+
* `
|
|
34
|
+
* })
|
|
35
|
+
* export class CounterComponent extends AteAngularNodeView {
|
|
36
|
+
* increment() {
|
|
37
|
+
* const count = this.node().attrs['count'] || 0;
|
|
38
|
+
* this.updateAttributes({ count: count + 1 });
|
|
39
|
+
* }
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare abstract class AteAngularNodeView {
|
|
44
|
+
/**
|
|
45
|
+
* The TipTap editor instance
|
|
46
|
+
*/
|
|
47
|
+
editor: Signal<Editor>;
|
|
48
|
+
/**
|
|
49
|
+
* The ProseMirror node
|
|
50
|
+
*/
|
|
51
|
+
node: Signal<ProseMirrorNode>;
|
|
52
|
+
/**
|
|
53
|
+
* Decorations applied to this node
|
|
54
|
+
*/
|
|
55
|
+
decorations: Signal<readonly Decoration[]>;
|
|
56
|
+
/**
|
|
57
|
+
* Whether the node is currently selected
|
|
58
|
+
*/
|
|
59
|
+
selected: Signal<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* The extension instance that created this node
|
|
62
|
+
*/
|
|
63
|
+
extension: Signal<unknown>;
|
|
64
|
+
/**
|
|
65
|
+
* Function to get the current position of this node in the document
|
|
66
|
+
*/
|
|
67
|
+
getPos: () => number | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Update the attributes of this node
|
|
70
|
+
*
|
|
71
|
+
* @param attrs - Partial attributes to update
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* this.updateAttributes({ count: 5, color: 'blue' });
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
updateAttributes: (attrs: Record<string, unknown>) => void;
|
|
79
|
+
/**
|
|
80
|
+
* Delete this node from the document
|
|
81
|
+
*/
|
|
82
|
+
deleteNode: () => void;
|
|
83
|
+
/** @internal */
|
|
84
|
+
private _writableSignals?;
|
|
85
|
+
/**
|
|
86
|
+
* Internal method to initialize the component with NodeView props.
|
|
87
|
+
* This is called by the AngularNodeViewRenderer.
|
|
88
|
+
*
|
|
89
|
+
* @internal
|
|
90
|
+
*/
|
|
91
|
+
_initNodeView(props: AteAngularNodeViewProps): void;
|
|
92
|
+
/**
|
|
93
|
+
* Internal method to update the component when the node changes.
|
|
94
|
+
* This is called by the AngularNodeViewRenderer.
|
|
95
|
+
*
|
|
96
|
+
* @internal
|
|
97
|
+
*/
|
|
98
|
+
_updateNodeView(node: ProseMirrorNode, decorations: readonly Decoration[]): void;
|
|
99
|
+
/**
|
|
100
|
+
* Internal method to update the selection state.
|
|
101
|
+
* This is called by the AngularNodeViewRenderer.
|
|
102
|
+
*
|
|
103
|
+
* @internal
|
|
104
|
+
*/
|
|
105
|
+
_selectNodeView(): void;
|
|
106
|
+
/**
|
|
107
|
+
* Internal method to update the deselection state.
|
|
108
|
+
* This is called by the AngularNodeViewRenderer.
|
|
109
|
+
*
|
|
110
|
+
* @internal
|
|
111
|
+
*/
|
|
112
|
+
_deselectNodeView(): void;
|
|
113
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AteAngularNodeView, never>;
|
|
114
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<AteAngularNodeView, never, never, {}, {}, never, never, false, never>;
|
|
115
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Injector } from "@angular/core";
|
|
2
|
+
import { Node } from "@tiptap/core";
|
|
3
|
+
import { RegisterAngularComponentOptions } from "./ate-node-view.models";
|
|
4
|
+
/**
|
|
5
|
+
* Factory to transform an Angular component into a TipTap Node extension.
|
|
6
|
+
* Supports both "TipTap-Aware" and "Standard" modes.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export declare function createAngularComponentExtension<T = unknown>(injector: Injector, options: RegisterAngularComponentOptions<T>): Node;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Injector, Type } from "@angular/core";
|
|
2
|
+
import { NodeConfig } from "@tiptap/core";
|
|
3
|
+
import { Node as ProseMirrorNode } from "@tiptap/pm/model";
|
|
4
|
+
/**
|
|
5
|
+
* Common options for rendering any Angular component as a TipTap NodeView
|
|
6
|
+
*/
|
|
7
|
+
export interface AteComponentRenderOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Angular injector to use for creating the component
|
|
10
|
+
*/
|
|
11
|
+
injector: Injector;
|
|
12
|
+
/**
|
|
13
|
+
* Additional inputs to pass to the component
|
|
14
|
+
*/
|
|
15
|
+
inputs?: Record<string, unknown>;
|
|
16
|
+
/**
|
|
17
|
+
* Custom wrapper element tag (default: 'div')
|
|
18
|
+
*/
|
|
19
|
+
wrapperTag?: string;
|
|
20
|
+
/**
|
|
21
|
+
* CSS classes to add to the wrapper element
|
|
22
|
+
*/
|
|
23
|
+
wrapperClass?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Whether the node should be treated as an atom (not editable)
|
|
26
|
+
* Default: true
|
|
27
|
+
*/
|
|
28
|
+
atom?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Enables editable content for <ng-content>.
|
|
31
|
+
* If true, TipTap will treat the component's content as editable.
|
|
32
|
+
* @default false
|
|
33
|
+
*/
|
|
34
|
+
editableContent?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Optional CSS selector to target an internal element of the component as the editable area.
|
|
37
|
+
*/
|
|
38
|
+
contentSelector?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Type of content allowed in the editable area.
|
|
41
|
+
*/
|
|
42
|
+
contentMode?: "block" | "inline";
|
|
43
|
+
/**
|
|
44
|
+
* Whether to ignore mutations in the component's DOM.
|
|
45
|
+
* If true, TipTap won't try to sync changes from the component's DOM back to the editor state.
|
|
46
|
+
* @default true
|
|
47
|
+
*/
|
|
48
|
+
ignoreMutation?: boolean | ((mutation: MutationRecord | {
|
|
49
|
+
type: "selection";
|
|
50
|
+
target: Node;
|
|
51
|
+
}) => boolean);
|
|
52
|
+
/**
|
|
53
|
+
* Callback called when an Output event is emitted by the component.
|
|
54
|
+
*/
|
|
55
|
+
onOutput?: (outputName: string, value: unknown) => void;
|
|
56
|
+
/**
|
|
57
|
+
* Callback called when the node is updated.
|
|
58
|
+
*/
|
|
59
|
+
onUpdate?: (node: ProseMirrorNode) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Callback called when the component is destroyed.
|
|
62
|
+
*/
|
|
63
|
+
onDestroy?: () => void;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Unified configuration for registering an Angular component as an interactive 'Angular Node'.
|
|
67
|
+
* This provides high-level options to map Angular component logic (inputs, outputs, lifestyle)
|
|
68
|
+
* directly to TipTap's document structure.
|
|
69
|
+
*/
|
|
70
|
+
export interface RegisterAngularComponentOptions<T = unknown> {
|
|
71
|
+
/**
|
|
72
|
+
* The Angular component to register
|
|
73
|
+
*/
|
|
74
|
+
component: Type<T>;
|
|
75
|
+
/**
|
|
76
|
+
* Unique name for the TipTap node
|
|
77
|
+
*/
|
|
78
|
+
name?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Default inputs (for standard components)
|
|
81
|
+
*/
|
|
82
|
+
defaultInputs?: Record<string, unknown>;
|
|
83
|
+
/**
|
|
84
|
+
* TipTap attributes (for TipTap-aware components)
|
|
85
|
+
*/
|
|
86
|
+
attributes?: Record<string, {
|
|
87
|
+
default?: unknown;
|
|
88
|
+
parseHTML?: (element: HTMLElement) => unknown;
|
|
89
|
+
renderHTML?: (attributes: Record<string, unknown>) => Record<string, unknown> | null;
|
|
90
|
+
}>;
|
|
91
|
+
/**
|
|
92
|
+
* CSS selector for the editable area inside the component
|
|
93
|
+
*/
|
|
94
|
+
contentSelector?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Content mode for the editable area
|
|
97
|
+
*/
|
|
98
|
+
contentMode?: "block" | "inline";
|
|
99
|
+
/**
|
|
100
|
+
* Enable editable content via <ng-content> or contentSelector
|
|
101
|
+
* @default false
|
|
102
|
+
*/
|
|
103
|
+
editableContent?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Node group (block or inline)
|
|
106
|
+
* @default 'block'
|
|
107
|
+
*/
|
|
108
|
+
group?: "block" | "inline";
|
|
109
|
+
/**
|
|
110
|
+
* Is the node draggable?
|
|
111
|
+
* @default true
|
|
112
|
+
*/
|
|
113
|
+
draggable?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Whether to ignore mutations in the component's DOM.
|
|
116
|
+
* @default true
|
|
117
|
+
*/
|
|
118
|
+
ignoreMutation?: boolean | ((mutation: MutationRecord | {
|
|
119
|
+
type: "selection";
|
|
120
|
+
target: Node;
|
|
121
|
+
}) => boolean);
|
|
122
|
+
/**
|
|
123
|
+
* Custom HTML attributes for the wrapper
|
|
124
|
+
*/
|
|
125
|
+
HTMLAttributes?: Record<string, unknown>;
|
|
126
|
+
/**
|
|
127
|
+
* Custom parseHTML rules
|
|
128
|
+
*/
|
|
129
|
+
parseHTML?: NodeConfig["parseHTML"];
|
|
130
|
+
/**
|
|
131
|
+
* Custom renderHTML function
|
|
132
|
+
*/
|
|
133
|
+
renderHTML?: NodeConfig["renderHTML"];
|
|
134
|
+
/**
|
|
135
|
+
* Callback called when an Output event is emitted by the component.
|
|
136
|
+
*/
|
|
137
|
+
onOutput?: (outputName: string, value: unknown) => void;
|
|
138
|
+
}
|